Why does Hash#select and Hash#reject pass a key to a unary block?

前端 未结 1 1497
清酒与你
清酒与你 2021-01-05 20:48

My understanding was that Hash#select and Hash#reject each passes an array of key and its value [key, value] as a single block argumen

相关标签:
1条回答
  • 2021-01-05 21:14

    It's actually passing two arguments, always.

    What you're observing is merely the difference between how procs and lambdas treat excess arguments. Blocks (Procs unless you tell Ruby otherwise) behave as if it had an extra splat and discard excess arguments, whereas lambdas (and method objects) reject the caller due to the incorrect arity.

    Demonstration:

    >> p = proc { |e| p e }
    => #<Proc:0x007f8dfa1c8b50@(irb):1>
    >> l = lambda { |e| p e }
    => #<Proc:0x007f8dfa838620@(irb):2 (lambda)>
    >> {a: 1}.select &p
    :a
    => {:a=>1}
    >> {a: 1}.select &l
    ArgumentError: wrong number of arguments (2 for 1)
        from (irb):2:in `block in irb_binding'
        from (irb):4:in `select'
        from (irb):4
        from /usr/local/bin/irb:11:in `<main>'
    

    As an aside, since it was mentioned in the comments: map, in contrast, actually passes one argument. It gets allocated to two different variables because you can assign multiple variables with an array on the right side of the assignment operator, but it's really one argument all along.

    Demonstration:

    >> {a: 1}.map { |k, v| p k, v }
    :a
    1
    >> {a: 1}.map &p
    [:a, 1]
    => [[:a, 1]]
    >> {a: 1}.map &l
    [:a, 1]
    

    And upon changing p and l defined further up:

    >> p = proc { |k, v| p k, v }
    => #<Proc:0x007ffd94089258@(irb):1>
    >> l = lambda { |k, v| p k, v }
    => #<Proc:0x007ffd940783e0@(irb):2 (lambda)>
    >> {a: 1}.map &p
    :a
    1
    => [[:a, 1]]
    >> {a: 1}.map &l
    ArgumentError: wrong number of arguments (1 for 2)
        from (irb):2:in `block in irb_binding'
        from (irb):4:in `each'
        from (irb):4:in `map'
        from (irb):4
        from /usr/local/bin/irb:11:in `<main>'
    
    0 讨论(0)
提交回复
热议问题