2013-03-19 80 views
0

我在學習Ruby的時候注意到,每種方法的這些用法都工作併產生相同的輸出,而且我想知道Ruby是如何實現這種功能的(以及我如何使它實現我自己的功能):Ruby:超載收益函數

my_array = [["hello","goodbye"],["picture","perfect"]] 

my_array.each do |array| 

    puts array[0] + " " + array[1] 

end 

my_array.each do |first, second| 

    puts first + " " + second 

end 

我理解的是寫入一個接受代碼塊的方法的定義的情況下,產量的方法是利用將參數傳遞到碼塊,並調用塊。但是,如何利用yield方法來根據所提供的代碼塊傳遞不同的參數?在這個例子中,看起來yield方法在塊內使用兩個參數(即第一個,第二個)時傳遞單個數組元素,並且當在塊內使用一個參數時,它傳遞數組本身(即數組)。

+0

@RoneyMichael糾正我,如果我錯了,但我不認爲這是一個解決方案。 splat操作符旨在用於參數,而不是參數。而我的問題是關於如何構建我的產量陳述和我傳遞給他們的論點。 – voltair 2013-03-19 06:34:19

+0

哦對!我的錯。 – 2013-03-19 07:37:32

回答

1

each而不是yield都沒有做任何特殊的事情,這就是塊參數的工作方式。考慮一個簡單的例子:

def f(x) yield x end 

現在我們可以看看會發生什麼:

>> f([1,2]) { |a| puts a.inspect } 
[1, 2] 
>> f([1,2]) { |a, b| puts "#{a} - #{b}" } 
1 - 2 
>> f([1,2]) { |a, b, c| puts "#{a} - #{b} - #{c}" } 
1 - 2 - 

你會在分配看到類似自毀:

a, b = [1, 2] 

您也可以做到這一點明確a splat:

a, b = *[1, 2] 

或像這樣:

def g(x) yield *x end 
g([1, 2]) { |a, b| puts "#{a} - #{b}" } 

想必塊知道各種各樣的事情會被賦予這樣的塊,能很好地解壓縮參數。請注意,g函數必須知道它的參數是splatable(即數組),但f不是。 f很好地把「x」這個邏輯放在f的呼叫中,g掩埋了它自身內部的一半邏輯。一個地方的差異變得很明顯是當你使用一個散列可枚舉的方法:

{ :where => :is, :pancakes => :house? }.map { |k, v| ... } 

Enumerable#map並不需要知道一個哈希鍵/值的兩個元素數組的作品,它只是通過周圍的事物和葉它讓所有人都擔心細節。

+0

非常感謝你的回答。那麼在那裏我可以看到ruby如何自動檢測和解構(或不解構)這些對象(如數組和哈希)的規則嗎?或者它只是通過反覆試驗學到的東西,因爲它真的只是與數組和哈希值相關?另外,對於g方法,如果傳遞給g的參數不是數組,那麼yield函數中的splat是否意味着會出現錯誤?並且只有陣列可以運行?這似乎是你推斷的,但我不確定。 – voltair 2013-03-20 01:27:29

+0

@ user1419674:只有數組在塊參數中獲得自動觸發/解構。如果你想看看如何與['Enumerable'](http://ruby-doc.org/core-2.0/Enumerable.html)(地圖和朋友的來源)進行交互,那麼你必須檢查班級的文件。 – 2013-03-20 03:51:12