2017-04-13 83 views
5

我明白在没有参数`&block`的方法中,在带有参数`&block`和yield self`的方法中使用`yield self`有没有什么区别?

def a(&block) 
    block.call(self) 
end 

def a() 
    yield self 
end 

导致相同的结果,如果我假定有这样的块a {}。我的问题是 - 因为我偶然发现了这样的一些代码,无论任何差别或是否存在具有(如果我不以其他方式使用变量/参考块)的任何优势:

def a(&block) 
    yield self 
end 

这是一个具体情况我不了解使用&block

def rule(code, name, &block) 
    @rules = [] if @rules.nil? 
    @rules << Rule.new(code, name) 
    yield self 
end 
+0

为[块参数](http://ruby-doc.org/core-2.4.1/doc/syntax/methods_rdoc.html#label-Block+Argument)文档显示不同的使用情况。 – Stefan

+0

@Stefan我添加了一个特定的案例,我不明白使用&block,也许我错过了一些东西,所以你可能会看看?除此之外,我还阅读了文档,它对应于我的理解。 –

+0

如果您不打算明确使用它,请不要将其添加到列表中。它使得调用速度变慢并且令人困惑。 – ndn

回答

8

我能想到的唯一好处是自省:

def foo;  end 
def bar(&blk); end 

method(:foo).parameters #=> [] 
method(:bar).parameters #=> [[:block, :blk]] 

IDE和文档发电机可以利用这一点。但是,它不影响Ruby的参数传递。调用方法时,无论是否声明或调用,都可以传递或省略块。

+1

至少对我而言,这不仅仅是内省。我发现查看方法签名更容易,并查看最后一个参数是否具有前导'&',而不是查看整个方法并尝试在某处找到yield。 –

1

def pass_block 
    yield 
end 
pass_block { 'hi' } #=> 'hi' 

def pass_proc(&blk) 
    blk.call 
end 
pass_proc { 'hi' } #=> 'hi' 

之间的主要区别在于,blk,的Proc一个实例,是一个对象,并且因此可以被传递到其他方法。相反,块不是对象,因此不能传递。

def pass_proc(&blk) 
    puts "blk.is_a?(Proc)=#{blk.is_a?(Proc)}" 
    receive_proc(blk) 
end 

def receive_proc(proc) 
    proc.call 
end 

pass_proc { 'ho' } 
blk.is_a?(Proc)=true 
    #=> "ho" 
相关问题