2013-02-21 22 views
4

如何將lambda傳遞給hash.each,以便我可以重新使用一些代碼?如何將lambda傳遞給Hash.each?

> h = { a: 'b' } 
> h.each do |key, value| end 
=> {:a=>"b"} 
> test = lambda do |key, value| puts "#{key} = #{value}" end 
> test.call('a','b') 
a = b 
> h.each &test 
ArgumentError: wrong number of arguments (1 for 2) 
    from (irb):1:in `block in irb_binding' 
    from (irb):5:in `each' 
    from (irb):5 
    from /Users/jstillwell/.rvm/rubies/ruby-1.9.3-p362/bin/irb:16:in `<main>' 
> h.each test 
ArgumentError: wrong number of arguments(1 for 0) 
    from (irb):8:in `each' 
    from (irb):8 
    from /Users/jstillwell/.rvm/rubies/ruby-1.9.3-p362/bin/irb:16:in `<main>' 
+0

感謝您的問題清理。 – DragonFax 2013-02-21 00:33:56

回答

10

each產生當前元素到塊,如果lambda需要一個參數,而不是兩個。在Hash的情況下,產生的元素是一個兩元素Array,第一個元素是鍵,第二個元素是值。

test = lambda do |el| puts "#{el.first} = #{el.last}" end 
h.each &test 
# a = b 

或者,你可以用解構的參數列表綁定Ruby的支持:

test = lambda do |(k, v)| puts "#{k} = #{v}" end 
h.each &test 
# a = b 

或者,而不是使用lambda具有相同的參數結合語義的方法,您可以使用Proc,其具有相同的參數結合的語義塊,即,其將解包的單個Array參數分成多個參數綁定:

test = proc do |k, v| puts "#{k} = #{v}" end 
h.each &test 
# a = b 
+0

我遇到的問題(在我找到答案之後)是,正如你可以在我的第二行代碼中看到的那樣,'each'顯然需要一個帶有2個參數的塊。它只是沒有帶有2個參數的'lambda'。 WTF – DragonFax 2013-02-21 00:35:26

+0

'each' * always *產生* single *參數。 *總是*。沒有例外。如果將一個* single *'Array'傳遞給一個帶有多個*參數的塊,那麼'Array'將被解壓到類似於並行賦值的參數中。但是這與'each'沒有任何關係,只是基本的Ruby 101參數傳遞。 – 2013-02-21 00:39:18

+1

有魔力。如果可能,yield/block將打開一個**單個數組**。我無法在任何地方找到這個文件,也沒有懷疑它。謝謝Jörg。 – DragonFax 2013-02-21 00:40:08

0

我還是覺得這是語法不一致,我發現了另一個問題的答案(但沒有道歉) Inconsistency of arity between Hash.each and lambdas

我把它切換到

lambda do |(key, value)| 

然後我可以在

hash.each &test 

或者我可以直接打電話給

test.call([key, value]) 

如果有人有一個更好的答案,或者至少有一個簡潔的藉口,爲什麼這是必要的。我很樂意給他們分。

+0

您需要這種轉換,因爲'h.each'將每個對作爲單個對象傳遞給一個數組。數組被傳遞給你的''''參數,並且你缺少一個'value'。用'(key,value)'表示法,它將數組的值正確地傳遞給它們中的每一個。就像當你寫'a,b = [1,2]' – oldergod 2013-02-21 00:32:52

+0

我不確定你爲什麼覺得你在這裏需要一個「藉口」。 'each' * always *會產生一個* single *參數。你的lambda需要*兩個*參數。顯然,這是行不通的。 – 2013-02-21 00:33:24

0

看起來這是您從hash.each獲得參數的方式。我只是在撬REPL測試了這個(如果你還沒有使用過它,給它一個鏡頭。)

h.each { |k,v| 
    test.call(k,v)} 

each得到的值,並將它們放入拉姆達。

相關問題