Space before parentheses leads to syntax error

#1

I write a method

def additionner (x,y) puts (x * y) end additionner(2,7)

It works, but if I make a space after calling the method, it doesn’t work, why?

def additionner (x,y)

puts (x * y)

end

additionner (2,7)

(repl):4: syntax error, unexpected ‘,’, expecting ‘)’
additionner (2,7)

in version: ruby 2.5.5p157 (2019-03-15 revision 67260) [x86_64-linux]

#2

Hello @kouty,

The reason is positional arguments.

2 Likes
#3

Thank’s so much. I will read the link.

#4

Now I did read it, it is not clear how the space between the method name and the parenthesis makes a trouble regarding the arguments. What is the difference between method (1, 2) and method(1, 2)? Is the space an argument?

#5

See this link

#6

When you type:
(5 + 5) it’s evaluated first.

When you type:
puts (5 + 5) literally the same thing happens. You pass 10 to puts.

But when you type:
puts (5, 5), Ruby raises SyntaxError because it can’t be evaluated… It’s like writing 5, 5 without any method name. Ruby doesn’t know that it’s passed to the method call.

You can either do puts 5, 5 or do puts(5, 5). Both will work the same way. For method chaining though:

puts 5.class     # => nil (and writes Integer to STDOUT)
puts(5).class    # => NilClass (and writes 5 to STDOUT)
puts (5).class   # => nil (and writes Integer to STDOUT)

On the first line, we are calling 5.class first, which returns Integer, which is then passed to Kernel#puts which prints Integer and returns nil.

On the second line, we are calling Kernel#puts with 5, which displays 5, and returns nil. That’s why the second line returns NilClass because it’s like running nil.class.

On the third line, when we write (5) it returns 5, which is an Integer object. We then call the class method on 5, which obviously returns Integer. We are then passing this to the Kernel#puts, which writes Integer to the standard output, and returns nil.

Another example which might help:

puts(5 + 5 / 2)    # => 7
puts(5.+(5)./(2))  # => 5
puts((5 + 5) / 2)  # => 5

And that’s the reason my friend you get SyntaxError when you write additioner (x, y) puts (x * y) in your code…

Hope this helps!

2 Likes
#7

Had the same problem when I was first starting Ruby… a few days ago. Nice to see an explanation of the problem.

#8

Thanks so much.

I need to understand. Your example with dots is not clear for me.

#9

When you are calling 5 + 5, you are calling the + method.
So you are basically doing:
5.+(5)

This is called syntactical sugar or syntactic shorthand.


Let’s consider an advanced [useless] example to help you clarify more. You might know there’s no + method on nil:

nil + nil

Output:

Traceback (most recent call last):
        2: from /home/sourav/.irb:350:in `<main>'
        1: from (irb):1
NoMethodError (undefined method `+' for nil:NilClass)

Now let’s define the method:

#!/usr/bin/ruby -w

# Return the arg when you call + method:
NilClass.define_method(:+) { |arg| arg }    # => :+

p nil + nil                                 # => nil
p nil.+(nil)                                # => nil

p nil + nil + 'Hello World'                 # => "Hello World"
p nil.+(nil).+('Hello World')               # => "Hello World"

p (nil + nil) + 'Hello World'               # => "Hello World"

We literally patched the NilClass so that + method can be called on the NilClass objects… Did you see there are that there are many ways to call the method. Here the nil + nil is syntactic shorthand for nil.+(nil)
That means when you call:

puts 5.+(5)./(2)
# Similar to puts (5 + 5) / 2
# Or puts 5.+(5).div(2)

You start with 5, add 5 (and return 10), divide that with 2 (and return 5), which is passed to puts.
That’s the role of the parentheses here.

You can also do:

(puts 5, 5)

And ruby evaluates the parentheses code normally. That’s why you won’t raise any SyntaxError.
But writing puts (5, 5) means you are trying to evaluate 5, 5 which makes few sense to the Ruby interpreter…

Hope it clarifies my answer above!

1 Like
#10

Thank you Sourav. Very good answer.

1 Like