Reputation: 168199
Some block methods such as inject
can optionally take a symbol instead of a block:
%w[a b c].inject(&:+)
# => "abc"
%w[a b c].inject(:+)
# => "abc"
%w[a b c].inject("", :+)
# => "abc"
while other block methods such as map
cannot:
%w[a b c].map(&:upcase)
# => ["A", "B", "C"]
%w[a b c].map(:upcase)
# => ArgumentError: wrong number of arguments (1 for 0)
Why can't the latter take a symbol?
Upvotes: 2
Views: 689
Reputation: 168199
For inject
, a block (or a substitute) is obligatory. If it weren't passed a block, then there has to be at least one argument, the last argument has to be a symbol, and the block would be constructed out of it. Whatever the arity, there is no ambiguity; the last argument is used to construct a block when the block is lacking.
For map
, a block is optional. When there is no block given, then the return value would be an Enumerator
instance. Hence, from the information whether a block was passed or not, it cannot be decided whether the last argument should be used to construct a block.
In the particular case of map
, it does not take an argument, so there is a sense in saying that an extra argument should be taken as a block, but it makes things complicated to judge whether that last argument is to be taken as a block depending on the arity. And it also loses the future possibility of changing the arity of the method.
Upvotes: 1
Reputation: 230461
It's just a special handling for this special case in some methods and lack of such handling in the others.
Upvotes: 0
Reputation: 44370
Not sure but i know this operator &
to_proc, inject()
method accept 2 args first accum second proc
, but map()
accept only one args proc
or block
. In inject()
first args(accum) can be first item in enum.
Upvotes: 0