2016-05-06 196 views

回答

2

通常&调用对象的to_proc方法,如gets.split.map(&:to_i)用于读取整数线,这是相同的map { |e| e.to_i }

在方法参数,它出现在最后的参数,这意味着您传递给代码块,请查看以下代码以获取详细信息。

def g 
    puts yield "g" 
end 

def h(block) 
    puts block.call "h" 
end 

def f(&block) 
    puts block.class  # => Proc 
    puts block.call "f"  # => hello f 
    g &block    # => hello g  passed as code block 
    h block     # => hello h  passed as proc 
end 

f { |x| "hello " + x } 
4

在功能& '层片' 块(还要求它to_proc),类似于*用于常规参数。

,有点相当于

def before_load(&block) # this binds provided block into block variable 
    ActiveSupport::Notifications.subscribe(ActiveAdmin::Application::BeforeLoadEvent){|some_params_maybe| 
    ActiveAdmin::Event.wrap_block_for_active_support_notifications(block).call(some_params_maybe) 
    } 
end 
+0

这里重要的是你不必知道或关心有多少参数可以阻止需要。 – tadman

1

Following article提供Ruby中使用的“&”一个很好的解释:

的隐性块 方法在Ruby中可以使用参数在各种有趣的方式。一个特别有趣的例子是Ruby方法占用一个块。

事实上,所有Ruby方法可以隐含采取的块,而不需要在参数列表中指定这个或具有到方法体例如内使用块:

def hello 
end 

hello do 
    puts "hello" 
end 

这将不执行任何麻烦,但绝对不会因为我们不执行,我们正在传递块被打印出来,我们可以 - 当然 - 很容易被yielding执行块吧。

def hello 
    yield if block_given? 
end 

hello do 
    puts "hello" 
end 

氏的时候,我们得到一些输出:

hello 

我们yielded的方法内的块,但事实证明,该方法需要一个块还是隐含的。

它变得更有趣,因为Ruby允许将任何对象传递给方法,并让该方法尝试将此对象用作其块。如果我们在方法的最后一个参数前加一个&符号,Ruby会尝试把这个参数作为方法的块。如果参数已经是Proc对象,则Ruby将简单地将其与该方法关联为其块。

def hello 
     yield if block_given? 
    end 

    blah = -> {puts "lambda"} 

hello(&blah) 
lambda 

如果参数不是Proc红宝石会尝试与方法,其块关联之前将其转换成一个(通过调用它to_proc)。

def hello 
    yield if block_given? 
end 

class FooBar 
    def to_proc 
    -> {puts 'converted lambda'} 
    end 
end 

hello(&FooBar.new) 
converted lambda 

所有这些看起来都很清楚,但是如果我想采用与方法关联的块并将其传递给另一个方法呢?我们需要一种方法来引用我们的区块。

显式模块 当我们编写我们的方法定义时,我们可以明确声明我们期望这个方法有可能取得一个块。令人困惑的是,红宝石使用符号此还有:

def hello(&block) 
    yield if block_given? 
end 

hello do 
    puts "hello" 
end 

定义我们的方法这种方式,给了我们,使我们可以参考我们的块方法体中的名称。而且,由于我们的块是Proc对象,而不是yielding它,我们可以call它:

def hello(&block) 
    block.call if block_given? 
end 

hello do 
    puts "hello" 
end 

我喜欢block.call,而不是yield,它使事情更清晰。当然,当我们定义我们的方法时,我们不必使用名称'block',我们可以这样做:

def hello(&foo) 
    foo.call if block_given? 
end 

hello do 
    puts "hello" 
end 

说了这么多, '块'是一个很好的约定。