with sintaxis loop iterators index for array ruby loops foreach iteration each

sintaxis - "Para" vs "cada uno" en Ruby



ruby map (7)

Acabo de tener una pregunta rápida con respecto a los bucles en Ruby. ¿Hay alguna diferencia entre estas dos formas de iterar a través de una colección?

# way 1 @collection.each do |item| # do whatever end # way 2 for item in @collection # do whatever end

Solo me pregunto si estos son exactamente iguales o si tal vez hay una diferencia sutil (posiblemente cuando @collection es nulo).



Esta es la única diferencia:

cada:

irb> [1,2,3].each { |x| } => [1, 2, 3] irb> x NameError: undefined local variable or method `x'' for main:Object from (irb):2 from :0

para:

irb> for x in [1,2,3]; end => [1, 2, 3] irb> x => 3

Con el bucle for , la variable del iterador sigue viva después de que el bloque está listo. Con each bucle, no es así, a menos que ya se haya definido como una variable local antes de que se inicie el bucle.

Aparte de eso, for es solo azúcar de sintaxis para each método.

Cuando @collection es nil ambos loops arrojan una excepción:

Excepción: variable local indefinida o método `@collection ''para main: Object


Hasta donde yo sé, usar bloques en lugar de estructuras de control en lenguaje es más idiomático.


Nunca lo use, puede causar errores.

¡La diferencia es sutil pero puede causar errores tremendos!

No se deje engañar, no se trata de un código idiomático o de problemas de estilo. Se trata de evitar errores casi imposibles de detectar en el código de producción. La implementación de Ruby for tiene un defecto serio y no debería usarse. Siempre use each bucle, nunca lo use for bucle.

Aquí hay un ejemplo donde for introducir un error,

class Library def initialize @ary = [] end def method_with_block(&block) @ary << block end def method_that_uses_these_blocks @ary.map(&:call) end end lib = Library.new for n in %w{foo bar quz} lib.method_with_block { n } end puts lib.method_that_uses_these_blocks

Huellas dactilares

quz quz quz

Usar %w{foo bar quz}.each { |n| ... } %w{foo bar quz}.each { |n| ... } impresiones

foo bar quz

¿Por qué?

En un bucle for la variable n se define una sola vez y luego esa única definición se usa para todas las iteraciones. Por lo tanto, cada bloque se refiere a la misma n que tiene un valor de quz en el momento en que termina el ciclo. ¡Error!

En each bucle se define una nueva variable n para cada iteración, por ejemplo, arriba de la variable n se define tres veces por separado. Por lo tanto, cada bloque se refiere a una n separada con los valores correctos.


Parece que no hay diferencia, for each debajo.

$ irb >> for x in nil >> puts x >> end NoMethodError: undefined method `each'' for nil:NilClass from (irb):1 >> nil.each {|x| puts x} NoMethodError: undefined method `each'' for nil:NilClass from (irb):4

Como dice Bayard, cada uno es más idiomático. Oculta más de usted y no requiere funciones especiales de idioma. Comentario de Telémaco

for .. in .. establece el iterador fuera del alcance del ciclo, por lo

for a in [1,2] puts a end

deja a definido después de que el ciclo haya terminado. Donde como each no lo hace. Cuál es otra razón a favor de usar each , porque la variable de la temperatura vive un período más corto.


Tu primer ejemplo,

@collection.each do |item| # do whatever end

es más idiomático Si bien Ruby admite construcciones de bucle como for y while , generalmente se prefiere la sintaxis de bloque.

Otra diferencia sutil es que cualquier variable que declare dentro de un bucle for estará disponible fuera del bucle, mientras que las que están dentro de un bloque de iterador son efectivamente privadas.