arraysrubyglobruby-1.9.3

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


Dir.glob("*.txt") {|f| p f} prints filenames.

Dir.glob("*.txt").sort {|f| p f} fails with an ArgumentError.

Dir.glob("*.txt").sort.each {|f| p f} prints filenames in alphabetical order.

Why does the second one fail? Better yet, why does the first one work, with or without the .each?

(Inspired by Alphabetize results of Dir.glob. Not a duplicate of Dir.glob with sort issue because the "third one" already answers that one's question.)


Solution

  • The other answer is correct, but I think there is a deeper explanation. When you have a block after a method call, like Dir.glob("*.txt") {|f| p f}, the block is an (optional) argument to the method. In the definition of Dir.glob, there is a yield statement that runs the block.

    When you chain the methods, like in Dir.glob("*.txt").sort {|f| p f}, the block becomes an argument to the sort method instead of the glob method. sort can also take a block to define a comparison, but this block doesn't make sense in that context.

    Chaining each to get Dir.glob("*.txt").sort.each {|f| p f} makes the block an argument to the each method, which uses it like glob does (running the block for each argument).