2015-10-15 36 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)

這是怪異那樣做呢..