为什么 Dir.glob("*.txt").sort 也需要 .each?

Why does Dir.glob("*.txt").sort also need .each?

Dir.glob("*.txt") {|f| p f} 打印文件名。

Dir.glob("*.txt").sort {|f| p f} 失败并出现 ArgumentError。

Dir.glob("*.txt").sort.each {|f| p f} 按字母顺序打印文件名。

为什么第二个失败了?更好的是,为什么第一个工作,有或没有 .each?

(受到 Alphabetize results of Dir.glob. Not a duplicate of 的启发,因为 "third one" 已经回答了那个问题。)

第二个失败了,因为sort {|f| p f}真的没有意义。您与 sort 一起使用的块应该 "return -1, 0, or +1" 并采用两个参数(要比较的元素)但是您的块采用一个参数并且 returns 该参数因为 p str returns str.

第三个很好,因为 sort 的默认比较器块相当于说:

sort { |a, b| a <=> b }

所以 .sort.each 很有道理。

如果您在第二个示例中使用 sort 期望的那种块:

Dir.glob("*.txt").sort {|a, b| a <=> b }

然后事情会更好。或者,如果您想按升序对事物进行排序,则可以省略该块:

Dir.glob('*.txt').sort

另一个答案是正确的,但我认为还有更深层次的解释。当您在方法调用之后有一个块时,例如 Dir.glob("*.txt") {|f| p f},该块是该方法的一个(可选)参数。在Dir.glob的定义中,有一个运行块的yield语句。

当你链接这些方法时,就像在 Dir.glob("*.txt").sort {|f| p f} 中一样,该块成为 sort 方法而不是 glob 方法的参数。 sort 也可以用一个块来定义比较,但是这个块在那个上下文中没有意义。

链接 each 得到 Dir.glob("*.txt").sort.each {|f| p f} 使块成为 each 方法的参数,它像 glob 一样使用它(运行 块对于每个参数)。