My understanding was that Hash#select and Hash#reject each passes an array of key and its value [key, value] as a single block argument for each iteration, and you can directly pick them separately within the block using implicit destructive assignment:
{a: 1, b: 2}.select{|k, v| k == :a} # => {:a => 1}
{a: 1, b: 2}.reject{|k, v| v == 1} # => {:b => 2}
or explicit destructive assignment:
{a: 1, b: 2}.select{|(k, v)| k == :a} # => {:a => 1}
I expected that, when I pass a unary block, the whole [key, value] array would be passed, but in reality, it seems like the key is passed:
{a: 1}.select{|e| p e} # => Prints `:a` (I expected `[:a, 1]`)
Why does it work this way? For other Hash instance methods like map, the whole [key, value] array is passed.
If it were especially designed to work differently for unary blocks as compared to binary blocks, then I can understand it is useful. But, then I would not understand why the case above with explicit destructive assignment works as is. And I also do not find any document mentioning such specification.
Edit I had a wrong result for {a: 1, b: 2}.reject{|(k, v)| v == 1}. It is corrected here:
{a: 1, b: 2}.reject{|(k, v)| v == 1} # => {:a=>1, :b=>2} (not `{:b=>2}`)
Now, this also indicates that (k, v) is the key, not [key, value], so v is always nil. Cf. Darek Nędza's comment.