2010-07-27 5 views
13

Sto imparando Ruby e ROR in questo momento, e mi sono imbattuto in questo:Qual è il punto di "x in y" in Ruby?

<% for post in @posts %> 

nel Rails guide. Avevo capito che il modo idiomatico per fare questo in Ruby è con:

<% @posts.each do |post| %> 

Se c'è una differenza, allora che cosa è? E se non c'è una differenza, non sarebbe meglio per le persone di Rails spingere i propri idiomi Ruby (piuttosto che questo, che per me sembra più pitonico)?

Edit: ho appena trovato due spiegazioni contrastanti di questo: Tutorials Point dice che sono gli stessi, tranne "un ciclo for non crea un nuovo ambito per le variabili locali", mentre CS.Auckland.ac.NZ dice for è solo sintattico zucchero per l'equivalente .each.

Edit2: La for ... in in questione era per la index.html.erb generata in app/views/posts da script/generate scaffold. Ho eseguito un controllo rapido e ora viene generata la sintassi .each. Immagino che parte della guida sia stata scritta in uno stadio precedente dello sviluppo delle rotaie quando lo scaffold ha generato for ... in.

Edit3: ora posso confermare che for x in y è stato utilizzato in Rails 2.2.2, ma 2.3.8 sta usando y.each do |x|. Solo per quello che sai.

risposta

21

La pagina del tutorial point è corretta, for equivale a each tranne per la differenza di ambito. Ecco una dimostrazione:

arr = [1,2,3] 
arr.each do |x| 
    last = x 
end 
last # NameError 

vs.

arr = [1,2,3] 
for x in arr 
    last = x 
end 
last #=> 3 

Se si vuole farlo funzionare utilizzando each, è necessario fare last = nil prima del ciclo. Questo è, come sottolineato dal link, perché i blocchi avviano un nuovo ambito mentre for no.

Si noti tuttavia che questo raramente fa una differenza pratica e poche persone ne sono consapevoli.

Quando le persone usano il for in ruby ​​è molto spesso perché è quello che sono abituati a venire da altre lingue - non a causa di eventuali differenze tra for e each.

+0

Grazie! Esattamente quello che stavo cercando. Questo mi riporta al punto originale, per cui il team di Rails (o almeno chi ha scritto la guida introduttiva) dovrebbe seguire la sintassi 'for ... in'? – Skilldrick

+2

C'è un sacco di persone che imparano i binari senza aver imparato prima il rubino. Suppongo che la guida sia scritta in uno stile che ha lo scopo di sembrare familiare alle persone che provengono da altre lingue. – sepp2k

+0

Una differenza correlata tra i due che non è evidente solo da quell'esempio: 'a = []; per x in [1,2,3,4]; una fine << proc {x}; map (&: call) 'dà' [4,4,4,4] 'mentre l'equivalente con' each' darebbe '[1,2,3,4]' perché 'each' introduce una nuova legatura' x' con ogni iterazione. – Chuck

0

Il fatto è che il primo esempio (for post in @posts) sembra più "procedurale", mentre il secondo (@posts.each do |post|) sembra più "funzionale". Sfortunatamente, il modo procedurale per leggere il codice è ancora considerato più popolare, più chiaro e meno "geek". Ecco perché, forse, molti preferirebbero il modo "nativo" di iterare attraverso i contenitori.

Se sembra pitonico (non sono sicuro che sia vero), allora può essere considerato ancora migliore, dal momento che migliora l'accessibilità di Rails da parte degli sviluppatori che provengono da altre piattaforme.

Personalmente, mi piacerebbe rubino e modi "funzionali" per essere spinti. Ma i motivi sopra esposti dimostrano che può essere fatto in entrambi i modi.

+0

Dico che sembra pitone perché 'for ... in' è il modo standard per scorrere in Python. – Skilldrick

+1

@skill, così come è un modo standard di iterare in altri linguaggi (sintassi Perl obsoleta, ad esempio). È anche il modo * naturale * (nel senso in cui gli esseri umani) di iterare attraverso qualsiasi raccolta. –

+0

sì, capisco cosa intendi. Non stavo necessariamente dicendo che stavano copiando Python, solo che somigliava più a Python. – Skilldrick

0

Un giorno stavo sviluppando la funzionalità di generare report PDF per il sito Web su cui stavo lavorando.

Il plug-in che stavo usando aveva molte limitazioni. Queste limitazioni mi hanno imposto di produrre la soluzione che era molto imperativa e procedurale. Stavo usando costruzioni come while o for solo per enfatizzare questo stile di programmazione.

In effetti, questa era l'unica situazione in cui ho usato quelle parole chiave in ruby.

0

È possibile utilizzare for x in y se si sta tentando di eseguire la profilazione di ruby ​​e la versione di ruby-prof non dispone di method elimination.

0

più Una cosa su for x in y è che si può fare for i in 1..5 che funzionerà come un normale ciclo for, a partire da i = 1 e passando attraverso i = 5.

La cosa a portata di mano di questo è che è possibile utilizzare una vasta gamma come 3..8 o x..y, non si è bloccato a partire da zero, che si sarebbe utilizzando n.times metodo.

+0

Non 1.upto (5) .each {| x | #qualcosa} prendersi cura di questo? – graydot

+0

@jeba ya lo farebbe. Sono relativamente nuovo al rubino, quindi non l'avevo mai visto prima. Quindi grazie! Imparo qualcosa di nuovo ogni giorno! –

+2

Puoi anche fare '(1..5) .each' – Skilldrick