yield: почему я не могу написать: p test_method {i.upcase} - PullRequest
0 голосов
/ 14 сентября 2009
def test_method
  ["a", "b", "c"].map {|i| yield(i) }
end

Если я вызову test_method так:

p test_method {|i| i.upcase }
# => ["A", "B", "C"]

Зачем мне нужен {| i |} внутри блока, вместо того, чтобы просто сказать это:

p test_method { i.upcase }

Причина, по которой я так думаю, заключается в том, что когда yield вызывается в test_method, у нас уже есть {| i |}

  ["a", "b", "c"].map {|i| yield(i) }

Ответы [ 5 ]

3 голосов
/ 15 сентября 2009

Если вы пришли из Groovy, где у них есть неявный итератор, или даже из Scala, где вы можете обойтись без этого | i | используя частичные функции, тогда вы можете найти это логичным вопросом, однако в настоящий момент лучшее, что вы можете сделать в Ruby 1.9 или даже внутри Rails, - это использовать метод Symbol # to_block, как упоминалось в JRL:

p test_method &:upcase

Так что просто добавьте &: перед именем метода.

2 голосов
/ 14 сентября 2009

Как сказал ennuikiller, вы должны определить, как вы хотите назвать переменную (и), которая передается обратно из оператора yield. Это связано с областью действия переменной. Область внутри блока, который вы передаете test_method, не знает о переменной i. Вы можете называть это как угодно.

Например, вы можете сделать следующее:

def test_method
  ["a", "b", "c"].map { |i| yield(i) }
end

p test_method { |some_variable_name| some_variable_name.upcase }

То, что тестовый метод знает об этом, не означает, что блок, который вы передаете тестовому методу, узнает об этом.

Редактировать 1: Чтобы дать немного больше информации, вы можете переопределить test_method следующим образом, если это делает его немного более понятным:

def test_method(&block)
  if not block.nil?
    ["a", "b", "c"].map { |i| yield(i) }
  end
end
2 голосов
/ 14 сентября 2009

В Ruby 1.9 вы можете написать:

 p test_method &:upcase
2 голосов
/ 14 сентября 2009

Блок нуждается в параметризованном значении для передачи в метод верхнего регистра. Это можно посмотреть следующим образом: если вы пропустите | i | в блоке нет способа «поймать» полученное значение (i в test_method)

0 голосов
/ 14 сентября 2009

Во время звонка

p test_method {|i| i.upcase}

|i|, использованное в определении метода, не отображается (его область действия находится исключительно в пределах {}). В частности, вы создаете блок, который принимает одну переменную, и чтобы построить этот блок, вы должны указать, что это за переменная. Обратите внимание, что

p test_method {|j| j.upcase}

также действует.

...