OP napisał
Wydaje mi się dziwne, że powyższa konstrukcja nie daje oczekiwanego rezultatu. Jaki jest tego powód? W jakich sytuacjach takie zachowanie jest uzasadnione?
nie „Czy można to zrobić?” ale aby odpowiedzieć na pytanie, które nie zostało zadane przed przejściem do pytania, które zostało zadane:
$ 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
Ponieważ twierdzi się, że reverse_each buduje całą tablicę, downto z pewnością będzie bardziej wydajne. Fakt, że projektant języka mógłby nawet rozważyć zastosowanie takich rzeczy, wiąże się z odpowiedzią na zadane pytanie.
Aby odpowiedzieć na pytanie tak, jak faktycznie zadano ...
Powodem jest to, że Ruby to nieskończenie zaskakujący język. Niektóre niespodzianki są przyjemne, ale jest wiele zachowań, które są wręcz zepsute. Nawet jeśli niektóre z poniższych przykładów zostaną poprawione w nowszych wersjach, istnieje wiele innych i pozostają one jako akty oskarżenia w myśleniu pierwotnego projektu:
nil.to_s
.to_s
.inspect
daje w wyniku „” ale
nil.to_s
# .to_s # Don't want this one for now
.inspect
prowadzi do
syntax error, unexpected '.', expecting end-of-input
.inspect
^
Prawdopodobnie spodziewałbyś się, że << i push będzie takie samo przy dołączaniu do tablic, ale
a = []
a << *[:A, :B] # is illegal but
a.push *[:A, :B] # isn't.
Prawdopodobnie spodziewałbyś się, że „grep” będzie zachowywał się jak jego odpowiednik w linii poleceń systemu Unix, ale mimo swojej nazwy === dopasowanie not = ~.
$ echo foo | grep .
foo
$ ruby -le 'p ["foo"].grep(".")'
[]
Różne metody są dla siebie nieoczekiwanie aliasami, więc musisz nauczyć się wielu nazw dla tej samej rzeczy - np. find
I detect
- nawet jeśli lubisz większość programistów i zawsze używasz tylko jednej lub drugiej. Dużo to samo dotyczy size
, count
oraz length
, z wyjątkiem klas, które określają każdy inaczej, albo nie definiują jeden lub dwa w ogóle.
Chyba że ktoś zaimplementował coś innego - tak jak podstawowa metoda tap
została na nowo zdefiniowana w różnych bibliotekach automatyzacji, aby nacisnąć coś na ekranie. Powodzenia w ustalaniu, co się dzieje, zwłaszcza jeśli jakiś moduł wymagany przez inny moduł zmusił kolejny moduł do zrobienia czegoś nieudokumentowanego.
Obiekt zmiennej środowiskowej ENV nie obsługuje funkcji „scalania”, więc musisz pisać
ENV.to_h.merge('a': '1')
Jako bonus możesz nawet przedefiniować swoje lub czyjeś stałe stałe, jeśli zmienisz zdanie na temat tego, jakie powinny być.