Разность синтаксиса блока вызывает "LocalJumpError: без блока (выход)"

Увидел странный случай, пытаясь понять, что здесь происходит:

> def test
>   p yield
> end
=> nil
> test { 1 }
1
=> 1
> p test { 1 }
1
1
=> 1
> p test do
>   1
> end
LocalJumpError: no block given (yield)

Ответы

Ответ 1

Парсер признает это

p test do
  1
end

как это

(p test) do
  1
end

Блок передается в p, а не в test. Следовательно, yield не может дать результат и вызывает эту ошибку.

Ответ 2

do и {} для обозначения блоков, прикрепленных к методам, не являются полностью взаимозаменяемыми.

p test do
  1
end

Приоритет прикручивает вас. На самом деле это:

p(test()) do
  1
end

Итак, блок переходит к p, а не test.

{} имеет более высокий приоритет, чем do, и поэтому более тесно привязывается к синтаксически более близкому методу. Это справедливо и для других рубиновых ключевых слов с символическими эквивалентами, таких как and/&& и or/||, поэтому символы обычно рекомендуются по словам.