2016-05-06 241 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 

說了這麼多, '塊'是一個很好的約定。