Project

General

Profile

Feature #13581

Syntax sugar for method reference

Added by americodls (Americo Duarte) 7 months ago. Updated about 2 months ago.

Status:
Open
Priority:
Normal
Assignee:
-
Target version:
-
[ruby-core:81282]

Description

Some another programming languages (even Java, in version 8) has a cool way to refer a method as a reference.

I wrote some examples here: https://gist.github.com/americodls/20981b2864d166eee8d231904303f24b

I miss this thing in ruby.

I would thinking if is possible some like this:

roots = [1, 4, 9].map &Math.method(:sqrt)

Could be like this:

roots = [1, 4, 9].map Math->method

What do you guys thinking about it?


Related issues

Is duplicate of Ruby trunk - Feature #12125: Proposal: Shorthand operator for Object#methodOpen

History

#1 [ruby-core:81283] Updated by Hanmac (Hans Mackowiak) 7 months ago

that might collide with -> {} a lambda syntax
so i think the chances are low that ruby gets something like that.

so ruby probably does think its "Math(->sqrt)" and thats a Syntax error.

#2 [ruby-core:81285] Updated by americodls (Americo Duarte) 7 months ago

The -> was just a suggestion... Could be another symbol or combination of symbols like Math->>sqrt, Math=>>sqrt, Math+>sqrt, Math$>sqrt, Math:>sqrt, etc
I just think could have another way to write it than not a method calling with a symbol as argument, something more concise and expressive.

Hanmac (Hans Mackowiak) wrote:

that might collide with -> {} a lambda syntax
so i think the chances are low that ruby gets something like that.

so ruby probably does think its "Math(->sqrt)" and thats a Syntax error.

#3 [ruby-core:81286] Updated by Hanmac (Hans Mackowiak) 7 months ago

my current thinking is if that short form should do symbol support.

if Math->sym should be supported, than the normal variant need to be Math->:sqrt

i currently think if we also could abuse the call method.

so we could harness "Math.(:sqrt)" into something.

#4 [ruby-core:81296] Updated by americodls (Americo Duarte) 7 months ago

Why the version with symbol (Math->:sqrt) needs to be supported?

#5 [ruby-core:82556] Updated by matz (Yukihiro Matsumoto) 3 months ago

I am for adding syntax sugar for method reference. But I don't like proposed syntax (e.g. ->).
Any other idea?

Matz.

#7 [ruby-core:82580] Updated by Hanmac (Hans Mackowiak) 3 months ago

nobu (Nobuyoshi Nakada) wrote:

obj\.method

i am not sure about that:

obj\
.method

is already valid ruby code, so i am not sure

PS: when using "&obj.method(:symbol)" should that be optimized if able?

#8 [ruby-core:82582] Updated by zverok (Victor Shepelev) 3 months ago

I am for adding syntax sugar for method reference. But I don't like proposed syntax (e.g. ->).
Any other idea?

In my pet projects, I often alias method as m. It is readable enough, short enough and easy to remember, once you've seen it:

roots = [1, 4, 9].map(&Math.m(:sqrt))
%w[foo bar baz].each(&m(:puts))

..., and, if introduced into language core, can be easily backported to earlier versions (through something like backports or polyfill gem).

Another weird-ish idea, following the first one closely, is .:, which (for me) looks guessable:

[1,2,3].map(&Math.:sqrt)
%w[foo bar baz].each(&.:puts)

