while sintaxis for ejemplos bucle ruby loops syntax foreach flow-control

sintaxis - Ruby: ¿Cuál es la diferencia entre un bucle for y cada bucle?



iteration ruby (4)

Posible duplicado:
para vs cada uno en Ruby

Digamos que tenemos una matriz, como

sites = %w[stackoverflow stackexchange serverfault]

Cuál es la diferencia entre

for x in sites do puts x end

y

sites.each do |x| puts x end

?

Parecen hacer exactamente lo mismo, para mí, y la sintaxis del bucle for es más clara para mí. ¿Hay una diferencia? ¿En qué situaciones sería esto un gran problema?


Hay una diferencia sutil con respecto al alcance, pero recomendaría entenderlo bien, ya que revela algunos de los aspectos importantes de Ruby.

for es una construcción de sintaxis, algo similar a if . Independientemente de lo que defina en el bloque, también se definirá después for :

sites = %w[ stackexchange serverfault] #=> ["", "stackexchange", "serverfault"] for x in sites do puts x end stackexchange serverfault #=> ["", "stackexchange", "serverfault"] x #=> "serverfault"

Por otro lado, each es un método que recibe un bloque. Block introduce un nuevo ámbito léxico, por lo que cualquier variable que introduzca en él, no estará allí después de que el método finalice:

sites.each do |y| puts y end stackexchange serverfault #=> ["", "stackexchange", "serverfault"] y NameError: undefined local variable or method `y'' for #<Object:0x855f28 @hhh="hello"> from (irb):9 from /usr/bin/irb:12:in `<main>''

Recomendaría olvidar for completo, ya que el uso de each es idiomático en Ruby para atravesar enumerables. También reconoce mejor el paradigma de la programación funcional al disminuir las posibilidades de efectos secundarios.


La respuesta CBZ es correcta pero incompleta ya que hay una diferencia en el comportamiento entre 1.8.X y 1.9.X:

1.9.2 IRB:

ruby-1.9.2-p180 :001 > x = [1,2,3,4,5] => [1, 2, 3, 4, 5] ruby-1.9.2-p180 :002 > y = ["a","b"] => ["a", "b"] ruby-1.9.2-p180 :003 > x.each do |y| ruby-1.9.2-p180 :004 > p y ruby-1.9.2-p180 :005?> end 1 2 3 4 5 => [1, 2, 3, 4, 5] ruby-1.9.2-p180 :006 > y => ["a", "b"]

1.8.7 IRB:

ree-1.8.7-2011.03 :001 > x = [1,2,3,4,5] => [1, 2, 3, 4, 5] ree-1.8.7-2011.03 :002 > y = ["a","b"] => ["a", "b"] ree-1.8.7-2011.03 :003 > x.each do |y| ree-1.8.7-2011.03 :004 > p y ree-1.8.7-2011.03 :005?> end 1 2 3 4 5 => [1, 2, 3, 4, 5] ree-1.8.7-2011.03 :006 > y => 5


La respuesta CBZ es correcta. Para ilustrar esto, mira este ejemplo:

ruby-1.9.2-p180 :001 > a = %w{ blah lah kah } => ["blah", "lah", "kah"] ruby-1.9.2-p180 :002 > x = 1 => 1 ruby-1.9.2-p180 :003 > for x in a do ruby-1.9.2-p180 :004 > puts x ruby-1.9.2-p180 :005?> end blah lah kah => ["blah", "lah", "kah"] ruby-1.9.2-p180 :006 > x => "kah" ruby-1.9.2-p180 :007 > x=1 => 1 ruby-1.9.2-p180 :008 > a.each do |x| ruby-1.9.2-p180 :009 > puts x ruby-1.9.2-p180 :010?> end blah lah kah => ["blah", "lah", "kah"] ruby-1.9.2-p180 :011 > x => 1


sites.each alcance x dentro del bloque, mientras que for reutilizará x si se declara fuera del bloque. En general, es mejor usar each , minimiza los efectos secundarios sobre grandes cuerpos de código.