Why does Dir.glob("*.txt").sort also need .each?
The second one fails because sort {|f| p f}
really doesn't make sense. The block you use with sort
is supposed to "return -1, 0, or +1" and take two arguments (the elements to be compared) but your block takes one argument and returns that argument because p str
returns str
.
The third one is fine because sort
's default comparator block is equivalent to saying:
sort { |a, b| a <=> b }
so .sort.each
makes perfect sense.
If you use the sort of block that sort
expects in the second example:
Dir.glob("*.txt").sort {|a, b| a <=> b }
then things will work better. Or you could just leave out the block if you want to sorting things in ascending lexical order:
Dir.glob('*.txt').sort
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).