Feature #17398


SyntaxError in endless method

Added by zverok (Victor Shepelev) about 2 years ago. Updated over 1 year ago.

Target version:


This works:

def foo() = puts("bar")

This does not:

def foo() = puts "bar"
#                ^ syntax error, unexpected string literal, expecting `do' or '{' or '('

Is this intentional or accidental? Not sure how it is reasoned.


Updated by mame (Yusuke Endoh) about 2 years ago

The body of an endless method must be an expression (called "arg" in the syntax rules of parse.y). puts("bar") is an expression, but puts "bar" is a statement (called "command" in the syntax rules).

I think it could be a bit confusing, but I have no idea whether we can/should allow a statement as a body of an endless method.

Updated by zverok (Victor Shepelev) about 2 years ago

@mame (Yusuke Endoh) Hmm, haven't thought about it from this perspective... Can you please explain a bit? As far as I can see, in, say, assignment context it behaves like an expression:

result = puts 'foo'
# prints "foo", result = nil

I am just trying to describe the behavior in full for the next installment of my changelog and this aspect is quite confusing for me... Though, it is not endless-method specific, as far as I can see:

y = sin x # OK
y = 1 + sin x
#           ^ unexpected local variable or method, expecting `do' or '{' or '('

What's the "rule of thumb" to understand this better?

Updated by Eregon (Benoit Daloze) about 2 years ago

Conceptually, according to the typical definition in computer science, both puts("bar") and puts "bar" are expressions (i.e., they return a value, and if it was some other method than puts it would also not always be nil).
It might be slightly less clear for e.g. a = 42 (it's still an expression, it still returns a value), but I think puts "bar" is clear that it should be the same as puts("bar"), except for precedence.

So it's probably going to be very difficult to explain the actual condition, other than showing specific examples.

Updated by austin (Austin Ziegler) about 2 years ago

Eregon (Benoit Daloze) wrote in #note-3:

So it's probably going to be very difficult to explain the actual condition, other than showing specific examples.

Endless methods definitions don’t support poetry mode?

Updated by mame (Yusuke Endoh) about 2 years ago

The following patch allows def foo() = puts "bar". It brings no parser conflict.

However, it is not perfect. private def foo() = puts "foo" does not parse.
private var = puts "bar" is not allowed neither, so I have no idea how to allow this.

Updated by matz (Yukihiro Matsumoto) almost 2 years ago

  • Tracker changed from Bug to Feature
  • Backport deleted (2.5: UNKNOWN, 2.6: UNKNOWN, 2.7: UNKNOWN)


  • More intuitive / consistent / natural


  • Duplicated syntax rules
  • Even more complex syntax

If I were young, I would add @mame's patch. I did similar decisions many times in the past. But Ruby has been mature and complex, I now feel reluctant. Let us consider this idea for a while.


Updated by matz (Yukihiro Matsumoto) over 1 year ago

I have considered this issue for a while and concluded it should be merged to be consistent with the assignment statement.


Actions #9

Updated by mame (Yusuke Endoh) over 1 year ago

  • Status changed from Open to Closed

Applied in changeset git|31794d2e733e081e4e221f27aff6380393981681.

parse.y: Allow "command" syntax in endless method definition

This change allows def hello = puts "Hello" without parentheses.

Note that private def hello = puts "Hello" does not parse for
technical reason.

[Feature #17398]


Also available in: Atom PDF