L'OP a écrit
Il me semble étrange que la construction ci-dessus ne donne pas le résultat attendu. Quelle en est la raison? Quelles sont les situations où ce comportement est raisonnable?
pas «Peut-il être fait? mais pour répondre à la question qui n'a pas été posée avant d'arriver à la question qui a été réellement posée:
$ 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
Puisque reverse_each est censé créer un tableau entier, downto sera clairement plus efficace. Le fait qu'un concepteur de langage puisse même envisager de mettre en œuvre des choses comme celles-là est un peu lié à la réponse à la question réelle posée.
Pour répondre à la question telle qu'elle est réellement posée ...
La raison en est que Ruby est un langage infiniment surprenant. Certaines surprises sont agréables, mais il y a beaucoup de comportements qui sont carrément cassés. Même si certains de ces exemples suivants sont corrigés par des versions plus récentes, il y en a beaucoup d'autres, et ils restent comme des accusations sur l'état d'esprit de la conception originale:
nil.to_s
.to_s
.inspect
donne "" mais
nil.to_s
# .to_s # Don't want this one for now
.inspect
résulte en
syntax error, unexpected '.', expecting end-of-input
.inspect
^
Vous vous attendriez probablement à ce que << et push soient les mêmes pour l'ajout aux tableaux, mais
a = []
a << *[:A, :B] # is illegal but
a.push *[:A, :B] # isn't.
Vous vous attendriez probablement à ce que «grep» se comporte comme son équivalent en ligne de commande Unix, mais il correspond === non = ~, malgré son nom.
$ echo foo | grep .
foo
$ ruby -le 'p ["foo"].grep(".")'
[]
Diverses méthodes sont inopinément des alias l'une pour l'autre, vous devez donc apprendre plusieurs noms pour la même chose - par exemple find
et detect
- même si vous aimez la plupart des développeurs et n'utilisez jamais que l'un ou l'autre. Il en va de même pour size
, count
et length
, à l' exception des classes qui définissent différemment chacun, ou ne définissent pas un ou deux du tout.
À moins que quelqu'un n'ait implémenté autre chose - comme la méthode principale tap
a été redéfinie dans diverses bibliothèques d'automatisation pour appuyer sur quelque chose à l'écran. Bonne chance pour découvrir ce qui se passe, surtout si un module requis par un autre module a monkey encore un autre module pour faire quelque chose de non documenté.
L'objet de variable d'environnement, ENV ne prend pas en charge 'merge', vous devez donc écrire
ENV.to_h.merge('a': '1')
En prime, vous pouvez même redéfinir vos constantes ou celles de quelqu'un d'autre si vous changez d'avis sur ce qu'elles devraient être.