Приоритет оператора и порядок оценки в Ruby: yield vs ‹‹ (оператор лопаты)

Я читаю эту книгу Обоснованный рубист и его глава «Техники управления потоком» на стр. 184 содержит простой пример реализации map с помощью итератора:

class Array
  def my_map
    c=0
    acc = []
    until c == size
      acc << yield self[c]
      c += 1 end
    acc
  end
end

У меня есть следующая ошибка при запуске этого кода ruby MY_FILE.rb:

MY_FILE.rb:6: syntax error, unexpected `self', expecting `end'
      acc << yield self[c]

Решение этой проблемы заключается в заключении скобок вокруг yield self[c], чтобы вся эта строка выглядела так:

  acc << (yield self[c])

Затем процедура работает с этим однострочным изменением. В моем понимании проблема либо с приоритетом оператора, либо с порядком оценки. Я довольно долго бродил по сети, но не мог точно определить, почему именно код из книги не работает.

Почему пример книги не работает? Каков приоритет оператора и/или порядок оценки в acc << yield self[c]?


person Smartens    schedule 11.01.2021    source источник
comment
Вы также можете использовать acc << yield(self[c]) Я не уверен в точной причине, но скобки иногда требуются для устранения неоднозначности аргументов.   -  person max pleaner    schedule 11.01.2021
comment
К вашему сведению, вы получаете ту же синтаксическую ошибку для acc << foo bar — это не относится к yield.   -  person Stefan    schedule 11.01.2021
comment
В моем понимании проблема либо с приоритетом оператора, либо с порядком оценки. – Это не может быть проблемой с порядком оценки, так как вы получаете SyntaxError, и, следовательно, ничто не может быть оценено в неправильном порядке, поскольку вообще ничего не оценивается.   -  person Jörg W Mittag    schedule 11.01.2021


Ответы (1)


Обычно параметры метода заключаются в скобки:

x=foo(y)
a=bar(baz(z))
b=7+baz(w)

В определенных ситуациях (например, если приоритеты не связаны иначе) вы можете не использовать фигурные скобки. Следовательно,

x = foo y

работает, но

a = bar baz z

интерпретируется как

a = (bar(baz))(z)

а также

b = 7 + baz w

as

b = (7+baz) w

Это рискованно, если интерпретация выражения приводит к чему-то осмысленному. В этом случае вы бы даже не получили сообщение об ошибке, а просто программа повела бы себя не так, как вы ожидали.

В общем, рекомендуется всегда использовать круглые скобки при вызове методов.

person user1934428    schedule 11.01.2021