define_method不会将块作为参数ruby

时间:2015-10-15 17:08:44

标签: ruby metaprogramming

我目前正在从this metaprogramming tutorial进行第二周作业1 并且发送块使用define_method时遇到一些问题。程序根本没有看到块,当我调用block_given时返回false?即使我提供了一个块。

这是发送块的文件:

require_relative 'dog'

lassie, fido, stimpy = %w[Lassie Fido Stimpy].collect{|name| Dog.new(name)}
lassie.can :dance, :poo, :laugh
fido.can :poo
stimpy.can :dance

stimpy.can(:cry){"#{name} cried AHHHH"} # the block that I can't receive

puts lassie.name

p lassie.dance
p lassie.poo
p lassie.laugh
puts
p fido.dance
p fido.poo
p fido.laugh
puts
p stimpy.dance
p stimpy.poo
p stimpy.laugh
p stimpy.cry # method call

收到的文件:

Dog = Class.new do
    MESSAGES = { dance: "is dancing", poo: "is a smelly doggy!", laugh: "finds this hilarious" }

    define_method :initialize do |name|
    instance_variable_set(:@name, name)
    end

    define_method :name do
    instance_variable_get :@name
    end

    define_method :can do |*args, &block|
    puts block_given? # false 
    if block_given?
        define_method args.to_sym do
        yield
        end
    else
        args.each do |ability|
        self.class.instance_eval do
            define_method "#{ability}".to_sym do
            @name + " " + MESSAGES[ability]
            end
        end
        end
    end
    end

    define_method :method_missing do |arg|
    puts "#{@name} doesn't understand #{arg}"
    end
end

2 个答案:

答案 0 :(得分:1)

相信(但尚未检查)block_given?是指传递给由最近的词汇封闭方法定义定义的方法的块,即def在使用define_method定义的方法中工作。

知道这个事实yield只会产生一个块传递给最近的词法封闭方法定义所定义的方法,即def从一个块中产生(毕竟,define_method是,它只是一个像任何其他方法一样的方法,就像任何其他方法一样, yield产生方法的块,而不是其他块。)

yieldblock_given?与明确命名的阻止 - Proc结合起来有点奇怪。如果您有姓名,则无需匿名,您可以说

if block
  define_method(args.to_sym) do block.() end
end

或者您的意思是将块传递给define_method以用作方法的实现?那就是

if block
  define_method(args.to_sym, &block)
end

答案 1 :(得分:0)

不确定是否可以传递参数并阻止刚刚定义的内容。 read this

define_method(symbol, method) → symbol
define_method(symbol) { block } → symbol 

而不是define_method :can do |*args, &block|尝试使用明确的def can(*args, &block)

无论如何这样做真的很奇怪..