sawa
sawa

Reputation: 168199

Passing symbol to block methods

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

Answers (3)

sawa
sawa

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

Sergio Tulentsev
Sergio Tulentsev

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

Roman Kiselenko
Roman Kiselenko

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

Related Questions