Project

General

Profile

Actions

Feature #17398

closed

SyntaxError in endless method

Added by zverok (Victor Shepelev) 12 months ago. Updated 7 months ago.

Status:
Closed
Priority:
Normal
Assignee:
-
Target version:
-
[ruby-core:101475]

Description

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.


Files

Updated by mame (Yusuke Endoh) 12 months 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) 11 months 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) 11 months 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) 11 months 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) 11 months ago

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

https://gist.github.com/mame/0773bf3938e046e2b608de5fb2a826c8

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) 8 months ago

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

Pros

  • More intuitive / consistent / natural

Cons

  • Duplicated syntax rules
  • Even more complex syntax

If I were young, I would add mame (Yusuke Endoh)'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.

Matz.

Updated by matz (Yukihiro Matsumoto) 7 months ago

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

Matz.

Actions #9

Updated by mame (Yusuke Endoh) 7 months 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]

Actions

Also available in: Atom PDF