2014-05-24 27 views
5

In Ruby sto cercando di capire tra i metodi to_enum e enum_for. Prima di me la mia domanda, ho fornito alcuni esempi di codice e due esempi per aiutare w/context.Differenze tra [1,2,3] .to_enum e [1,2,3] .enum_for in Ruby

codice

Esempio:

# replicates group_by method on Array class 
class Array 
    def group_by2(&input_block) 
    return self.enum_for(:group_by2) unless block_given? 
    hash = Hash.new {|h, k| h[k] = [] } 
    self.each { |e| hash[ input_block.call(e) ] << e } 
    hash 
    end 
end 

Esempio # 1:

irb (main)> puts [1,2,3].group_by2.inspect 
=> #<Enumerator: [1, 2, 3]:group_by2> 

Nell'esempio # 1: Chiamata group_by sull'array [1,2,3], senza passare in un blocco, restituisce un enumeratore generata con il comando self.enum_for(:group_by_2).

Esempio # 2

irb (main)> puts [1,2,3].to_enum.inspect 
=> #<Enumerator: [1, 2, 3]:each> 

Nell'esempio # 2, l'enumeratore viene generato chiamando il metodo to_enum sulla matrice [1,2,3]

Domanda:

fare enumeratori genera negli esempi 1 e 2, si comportano diversamente in alcun modo? Posso vedere dalle uscite ispezionate che mostrano etichette leggermente diverse, ma posso trovare qualche differenza nel comportamento degli enumeratori.

# Output for example #1 
#<Enumerator: [1, 2, 3]:each> # label reads ":each" 

# Output for example #2 
#<Enumerator: [1, 2, 3]:group_by2> # label reads ":group_by2" 

risposta

10
p [1, 2, 3].to_enum 
p [1, 2, 3].enum_for 

--output:-- 

#<Enumerator: [1, 2, 3]:each> 
#<Enumerator: [1, 2, 3]:each> 

Dalla documentazione:

to_enum

di creare un nuovo enumeratore che enumerare con il metodo invitando obj, passando args se presente.

...

enum_for

di creare un nuovo enumeratore che enumerare con il metodo invitando obj, passando args se presente.

rubino è un linguaggio che ha spesso nomi di metodi che sono sinonimi.

Followup domanda:

significa il simbolo nel comando [1,2,3] .to_enum (: foo) servono a uno scopo, altro che sostituire: ciascuno con: foo nell'output ?

Sì. Di default, ruby ​​collega l'enumeratore al metodo each() del ricevente.Alcune classi non hanno un metodo di ciascuno(), per esempio String:

str = "hello\world" 
e = str.to_enum 
puts e.next 

--output:-- 
1.rb:3:in `next': undefined method `each' for "helloworld":String (NoMethodError) 
    from 1.rb:3:in `<main> 

to_enum() consente di specificare il metodo che si desidera l'enumeratore da utilizzare:

str = "hello\nworld" 
e = str.to_enum(:each_line) 
puts e.next 

--output:-- 
hello 

Ora, supporti avere l'array [1, 2, 3] e si desidera creare un enumeratore per l'array. Un array ha un metodo each(), ma invece di creare un enumeratore con each(), che restituirà ciascuno degli elementi nell'array, quindi terminerà; vuoi creare un enumeratore che ricomincia dall'inizio della matrice quando raggiunge la fine?

e = [1, 2, 3].to_enum(:cycle) 

10.times do 
    puts e.next() 
end 

--output:-- 
1 
2 
3 
1 
2 
3 
1 
2 
3 
1 
+0

@ 7stud grazie. Volevo solo essere sicuro che non mi mancasse qualcosa. – amorphid

+2

@amorphid, I documenti ruby ​​erano abbastanza buoni nel dire: "Questo metodo è un sinonimo del metodo A. Vedi la descrizione per il metodo A." Preferirei vedere questo riferimento piuttosto che una descrizione duplicata. – 7stud

+0

Ho appena riletto il tuo esempio e solo ora mi sono reso conto che si può anche fare '[1,2,3] .to_enum (: foo)', che restituisce '# ' . Se l'avessi capito, la mia domanda sarebbe stata semplicemente => Il simbolo nel comando '[1,2,3] .to_enum (: foo)' ha uno scopo, diverso dalla sostituzione di ': each' con': foo' nell'output? La [docs per la classe Enumerator] (http://www.ruby-doc.org/core-2.1.2/Enumerator.html) non dice nulla a riguardo, almeno non che io possa vedere. – amorphid