Skip to content

Instantly share code, notes, and snippets.

@jessitron
Created March 10, 2013 17:45
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jessitron/5129618 to your computer and use it in GitHub Desktop.
Save jessitron/5129618 to your computer and use it in GitHub Desktop.
Ruby: Hash.each treats blocks and lambdas differently when the arity is 2
#
# Ruby 2.0 hashes: they treat lambdas inconsistently from blocks.
# Pass in a block straight-up, and each (or each_pair) looks at the arity of the block.
# A block that accepts one argument gets an array of two elements, key and value.
# A block that accepts two arguments gets the key and value separately. How nice.
#
# But, if you pass in a lambda as a block, you always get just one argument.
# No key-value separation for you!
#
#setup
lambda_of_arity_two = ->(k,v) { puts "lambda of 2, #{k} => #{v}" }
lambda_of_arity_one = ->(a) { puts "lambda of 1, #{a[0]} => #{a[1]}" }
some_hash = { fruit: "banana", veggie: "carrot" }
# equivalent
some_hash.each { |a| puts "block of 1, #{a[0]} => #{a[1]}" }
some_hash.each &lambda_of_arity_one
# I wish
some_hash.each { |k,v| puts "block of 2, #{k} => #{v}" }
some_hash.each &lambda_of_arity_two # failure! ArgumentError: wrong number of arguments (1 for 2)
@kputnam
Copy link

kputnam commented Mar 10, 2013

I agree, that's strange. Maybe you can get a little closer to what you want with this:

lambda_arity_of_two = ->((k,v)) { puts "lambda of 2, #{k} => #{v}" }

This is basically syntax sugar for k,v = a and is backward compatible at least to 1.8.7, probably further.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment