Используя урожай внутри define_method в Ruby

Действительно ли возможно заставить ключевое слово урожая работать в блоке, данном define_method? Простой пример:

class Test
  define_method :test do |&b|
    puts b    # => #<Proc:...>
    yield
  end
end

Test.new.test {
  puts "Hi!"
}

Этот код производит следующую ошибку и в Ruby 1.8.7 и в 1.9.0:

тест rb:4:in 'тест': никакой блок не дан (LocalJumpError) от теста rb:8

Странной вещью является b основная переменная != nil но block_given? возвращает false. Это - намеренное поведение Ruby не распознать блоки объектами Proc?

Править: Отношения к ответу Beerlington: b.call() не то, что я ищу. Основная переменная использовалась только, чтобы указать, что блок на самом деле дан и не обнаруживается внутри define_method.

Причина, почему я должен использовать yield вместо block.call

Я готов записать некоторое расширение пути, как новые классы определяются в Ruby, таким образом любой код, который можно написать в чистом Ruby, должен быть принят, когда я использую свое расширение.

Таким образом, подобная семантика не может быть учтена, потому что это вынуждает пользователей моей библиотеки использовать только один надлежащий способ передать блок. Это нарушает правило TIMTOWTDI и не делает мою библиотеку прозрачной.

Реальный пример

Код ниже может быть упрощен для кодирования выше с тех пор my_def использование define_method:

require 'my_library'

class Test
  # client can write 'my_def' instead of 'def' since
  # my_library extends Class class
  my_def :test, "some parameter" do
    yield        # oh no, error :(
  end
end

Test.new.test {
  puts "Hi!"
}
29
задан Dawid 22 February 2010 в 20:35
поделиться

1 ответ

Думаю, это то, что вы ищете:

class Test
  define_method :test do |&b|
    b.call
  end
end

Test.new.test {
  puts "Hi!"
}

Подробнее на http://coderrr.wordpress.com/2008/10/29/using-define_method-with-blocks-in-ruby- 18 /

23
ответ дан 28 November 2019 в 01:49
поделиться