(BTW, object-less form should also be considered, when weighing proposals, don't you think?)

#9 [ruby-core:82583] Updated by k0kubun (Takashi Kokubun) 3 months ago

Another idea: &obj:method

It just puts receiver between & and : from existing one. I'm not sure it conflicts with existing syntax or not but I feel it's consistent with &:foo syntax.

roots = [1, 4, 9].map(&Math:sqrt)
%w[foo bar baz].each(&self:puts)

#10 [ruby-core:82584] Updated by Hanmac (Hans Mackowiak) 3 months ago

k0kubun (Takashi Kokubun) wrote:

Another idea: &obj:method

hm i like that idea, but think that might be a bit conflicting, that depends on if obj is an object or not?

obj = Object.new
obj:method #=> syntax error

but notice that: (xyz not known)

xyz:method #=> undefined method 'xyz' for main

it thinks that it's xyz(:method)

#11 [ruby-core:82586] Updated by k0kubun (Takashi Kokubun) 3 months ago

Oh, I'm so sad to hear obj:method (without &) is already valid. I still have hope to have it only when it's put with & in the last of arguments because that case is not valid for now.

irb(main):001:0> def obj(method); method; end
=> :obj
irb(main):002:0> obj:method
=> :method
irb(main):003:0> obj(&obj:method)
SyntaxError: (irb):3: syntax error, unexpected tSYMBEG, expecting keyword_do or '{' or '('
obj(&obj:method)
         ^
        from /home/k0kubun/.rbenv/versions/2.4.1/bin/irb:11:in `<main>'
irb(main):004:0> obj(&(obj:method))
SyntaxError: (irb):4: syntax error, unexpected tLABEL
obj(&(obj:method))
          ^
        from /home/k0kubun/.rbenv/versions/2.4.1/bin/irb:11:in `<main>'
irb(main):005:0> obj &obj:method
SyntaxError: (irb):5: syntax error, unexpected tSYMBEG, expecting keyword_do or '{' or '('
obj &obj:method
         ^
        from /home/k0kubun/.rbenv/versions/2.4.1/bin/irb:11:in `<main>'
irb(main):006:0> obj &(obj:method)
SyntaxError: (irb):6: syntax error, unexpected tLABEL
obj &(obj:method)
          ^
        from /home/k0kubun/.rbenv/versions/2.4.1/bin/irb:11:in `<main>'

I've never seen a person who writes a(:b) as a:b (without space or parenthesis before ":") and personally I don't expect &a:b to be &a(:b).

#12 [ruby-core:82588] Updated by nobu (Nobuyoshi Nakada) 3 months ago

Hanmac (Hans Mackowiak) wrote:

i am not sure about that:

obj\
.method

is already valid ruby code, so i am not sure

It's different at all.
My example is a token \., do not split.

PS: when using "&obj.method(:symbol)" should that be optimized if able?

Probably, but it's not possible to guarantee that it will return the method object.

#13 [ruby-core:82589] Updated by nobu (Nobuyoshi Nakada) 3 months ago

k0kubun (Takashi Kokubun) wrote:

Another idea: &obj:method

Consider more complex example, &(obj.some.method(args)):method, not only a simple reciever.
& and : are separated too far.

#14 [ruby-core:82590] Updated by Hanmac (Hans Mackowiak) 3 months ago

my idea for optimising &obj.method(:symbol)
is that it already creates a proc (object) without going over a Method object,
i don't know if that would be an good idea for that.

#15 [ruby-core:82597] Updated by mrkn (Kenta Murata) 3 months ago

How about obj.{method_name} for the syntax sugar of obj.method(:method_name)?

#16 [ruby-core:82611] Updated by zverok (Victor Shepelev) 3 months ago

Another pretty unholy idea: resemble the way Ruby docs document the methods:

[1,2,3].map(&Math#sqrt)
%w[foo bar baz].each(&#puts)

Yes, it conflicts with comment syntax, but in fact, no sane person should join the comment sign immediately after non-space symbol.

And we already have parsing ambiguities like this:

  • foo -bar → foo(-bar);
  • foo - bar → foo.-(bar).

#17 [ruby-core:82612] Updated by tom_dalling (Tom Dalling) 3 months ago

What about triple colon :::?

[1,2,3].map(&Math:::sqrt)
[1,2,3].each(&:::puts)

:: is for looking up constants, so it kind of makes sense that ::: is for looking up methods.

#18 [ruby-core:82614] Updated by tom-lord (Tom Lord) 3 months ago

Consider the following:

def get_method(sym, object = Object)
  object.send(:method, sym)
end

This allows us to write code like:

[1, 4, 9].map &get_method(:sqrt, Math)

So as an idea, how about introducing some syntax sugar for the above - such as:

[1, 4, 9].map &~>(:sqrt, Math)

Where in general, ~> (or whatever) could be the "method lookup operator".

For example, this would yield:

~>(:puts)       # => #<Method: Class(Kernel)#puts>
~>(:sqrt, Math) # => #<Method: Math.sqrt>
~>(:sqrt)       # => NameError: undefined method `sqrt' for class `#<Class:Object>'

#19 Updated by k0kubun (Takashi Kokubun) 2 months ago

  • Is duplicate of Feature #12125: Proposal: Shorthand operator for Object#method added

#20 [ruby-core:83365] Updated by americodls (Americo Duarte) about 2 months ago

matz (Yukihiro Matsumoto) wrote:

I am for adding syntax sugar for method reference. But I don't like proposed syntax (e.g. ->).
Any other idea?

Matz.

What do you think about: Kernel:puts, Kernel~>puts, Kernel:>puts ?

Also available in: Atom PDF