как передать блок методу, имя которого заканчивается знаком равенства? - PullRequest
2 голосов
/ 26 января 2012

это звучит странно, не так ли?

class Dummy
  def foo=(value); end
end

Dummy.new.foo = 1 { |x| x } # => syntax error
Dummy.new.foo=(1) { |x| x } # => syntax error

я пробовал каждую перестановку пробелов, скобок, запятых;неудачно.я озадаченя никогда не подозревал, что методы, заканчивающиеся на '=', были особенными.это ошибка?это предназначено?если задумано, почему?это задокументировано?где?Пожалуйста, поделитесь пониманием.

спасибо

пс.ruby равен 1.9.2p290 (редакция 2011-07-09, 32553) [x86_64-darwin11.0.1]

Ответы [ 2 ]

2 голосов
/ 26 января 2012

Синтаксический сахар для методов, заканчивающихся на =, делает его особенным.Вы все еще можете делать такие вещи, как передавать множественные аргументы этому методу или передавать блок, но не каким-либо симпатичным или удобным способом:синтаксис сахара они оценивают по правому значению, а не по возвращаемому значению метода:

class Foo
  def bar=(a)
    return 17 # really explicit
  end
end

f = Foo.new

x = (f.bar = 42)
p x
#=> 42

x = f.send(:bar=,42)
p x
#=> 17
0 голосов
/ 26 января 2012

Дело не столько в том, что сами методы являются особыми, но в большей степени связано с тем, как Ruby обрабатывает назначения (например, foo = bar). Сначала оценивается правая часть, затем оценивается левая часть и предпринимается соответствующее действие. Если левая часть является атрибутом объекта, то вызывается соответствующий метод установки.

Итак, в вашем примере:

Dummy.new.foo = 1 { |x| x }

Первый ruby ​​пытается вычислить 1 { |x| x }, что и вызывает синтаксическую ошибку.

Dummy.new.foo=something на самом деле не означает «вызов метода с именем foo=», но на самом деле означает что-то более похожее на «evalualate something», а затем определяет, что такое `Dummy.new.foo, и выглядит ли он как атрибут объекта , добавьте = к имени и вызовите этот метод ". Вот почему Dummy.new.foo= и Dummy.new.foo = работают одинаково.

Вы можете вызывать эти методы, используя send, и можете передать блок следующим образом:

Dummy.new.send "foo=", 2 do
  puts "HI"
end

Это потому, что с помощью send вы можете явно назвать метод, который хотите вызвать.

Конечно, конечный результат заключается в том, что методы, оканчивающиеся на =, по-видимому, имеют какое-то "особое" поведение, о котором вам нужно знать, но может быть полезно понять, что на самом деле происходит.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...