2014-10-12 3 views
0

Пожалуйста, обратите внимание на следующие различные способы для определения метода m:неявный блок прохождения и динамически определенные методы

  • Метод 1:

    class C 
        def m; yield; end 
    end 
    
  • Метод 2:

    class C 
        def initialize 
        (class << self; self; end).class_eval do    
         define_method(:m){|&b| b.call } 
        end 
        end 
    end 
    
  • Способ 3:

    class C 
        def initialize 
        (class << self; self; end).class_eval do    
         define_method(:m){puts block_given?; yield}    
        end 
        end 
    end 
    

Тогда я могу вызвать m с помощью Object#send.

o = C.new 
o.send(:m) {puts 'test'} 

Призывая m, используя метод 1 или метод 2 работает отлично, Метод 3 дает эту ошибку:

no block given (yield) (LocalJumpError) 

Я понимаю, что блок не является объектом, но вместо того, чтобы просто часть метода вызова синтаксис и вы не можете передать неявный блок от одной функции к другой, не писать что-то неясное, как это:

def printer 
    yield 
end 
def proxy 
    printer &Proc.new 
end 

proxy { puts "&Proc.new probably creates Proc object from block"} 

Но в таком случае, почему метод 1 работает? Было бы здорово получить ответ, который объяснил бы, что происходит под капотом.

+0

Непонятно, что вы подразумеваете под «define ... static», «с явным блоком» или «первым случаем». Я могу догадаться, что вы, вероятно, упоминали либо ваш метод 1, метод 2, либо метод 3, но неясно, какой из них. – sawa

+0

@sawa Я думал, что это будет ясно с фрагментом кода. Вы цитировали метод 1, метод 2 и метод 1 соответственно :) – yuyoyuppe

+0

Почему вы использовали 'send' для вызова' m'? Не похоже, что это имеет какое-то значение. – sawa

ответ

3

Проблема с методом 3 - это область действия. yield относится к блоку, переданному initialize, если таковой имеется. Он не относится к блоку, переданному в m. И так как вы создали o на C.new без блока, ожидаемый yield отсутствует, и это вызывает ошибку.

В способе 1 yield относится к блоку, переданному в m. В способе 2 b относится к proc, преобразованному из блока, переданного в m.

+0

А, я вижу! Но можно ли использовать 'yield' в динамически определенном методе? – yuyoyuppe

+1

См. [This] (http://stackoverflow.com/questions/2306731/using-yield-inside-define-method-in-ruby). – sawa

Смежные вопросы