Project

General

Profile

Feature #16746

Endless method definition

Added by mame (Yusuke Endoh) about 2 months ago. Updated 17 days ago.

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

Description

Ruby syntax is full of "end"s. I'm paranoid that the ends end Ruby. I hope Ruby is endless.

So, I'd like to propose a new method definition syntax.

def: value(args) = expression

As you see, there is no "end".

Examples.

def: hello(name) =
  puts("Hello, #{ name }")

hello("endless Ruby") #=> Hello, endless Ruby
def: inc(x) = x + 1

p inc(42) #=> 43
x = Object.new

def: x.foo = "FOO"

p x.foo #=> "FOO"
def: fib(x) =
  x < 2 ? x : fib(x-1) + fib(x-2)

p fib(10) #=> 55

Limitations.

  • def: foo x = x is invalid; the parentheses for formal arguments are mandatory.
  • private def: foo = x is invalid; this method definition cannot be an method argument.

A patch is attached. No conflicts.


Files

endless-method-definition.patch (2.47 KB) endless-method-definition.patch mame (Yusuke Endoh), 04/01/2020 03:26 AM

Related issues

Related to Ruby master - Feature #5054: Compress a sequence of endsRejectedtechnohippy (Yasushi ANDO)Actions
Related to Ruby master - Feature #5065: Allow "}" as an alternative to "end"RejectedActions
Related to Ruby master - Feature #12241: super endRejectedActions

Updated by shevegen (Robert A. Heiler) about 2 months ago

I'm paranoid that the ends end Ruby. I hope Ruby is endless.

With so many cancellations of events this year, we may not want to
want to jinx ruby too much for the 3.0 release this year because
then 3.0 itself may become the endless version! (Or we could skip
it, like PHP skipped a version ... I was briefly tempted to propose
this on this special day today, but I really don't want to jinx
it. I do, however had, remember matz joking last year about unforeseen
events ... now I hope I just did not jinx it!)

#2

Updated by shyouhei (Shyouhei Urabe) about 2 months ago

#3

Updated by shyouhei (Shyouhei Urabe) about 2 months ago

  • Related to Feature #5065: Allow "}" as an alternative to "end" added
#4

Updated by shyouhei (Shyouhei Urabe) about 2 months ago

#5

Updated by mame (Yusuke Endoh) about 2 months ago

  • File deleted (endless-method-definition.patch)

Updated by matz (Yukihiro Matsumoto) about 2 months ago

  • Tags deleted (joke)

