Das OP schrieb
Es scheint mir seltsam, dass das obige Konstrukt nicht das erwartete Ergebnis liefert. Was ist der Grund dafür? In welchen Situationen ist dieses Verhalten angemessen?
nicht 'Kann es gemacht werden?' aber um die Frage zu beantworten, die nicht gestellt wurde, bevor man zu der Frage kam, die tatsächlich gestellt wurde:
$ 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
Da reverse_each angeblich ein ganzes Array erstellt, wird Downto eindeutig effizienter. Die Tatsache, dass ein Sprachdesigner sogar in Betracht ziehen könnte, solche Dinge zu implementieren, hängt mit der Antwort auf die eigentliche Frage zusammen.
Um die tatsächlich gestellte Frage zu beantworten ...
Der Grund ist, dass Ruby eine unendlich überraschende Sprache ist. Einige Überraschungen sind angenehm, aber es gibt viele Verhaltensweisen, die regelrecht gebrochen sind. Auch wenn einige dieser folgenden Beispiele durch neuere Versionen korrigiert wurden, gibt es viele andere, und sie bleiben als Anklage gegen die Denkweise des ursprünglichen Designs:
nil.to_s
.to_s
.inspect
führt zu "" aber
nil.to_s
# .to_s # Don't want this one for now
.inspect
führt zu
syntax error, unexpected '.', expecting end-of-input
.inspect
^
Sie würden wahrscheinlich erwarten, dass << und push beim Anhängen an Arrays gleich sind, aber
a = []
a << *[:A, :B] # is illegal but
a.push *[:A, :B] # isn't.
Sie würden wahrscheinlich erwarten, dass sich 'grep' wie sein Unix-Befehlszeilenäquivalent verhält, aber es stimmt trotz seines Namens nicht = ~ überein.
$ echo foo | grep .
foo
$ ruby -le 'p ["foo"].grep(".")'
[]
Verschiedene Methoden sind unerwartet Aliase für einander, daher müssen Sie mehrere Namen für dasselbe lernen - z. B. find
und detect
- auch wenn Sie die meisten Entwickler mögen und immer nur den einen oder anderen verwenden. Ähnliches gilt für size
,, count
und length
, mit Ausnahme von Klassen, die jeweils unterschiedlich oder gar nicht ein oder zwei definieren.
Es sei denn, jemand hat etwas anderes implementiert - wie die tap
Kernmethode in verschiedenen Automatisierungsbibliotheken neu definiert wurde, um etwas auf den Bildschirm zu drücken. Viel Glück beim Herausfinden, was los ist, insbesondere wenn ein Modul, das von einem anderen Modul benötigt wird, ein weiteres Modul aktiviert hat, um etwas Undokumentiertes zu tun.
Das Umgebungsvariablenobjekt ENV unterstützt 'Zusammenführen' nicht, daher müssen Sie schreiben
ENV.to_h.merge('a': '1')
Als Bonus können Sie sogar die Konstanten Ihrer oder einer anderen Person neu definieren, wenn Sie Ihre Meinung darüber ändern, was sie sein sollen.