L'OP ha scritto
Mi sembra strano che il costrutto di cui sopra non produca il risultato atteso. Qual è la ragione per questo? Quali sono le situazioni in cui questo comportamento è ragionevole?
non "Si può fare?" ma per rispondere alla domanda che non è stata posta prima di arrivare alla domanda che è stata effettivamente posta:
$ irb
2.1.5 :001 > (0..4)
=> 0..4
2.1.5 :002 > (0..4).each { |i| puts i }
0
1
2
3
4
=> 0..4
2.1.5 :003 > (4..0).each { |i| puts i }
=> 4..0
2.1.5 :007 > (0..4).reverse_each { |i| puts i }
4
3
2
1
0
=> 0..4
2.1.5 :009 > 4.downto(0).each { |i| puts i }
4
3
2
1
0
=> 4
Poiché si afferma che reverse_each crei un intero array, downto sarà chiaramente più efficiente. Il fatto che un progettista di linguaggi possa anche prendere in considerazione l'implementazione di cose del genere si lega alla risposta alla domanda effettiva come posta.
Per rispondere alla domanda come effettivamente posta ...
Il motivo è perché Ruby è un linguaggio infinitamente sorprendente. Alcune sorprese sono piacevoli, ma c'è molto comportamento che è decisamente rotto. Anche se alcuni di questi esempi seguenti vengono corretti dalle versioni più recenti, ce ne sono molti altri e rimangono come accuse nella mentalità del design originale:
nil.to_s
.to_s
.inspect
risultati in "" ma
nil.to_s
# .to_s # Don't want this one for now
.inspect
risultati in
syntax error, unexpected '.', expecting end-of-input
.inspect
^
Probabilmente ti aspetteresti che << e push siano gli stessi per l'aggiunta agli array, ma
a = []
a << *[:A, :B] # is illegal but
a.push *[:A, :B] # isn't.
Probabilmente ti aspetteresti che 'grep' si comporti come il suo equivalente a riga di comando Unix, ma === non corrisponde a = ~, nonostante il suo nome.
$ echo foo | grep .
foo
$ ruby -le 'p ["foo"].grep(".")'
[]
Vari metodi sono inaspettatamente alias l'uno per l'altro, quindi devi imparare più nomi per la stessa cosa, ad esempio find
e detect
, anche se ti piacciono la maggior parte degli sviluppatori e usi solo l'uno o l'altro. Molto lo stesso vale per size
, count
e length
, tranne per le classi che definiscono ogni diverso, o non definiscono uno o due affatto.
A meno che qualcuno non abbia implementato qualcos'altro, come il metodo principale tap
è stato ridefinito in varie librerie di automazione per premere qualcosa sullo schermo. Buona fortuna per scoprire cosa sta succedendo, specialmente se qualche modulo richiesto da un altro modulo ha scimmiottato un altro modulo per fare qualcosa di non documentato.
L'oggetto della variabile d'ambiente ENV non supporta 'merge', quindi devi scrivere
ENV.to_h.merge('a': '1')
Come bonus, puoi persino ridefinire le costanti tue o di qualcun altro se cambi idea su cosa dovrebbero essere.