ruby - 为什么 Hash#select 和 Hash#reject 将 key 传递给一元 block ?

标签 ruby hash block

我的理解是 Hash#selectHash#reject 分别传递一个键数组及其值 [key, value] 作为每次迭代的单个 block 参数,您可以使用隐式破坏性赋值直接在 block 内单独选择它们:

{a: 1, b: 2}.select{|k, v| k == :a} # => {:a => 1}
{a: 1, b: 2}.reject{|k, v| v == 1} # => {:b => 2}

或显式破坏性赋值:

{a: 1, b: 2}.select{|(k, v)| k == :a} # => {:a => 1}

我预计,当我传递一个一元 block 时,整个 [key, value] 数组都会被传递,但实际上,似乎传递了键:

{a: 1}.select{|e| p e} # => Prints `:a`  (I expected `[:a, 1]`)

为什么会这样?对于其他 Hash 实例方法,如 map,将传递整个 [key, value] 数组。

如果它专门设计用于与二进制 block 相比对一元 block 的工作方式不同,那么我可以理解它是有用的。但是,然后我不明白为什么上面带有显式破坏性赋值的情况会按原样工作。并且没有找到任何提及此类规范的文档。

编辑 {a: 1, b: 2}.reject{|(k, v)| 结果有误v == 1}。此处更正:

{a: 1, b: 2}.reject{|(k, v)| v == 1} # => {:a=>1, :b=>2} (not `{:b=>2}`)

现在,这也表明 (k, v)key,而不是 [key, value],所以 v 始终为 nil。比照。 Darek Nędza 的评论。

最佳答案

它实际上总是传递两个参数。

您所观察到的只是 proc 和 lambda 处理多余参数的方式之间的区别。 block (Procs,除非你另外告诉 Ruby)表现得好像它有一个额外的 splat 并丢弃多余的参数,而 lambdas(和方法对象)由于不正确的元数而拒绝调用者。

演示:

>> 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>'

顺便说一句,因为它在评论中被提及:map,相比之下,实际上传递了一个参数。它被分配给两个不同的变量,因为您可以在赋值运算符的右侧使用一个数组来分配多个变量,但它实际上一直是一个参数。

演示:

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

并且在进一步更改 pl 后定义:

>> 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>'

关于ruby - 为什么 Hash#select 和 Hash#reject 将 key 传递给一元 block ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20861502/

相关文章:

c++ - 如何生成伪随机 32 字节字符串以用作加密哈希函数中的盐?

javascript - 哈希数组上的 Handlebars JS

ruby - 使用 ruby​​ gmail api v0.9 发送电子邮件

Ruby 通过拖放到 rb 脚本接受参数

ruby 鞋子 : counting the amount of times a value occurs in an Array

ruby - 如何在 ruby​​ 中以简单而强大且可移植的方式以可验证的方式签署文本?

ruby - Net::HTTP.start 适用于 127.0.0.1 但不适用于 'localhost' 。为什么?

linux - 结束 Linux block 设备驱动程序中的 I/O 上下文

CSS "display: inline-block"拒绝断行

html - 如何居中 - 显示 :block/inline-block