2010-06-15 59 views
5

比方說,我有一個函數瞭解Ruby的可枚舉#地圖(更復雜的塊)

def odd_or_even n 
    if n%2 == 0 
    return :even 
    else 
    return :odd 
    end 
end 

而且我有一個簡單枚舉陣列

simple = [1,2,3,4,5] 

,我跑它通過地圖,與我功能,使用do-end塊:

simple.map do 
    |n| odd_or_even(n) 
end 
# => [:odd,:even,:odd,:even,:odd] 

我怎麼能做到這一點,沒有,比如說,首先定義函數呢?例如,

# does not work 
simple.map do |n| 
    if n%2 == 0 
    return :even 
    else 
    return :odd 
    end 
end 

# Desired result: 
# => [:odd,:even,:odd,:even,:odd] 

是無效的紅寶石,並且編譯器因爲想到它而生氣。但是,我將如何實現一個等效的東西,這是有效的?

編輯

在現實中,解決我的問題關係到我比它背後的動機/推理少了很多,幫助我瞭解更多塊紅寶石是如何工作的:)

+2

對於它的價值,你可以做甚麼?或1.odd?在紅寶石> = 1.8.7 – steenslag 2010-06-15 06:57:10

回答

13

你」離得這麼近。只需刪除return即可,您是金色的。

這是因爲傳遞給map的塊是一個proc(即使用Proc.new創建),而不是lambda。在proc中的return不會跳出進程,而是跳出執行該進程的方法(即稱爲call)。另一方面,拉姆達內的返回僅跳出拉姆達。

proc方法在Ruby 1.8中返回一個lambda,在Ruby 1.9中返回一個Proc。最好不要使用這種方法,並明確你想使用哪種結構。

我猜你是在IRB中,或者是在你嘗試這個時遇到一個普通的ruby腳本。

a = Proc.new { return } 
a.call # fails. Nothing to return from. 

def foobar 
    a = Proc.new { return } 
    a.call 
    puts 'hello' # not reached. The return within the proc causes execution to jump out of the foobar method. 
end 
foobar # succeeds, but does not print 'hello'. The return within the proc jumps out of the foobar method. 

b = lambda { return } 
b.call # succeeds. The return only returns from the lambda itself. 

def bazquux 
    b = lambda { return } 
    b.call 
    puts 'hello' # this is reached. The lambda only returned from itself. 
end 
bazquux # succeeds, and prints 'hello' 

從中學習的教訓是使用隱式返回,除非你不能,我想。

+0

是否有任何理由*爲什麼會發生這種情況?該塊是否簡單地輸出最後執行的命令,如隱式返回? 我問這是因爲我想能夠預測會發生什麼;有這些出來,似乎有點......隨機。 – 2010-06-15 01:35:32

+0

簡短版本是「這是proc和lambdas之間的區別之一。」工作更好的解釋。是的,塊會返回最近評估過的表達式。 – x1a4 2010-06-15 01:37:55

+0

感謝您的解釋;這是非常徹底的和有益的=) 只是最後一個問題......是否有可能通過lambda作爲塊?到#map,也許? – 2010-06-15 02:28:15

9

我懷疑這可能是一個重複的問題,而是給一個數值超出塊,用安德魯的回答使用next

simple.map do |n| 
    if n%2 == 0 
    next :even 
    else 
    next :odd 
    end 
end 
+0

嗯,這似乎正是我正在尋找:)謝謝:) – 2010-06-15 04:00:26

3

最短的變體:

simple.map { |n| next :even if n % 2 == 0; :odd } 
+1

更進一步:'simple.map {| N |下一個n%2 == 0? :even::odd}';-) – 2012-10-06 23:06:56