¿Cuál es la diferencia o el valor de estos estilos de codificación de bloques en Ruby?


¿Qué estilo se prefiere? ¿Hay una buena razón para uno contra el otro?

Gracias de antemano!

1) cmds.each do |cmd|
   end

2) cmds.each { |cmd|
   }

Código de ejemplo:

cmds = [ "create", "update", "list", "help" ]

# Block style one
#
cmds.each do |cmd|
  puts "loop1, cmd: #{cmd}"
end

# Block style two
#
cmds.each { |cmd|
  puts "loop2, cmd: #{cmd}"
}
Author: Mohsen Nosratinia, 2009-02-10

7 answers

El equipo de rails y muchos otros rubistas prefieren usar llaves para bloques de una línea y do...end para bloques de varias líneas.

La única diferencia funcional entre los dos es que la precedencia de un bloque do...end es menor que la de un bloque {...}.

 37
Author: Gordon Wilson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-02-10 16:38:53

De acuerdo con el libro "Pico" (estoy mirando la 2da edición aquí), Gordon es correcto: la única diferencia es la precedencia:

P. 356 (mi cursiva):

Las llaves tienen una prioridad alta; do tiene una baja precedencia. Si el método la invocación tiene parámetros que no son entre paréntesis, el paréntesis forma de un bloque se unirá a la última parámetro, no a la general invocación. El formulario do se enlazará a la invocación.

Véase también p. 168 para un ejemplo.

 21
Author: Mike Woodhouse,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-07-26 16:05:25

Las dos formas son equivalentes.

El estilo recomendado es usar las llaves para bloques de una línea y usar el "do"-"end" para bloques de varias líneas.

Editar: Austin Ziegler señaló (en el comentario a continuación) que las dos formas tienen niveles de precedencia diferentes: Las llaves tienen mayor precedencia. Por lo tanto, cuando se llama a un método sin paréntesis, un bloque encerrado en {} se enlazará al último argumento en lugar del método que llama.

Lo siguiente ejemplo fue sugerido por Austin:

def foo
    yield
end

puts foo { "hello" }

puts foo do
    "hello"
end

El primer "puts" imprime "hola": a foo se le llama devolviendo "hola" que es el argumento para puts.

La segunda falla con un error:

in `foo': no block given

Ya que en este caso el bloque do-end se une al método puts.

Gracias de nuevo a Austin por aclarar esto.

 13
Author: nimrodm,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:10:31

La respuesta de Gordon es "the Ruby Way", y aunque es una práctica común poner una línea entre llaves, no es necesario.

También tenga en cuenta la facilidad con la que uno puede actuar sobre el valor resultante:

cmds.each do |cmd| cmd.upcase! end.sort

# Now, cmds = ["CREATE", "HELP", "LIST", "UPDATE"]

Aunque es posible que ya vea cómo {} es más legible aquí, y por lo tanto preferido si alguien más va a ver su código:

cmds.each { |cmd| cmd.upcase! }.sort
 10
Author: nerdz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-02-10 17:02:39

Muy a menudo, el estilo 1 se usa para bloques de varias líneas y el estilo 2 se usa para bloques de una línea.

La sintaxis do…end se parece mucho a otras estructuras de control de Ruby (if, def, class), por lo que usar eso para bloques mantiene la apariencia de su código consistente y claro. Pero no funciona bien para los de una sola línea, por lo que la versión brackets es la preferida allí.

 2
Author: Chuck,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-02-10 16:31:49

Convencionalmente, usar {} está reservado para bloques de una sola línea, mientras que do...end es para bloques de varias líneas.

Debido a que {} no se usan en Ruby tan a menudo como en otros lenguajes como C++ o Javascript, usar do...end cuando se le da la oportunidad en lugar de {} puede ayudar a que su código sea más legible para otros Rubistas.

Tenga en cuenta que {} tiene precedencia sobre do...end.

 1
Author: Charles,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-07-23 21:31:23

No creo que realmente importe - es solo una elección personal estética. Algunas personas prefieren usar la versión do...end cuando el bloque necesita varias líneas y la versión {...} cuando todo está en una línea.

 0
Author: James Mead,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-02-10 16:27:22