Почему это выражение карты дает разные результаты в зависимости от того, использую ли я фигурные скобки или do / end?
a = [1,2,3,4,5]
p a.map { |n|
n*2
}
#=> [2,4,6,8,10]
p a.map do |n|
n*2
end
#=> [1,2,3,4,5]
Почему это выражение карты дает разные результаты в зависимости от того, использую ли я фигурные скобки или do / end?
a = [1,2,3,4,5]
p a.map { |n|
n*2
}
#=> [2,4,6,8,10]
p a.map do |n|
n*2
end
#=> [1,2,3,4,5]
Это потому, что вторая строка интерпретируется как:
p(a.map) do ... end
вместо:
p(a.map do ... end)
Грамматика в этом случае неоднозначна, и do
, похоже, не связывает так сильно, как {
.
do...end
с многострочным блоком, чтобы map
получил его как параметр? Фигурные скобки - как вы предлагаете - этого не сделают, Ruby выдает ошибку, unexpected keyword_do_block
даже весь блок представляет собой одну строку.
- person karatedog; 08.07.2012
foo = a.map do ... end ; p(foo)
. Это точно такая же семантика, потому что map
всегда нужно агрегировать массив для передачи в первую очередь. Будет ли этот массив затем сохранен в переменной или передан в качестве параметра другому методу, не имеет значения, массив должен быть создан первым, несмотря ни на что.
- person DarkDust; 10.07.2012
Это связано с разницей в ассоциативности символа {
и ключевого слова do
.
В первом случае блок интерпретируется как аргумент блока для функции map
. Результатом функции карты является аргумент функции p
.
Во втором случае блок интерпретируется как аргумент блока для функции p
, а a.map
интерпретируется как первый аргумент функции p
. Поскольку a.map
оценивается как a
, выводится исходный массив. В этом случае блок фактически игнорируется.
С синтаксисом do/end
вы передаете блок в p
в качестве второго аргумента, а не в карту. Вы получите тот же результат с:
p a.map
Блок игнорируется p
, поскольку он ничего не производит на inspect
.