Blocco multilinea ruby senza fine

Sono un principiante in Ruby, quindi mi dispiace chiedere una cosa così semplice, ma c’è qualcosa di sbagliato in questo codice –

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

o

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

Funziona abbastanza bene, ma la maggior parte degli esempi di codice che vedo usano la syntax di

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

è solo la convenzione a usare solo parentesi graffe per le singole affermazioni? Venendo da C / C # la prima sembra più naturale per me, ma quando a Roma!

C’è una sottile differenza tra le due syntax. { } hanno precedenza più alta di quanto do ... end . Quindi, quanto segue passerà la bar e un blocco al metodo foo :

 foo bar do ... end 

mentre quanto segue passerà un blocco a bar , e il risultato di ciò a foo :

 foo bar { ... } 

Quindi i tuoi esempi agiranno allo stesso modo. Tuttavia, se hai lasciato le parentesi su:

 > 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 

Quindi, { } è più probabile che ti raggiungano se lasci le parentesi in Ruby, che è abbastanza comune; per questo motivo, e poiché le condizioni condizionali di Ruby e gli altri costrutti di controllo usano tutti end come delimitatori, le persone solitamente usano do ... end per i blocchi di codice a più righe che si trovano alla fine di un’istruzione.

Tuttavia, { } è spesso usato in luoghi dove do ... end sarebbe ingombrante, ad esempio, se si concatenano insieme diversi metodi che prendono dei blocchi. Questo può consentire di scrivere brevi blocchi di una riga che possono essere utilizzati come parte di una catena di metodi.

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

Ecco un esempio per illustrare questa differenza:

 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 

È solo una convenzione.

C’è senza soluzione di continuità . Dal README :

Python ti permette di segnalare la fine di un blocco di codice con indentazione. Ruby soffre di un terminatore di blocco estremamente prolisso e noioso, “end”. Proprio come i Lisps finiscono con dozzine di parenti ravvicinati, i file di Ruby che usano moduli e classi finiscono pesantemente con una pletora di “fini” che proprio non sono necessari.

Scrivi un file Ruby, ma salta tutti i “fini”. Allinea i blocchi di codice come in Python. Quindi chiamalo ‘your_file.rbe’, richiedi ‘seamless’ e richiedi ‘your_file’. Senza soluzione di continuità fa il resto.

Questo dovrebbe mai vedere un uso diffuso? Non lo so. Ma è piuttosto divertente!