I totally agree with the idea seriously, (far better than #5054, #5065 and #12241) but don't like the syntax. First I thought

def foo(a) = expression

But it is a conflicting syntax.

Matz

Updated by mame (Yusuke Endoh) about 2 months ago

  • Assignee set to nobu (Nobuyoshi Nakada)
  • Status changed from Open to Assigned

Okay seriously. You should have written many "simple" method definitions that have only one expression:

# three-line style
def value
  @val
end

# one-line style
def value; @val; end

Surprisingly, according to the following rough estimate of ruby/ruby code base, this kind of simple method definitions account for 24% of the entire method definitions.

# three-line style: 8570
p Dir.glob("**/*.rb").map {|f| File.binread(f).scan(/^(\s*)def.*\n.*\n\1end$/).size }.sum

# one-line style: 949
p Dir.glob("**/*.rb").map {|f| File.binread(f).scan(/^\s*def.*;[^;]*;\s*end$/).size }.sum

# all method definitions: 39502
p Dir.glob("**/*.rb").map {|f| File.binread(f).scan(/\bdef\b/).size }.sum

# propotion = (8570 + 949) / 39502 = 24%

I agree that def foo(a) = expression is best, but I cannot implement it. Pass it to nobu (Nobuyoshi Nakada) .

Updated by ka8725 (Andrey Koleshko) about 2 months ago

matz (Yukihiro Matsumoto) wrote in #note-7:

I totally agree with the idea seriously, (far better than #5054, #5065 and #12241) but don't like the syntax. First I thought

def foo(a) = expression

But it is a conflicting syntax.

Matz

How about this:

def foo(a):
  expression

Updated by ruurd (Ruurd Pels) about 2 months ago

shevegen (Robert A. Heiler) wrote in #note-1:

I'm paranoid that the ends end Ruby. I hope Ruby is endless.

Like - basically - a snake biting its own tail amirite ;-)

Updated by ioquatix (Samuel Williams) about 2 months ago

Have you considered adopting Python's whitespace sensitive indentation?

def hello(name):
  puts("Hello, #{ name }")

hello("endless Ruby") #=> Hello, endless Ruby

Updated by mame (Yusuke Endoh) about 2 months ago

nobu (Nobuyoshi Nakada) implemented def foo(arg) = expression in one night. Also, it allows private def: foo = 42. Perfect.

https://github.com/ruby/ruby/pull/2996

matz (Yukihiro Matsumoto) We are ready to perform the experiment.

Updated by retro (Josef Šimánek) about 2 months ago

To be honest, I'm a little confused if this is serious proposal now, since it probably started as a joke and got some attention already at GitHub pull request (https://github.com/ruby/ruby/pull/2996) with mixed attitude.

Anyway for one-line method definitions I like part of https://bugs.ruby-lang.org/issues/5065 (originally at https://bugs.ruby-lang.org/issues/729, that was rejected because of invalid reason for the change request AFAIK). It looks "nature" to me since similar syntax is already available for blocks and often is used for one-liners. Ideally scope this syntax only for one-liners.

# original
def value; @val; end

# proposed - is that conflicting one?
def value { @val }

Alternatively, since the only use-case I have found in this issue is getter having different method and instance variable names, what about to support this out of attr_reader (and all attr_* friends)?

# few ideas
attr_reader :value, for: :val # reads as -> attribute reader "value" for instance variable "val", probably impossible for multiple definitions on one line
attr_reader value: :val # this would support multiple definitions on one line

Updated by osyo (manga osyo) about 2 months ago

Using the assignment operator like def value = expects the following behavior.

value = 42
# Refer to variables outside scope
def hoge = value
hoge # => 42

However, currently it is error: undefined local variable or method.
In the Endless method definition, the scope seems ambiguous, so I need to discuss whether to capture variables.

Updated by matz (Yukihiro Matsumoto) about 1 month ago

I'd like to experiment with this new syntax. We may find drawbacks in the future, but to find them, we need to experiment first.

Matz.

#17

Updated by nobu (Nobuyoshi Nakada) about 1 month ago

  • Status changed from Assigned to Closed

Applied in changeset git|e8f53692ca7d65c92bde6d5bc6a1aea492915d9f.


Endless method definition [Feature #16746]

Updated by retro (Josef Šimánek) about 1 month ago

I'd like to experiment with this new syntax. We may find drawbacks in the future, but to find them, we need to experiment first.

If this was merged as an experiment, shouldn't it raise warning on usage (same as pattern matching does)?

Updated by nobu (Nobuyoshi Nakada) about 1 month ago

It is not easy to control parsing time warnings, and bothers tests.

Updated by Eregon (Benoit Daloze) about 1 month ago

nobu (Nobuyoshi Nakada) wrote in #note-19:

It is not easy to control parsing time warnings, and bothers tests.

The exact same applies to pattern matching and yet we added a warning there.
Testing/suppressing the warning is an eval away.

I think it's important for new experimental syntax to warn about it, especially when the right semantics are unclear.

My opinion is it should not capture, def/class/module never captured outside scopes and that shouldn't change.

Updated by Eregon (Benoit Daloze) 17 days ago

Is it intended to allow multi-line definitions in this style?
I think we should not, and only single-line expressions should be allowed.

I think that's not the original purpose of this ticket and rather an incorrect usage of this new syntax,
e.g., https://twitter.com/devoncestes/status/1256222228431228933

Also available in: Atom PDF