I'm having some trouble understanding why I can't call select with round brackets.
a = [1,2,3]
a.select {|v| v.is_a?(Integer)} # works
a.select({|v| v.is_a?(Integer)}) # syntax error, unexpected '|', expecting '}
As far as I can tell select is a regular method.
Array.method_defined? :select # true
Array.method_defined? :is_a? # true
I though round brackets are optional for methods in ruby.
In the case below round brackets make no difference.
a.reverse() == a.reverse #true
I'm using ruby 2.2.1.
Any ideas?
You cannot pass a block with such a synatx, you would have to do something like this:
a.select(&lambda { |v| v.is_a?(Integer) })
but normally you would just do
a.select { |v| v.is_a?(Integer) }
which is the same as
a.select() { |v| v.is_a?(Integer) }
i.e the block is outside the method parameters.
You could also use the 'stabby' lambda syntax:
is_a_integer = ->(v) { v.is_a?(Integer) }
a.select(&is_a_integer)
So if you want to pass a block as an argument you need to prefix with &
, but usually you would have the block outside the parameters for atheistic reasons.
Also notice the difference between these to method signatures and the way they are called:
def call(&block)
yield
end
call { 1 } # => 1
call(lambda { 1 }) # => ArgumentError
call(&lambda { 1 }) # => 1
and
def call(block)
block.call
end
call { 1 } # => ArgumentError
call(lambda { 1 }) # => 1
call(&lambda { 1 }) # => ArgumentError
This is because lambda (and Procs) are objects hence we can do #call
to evaluate them, but blocks are not and can be evaluated using the yield
keyword. There is more information in this blog post.
lambda { 1 }.class # => Proc