Reputation: 2520
At the end of this here block,
entries.map do |key_val|
"[#{key_val.first}] \"#{key_val.last}\""
end.sort.join("\n")
I see sort
tacked onto end
. Is this common? What is it doing? I've never seen end
being treated as the value of return
. Is that what's happening? The map
inside the method returns an array and you can grab onto it with end
?
Upvotes: 2
Views: 93
Reputation: 95315
Don't be fooled by the syntax. The block defined by do
...end
is just a special type of argument passed to the map
call. It doesn't go in parentheses or otherwise look like it's an argument, but it is one; the syntax of the method call runs all the way to the end
. So when you stick a .
method on the end
, you're calling that method on the return value of the map
call - which is, hopefully, an Array.
There are various ways to rewrite so that it's clearer to those less familiar with Ruby's syntax oddities. For instance, add some parentheses to make the precedence explicit, as suggested by @AndrewMarshall:
(entries.map do |key_val|
"[#{key_val.first}] \"#{key_val.last}\""
end).sort.join("\n")
Or create a Proc out of the block and pass it inside the method call parentheses using &
, so the chained method call is in a more familiar place syntactically (in this one I also rewrote the block itself in what I think is a cleaner style):
block = proc do |key, val|
%([#{key}] "#{val}")
end
entries.map(&block).sort.join("\n")
You can combine that with removing a level of chaining, as in AJcodez's answer:
intermediate_array = entries.map(&block)
intermediate_array.sort.join("\n")
Or eliminate the chaining entirely:
mapped = entries.map(&block)
sorted = mapped.sort
joined = sorted.join("\n")
return joined
Basically, the fact that the method call syntax is attached to the end
is just a quirk of Ruby's block-passing syntax (and, of course, also works if you attach the method call to the closing brace of a {
...}
block). You're just calling a method (that happens to take a block, which you supply) and then calling a second method on the return value of the first.
Upvotes: 6
Reputation: 1
I do not believe calling a method on 'end' is common practice. I have been learning ruby for about 2 months now, and have not once come across that syntax.
Upvotes: 0
Reputation: 34206
In ruby everything returns a value, including blocks. Same as:
intermediate_array = entries.map do |key_val|
"[#{key_val.first}] \"#{key_val.last}\""
end
intermediate_array.sort.join("\n")
I prefer the above syntax choice, but both are perfectly valid for the interpreter.
Upvotes: 0