2015-10-15 35 views
0

我目前正在从this metaprogramming tutorial 做第二周任务1,并有一些与define_method使用它的发送块的问题。程序根本看不到块,当我调用block_given时返回false?即使我提供了一个块。define_method没有收到块作为参数ruby

下面是发送数据块文件:

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 
+0

如果块被给出,为什么你要定义一个方法?如果这就是你应该做的事情,那么在splatted数组上调用'to_sym'的结果是什么? –

+0

@DaveNewton我甚至无法收到该块,所以我无法编辑程序的这一部分。我发送唯一的参数时通过一个块,它的方法名称 – poctek

+0

这与Rails无关,所以你应该删除Rails标签。 –

回答

1

相信(但还没有签)block_given?指块是传递给由最接近的词法封闭方法定义所定义的方法,即def不会在由定义的方法内工作。

知道一个事实,即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 
+0

是的,你的第二个猜测是正确的,谢谢你) – poctek

0

不知道你可以传递参数,并阻止对刚刚被定义的东西。 read this

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

代替define_method :can do |*args, &block|尝试明确def can(*args, &block)

这是怪异那样做呢..