Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Confused when to use Parentheses vs Blocks in Ruby

Tags:

ruby

At Surface, Ruby appears to be quite similar to other object orieinted languages like Java,Php,C etc.

but, things get bit weird when we start to bump into blocks.

for example, this works

(0...8).max()
 => 7 

but this doesn't

(0...8).map(puts "hello world")
hello world
ArgumentError: wrong number of arguments(1 for 0)

Apprantly, map method doesn't take arguments but takes blocks, so passing replacing () with {} fix the error.

(0...8).map{puts "hello world"}
hello world
hello world
hello world
hello world
hello world
hello world
hello world
hello world
 => [nil, nil, nil, nil, nil, nil, nil, nil] 

And then, there are some methods should take both -- blocks & arguments

8.downto(1){puts "hello world"}
hello world
hello world
hello world
hello world
hello world
hello world
hello world
hello world
 => 8 

The problem I have is the confusion on if I should be using () , {} or both on given method. On what basis it gets decided?

  • Is it fixed on per method basis & I just to have remember what the method takes(Blocks or params)?
  • Or is there any other logical reasoning on basis of which it gets decided, if the method takes blocks{} or params()?

Please help me understand

like image 959
CuriousMind Avatar asked Jan 27 '26 18:01

CuriousMind


2 Answers

Parenthesis after method calls are actually optional.

(0...8).map{puts "hello world"} is equivalent to (0...8).map() {puts "hello world"}

So you don't really replace them.

The acceptance of blocks is entirely up to the method, they can be specified in the method declaration:

def method(param, &block)
  block.call
end

which will allow the block to be accessed as a variable from within the method, and be invoked via block.call for example.

They can also be used implicitely via the use of the yield keyword:

def method(param)
  yield
end

So you have to refer to the API documentations to be sure what is accepted or not.

like image 148
SirDarius Avatar answered Jan 30 '26 11:01

SirDarius


It should be documented in the API of the method.

If there is a method that accepts an argument, the block usually is optional - in such a case it is used to "refine" the way the method works - e.g. Hash.new, that may accept an argument (the default hash value) and a block, which is used to do smart things during key-value initialization. But most of the methods that require a block, don't accept an argument, e.g. Array#select or Array#map.

like image 24
Aleksander Pohl Avatar answered Jan 30 '26 12:01

Aleksander Pohl



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!