Bloque multilínea Ruby sin fin

Soy un principiante en Ruby, así que lamento preguntar algo tan simple, pero ¿hay algún problema con este código?

3.upto(9) { print "Hello" puts " World" } 

o

 3.upto(9) { |n| print "Hello " puts n } 

Funciona bastante bien, pero la mayoría de las muestras de código que veo utilizan la syntax de

 3.upto(9) do |n| print "Hello " puts n end 

¿Es solo la convención usar solo llaves para declaraciones individuales? Viniendo de C / C #, el primero me parece más natural, ¡pero cuando estoy en Roma!

Hay una sutil diferencia entre las dos syntax. { } son de mayor precedencia que do ... end . Por lo tanto, lo siguiente pasará la bar y un bloque al método foo :

 foo bar do ... end 

mientras que lo siguiente pasará de bloque a bar , y el resultado de eso es foo :

 foo bar { ... } 

Entonces tus ejemplos actuarán de la misma manera. Sin embargo, si dejó los paréntesis desactivados:

 > 3.upto 9 { puts "Hi" } SyntaxError: compile error (irb):82: syntax error, unexpected '{', expecting $end 3.upto 9 { ^ from (irb):82 from :0 > 3.upto 9 do puts "Hi" end Hi Hi Hi Hi Hi Hi Hi => 3 

Entonces, { } es más probable que te atrape si dejas paréntesis en Ruby, que es bastante común; por esta razón, y debido a que los condicionales de Ruby y otras construcciones de control usan end como delimitador, las personas usualmente usan do ... end para bloques de código multilínea que se encuentran al final de un enunciado.

Sin embargo, { } se usa con frecuencia en lugares donde do ... end sería engorroso, por ejemplo, si está encadenando varios métodos juntos que toman bloques. Esto puede permitirle escribir pequeños bloques de una línea que pueden usarse como parte de una cadena de métodos.

 > [1,2,3].sort{|x,y| y< =>x}.map{|x| x+1} => [4, 3, 2] 

Aquí hay un ejemplo para ilustrar esta diferencia:

 def foo arg if block_given? puts "Block given to foo" yield arg else puts "No block given to foo" arg end end def bar if block_given? puts "Block given to bar" yield "Yielded from bar" else puts "No block given to bar" end "Returned from bar" end irb(main):077:0> foo bar { |arg| puts arg } Block given to bar Yielded from bar No block given to foo => "Returned from bar" irb(main):078:0> foo bar do |arg| puts arg end No block given to bar Block given to foo Returned from bar => nil 

Es solo una convención.

Hay sin costura . Del README :

Python le permite señalar el final de un bloque de código con sangría. Ruby sufre de un terminador de bloque extremadamente prolijo y tedioso, “final”. Al igual que los Lisps terminan con docenas de parientes cercanos, los archivos de Ruby que usan módulos y clases terminan con una plétora de “extremos” que simplemente no son necesarios.

Escribe un archivo Ruby, pero salta todos los “extremos”. Alinea tus bloques de código como en Python. Entonces solo llámalo ‘your_file.rbe’, requiere ‘seamless’ y necesita ‘your_file’. Inconsútil hace el rest.

¿Debería esto alguna vez ver un uso generalizado? No lo sé. ¡Pero es muy divertido!