How to pass lambda to Hash.each?

How to pass lambda to hash.each so that I can reuse some kind of code?

 > 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>' 
+4
source share
2 answers

each returns the current element in a block, ergo lambda should take one argument, not two. In the case of Hash resulting element is a two-element Array , with the first element being the key and the second element being the value.

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

Alternatively, you can use Ruby support to destruct the binding in parameter lists:

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

Or instead of using lambda , which has the same argument as binding semantics as a method, you can use Proc , which has the same argument as binding semantics as a block, that is, it decompresses one Array into several parameter bindings:

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

I still feel that this is inconsistent syntax, I found the answer (but not an apology) in another question The inconsistency of fate between Hash.each and lambdas

I switched it to

 lambda do |(key, value)| 

then i can go to

 hash.each &test 

or I can call it directly with

 test.call([key, value]) 

If someone has a better answer, or at least a brief excuse, why is this necessary. I will gladly give them glasses.

0
source

All Articles