ОП написал
Мне кажется странным, что приведенная выше конструкция не дает
ожидаемый результат. В чем причина этого? Каковы
ситуации, когда это поведение разумно?
не "Это может быть сделано?" но чтобы ответить на вопрос, который не задавался, прежде чем перейти к вопросу, который был фактически задан:
$ 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
Так как reverse_each, как утверждается, создает весь массив, downto явно будет более эффективным. Тот факт, что разработчик языка может даже рассмотреть возможность реализации подобных вещей, как бы связывается с ответом на реальный вопрос, который задают.
Чтобы ответить на вопрос в том виде, в котором он был задан ...
Причина в том, что Ruby - это бесконечно удивительный язык. Некоторые сюрпризы приятны, но есть много поведения, которое прямо нарушено. Даже если некоторые из этих следующих примеров будут исправлены более новыми выпусками, есть много других, и они остаются в качестве обвинительного заключения на образ мышления оригинального дизайна:
nil.to_s
.to_s
.inspect
приводит к "", но
nil.to_s
# .to_s # Don't want this one for now
.inspect
Результаты в
syntax error, unexpected '.', expecting end-of-input
.inspect
^
Вы, вероятно, ожидаете, что << и push будут одинаковыми для добавления в массивы, но </p>
a = []
a << *[:A, :B] # is illegal but
a.push *[:A, :B] # isn't.
Вы, вероятно, ожидаете, что 'grep' будет вести себя как эквивалент командной строки Unix, но он === не соответствует = ~, несмотря на его имя.
$ echo foo | grep .
foo
$ ruby -le 'p ["foo"].grep(".")'
[]
Различные методы неожиданно являются псевдонимами друг для друга, поэтому вам нужно выучить несколько имен для одной и той же вещи - например, find
и detect
- даже если вам нравится большинство разработчиков и когда-либо используете только один или другой. То же самое касается size
, count
и length
, за исключением классов, которые определяют каждый из них по-разному или не определяют один или два вообще.
Если кто-то не реализовал что-то еще - например, основной метод, tap
был переопределен в различных библиотеках автоматизации для нажатия чего-либо на экране. Удачи в выяснении того, что происходит, особенно если какой-то модуль, требуемый другим модулем, подключил еще один модуль для выполнения каких-либо документов.
Объект переменной среды, ENV не поддерживает слияние, поэтому вы должны написать
ENV.to_h.merge('a': '1')
В качестве бонуса вы можете даже переопределить свои или чужие константы, если передумаете, какими они должны быть.