Reputation: 1725
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?
Upvotes: 0
Views: 873
Reputation: 19938
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
Upvotes: 4
Reputation: 72186
With or without parenthesis, Array#select
doesn't accept any regular arguments. It, however accepts a block argument but the blocks associated with a method call are always placed after the parenthesis, not inside them.
Consequently, the call:
a.select {|v| v.is_a? Integer }
can also be written with parenthesis as:
a.select() {|v| v.is_a? Integer }
Upvotes: 1
Reputation: 2614
Round brackets are a way to pass arguments to a method while the squiggly brackets (or do/end) are a way to pass a block to a method. They are not interchangeable.
Squiggly brackets can also be used to create a hash in ruby, which can cause some confusion.
Some ruby methods can take arguments and a block in which case you can use round brackets before the squiggly brackets: E.G.
open("ChangeLog") { |f|
f.slice_before(/\A\S/).each { |e| pp e }
}
Upvotes: 2