Project

General

Profile

Feature #11141

new syntax suggestion for abbreviate definition on block parameters in order

Added by neohunter (Arnold Roa) about 5 years ago. Updated about 5 years ago.

Status:
Rejected
Priority:
Normal
Assignee:
ruby-core
Target version:
-
[ruby-core:69134]

Description

One of the most commons things I do in Ruby are small block definitions:

x.each{|a| a}

One useful syntax introduced was the &:method that allows calling a method on a block if only one param is expected. It's a shortcut for a.each{|x|x.method}. I think it would be nice if Ruby had a syntax that allows me to not define the params that block would receive, but instead access them in order. For example:

x.each { $1 }

Let's suppose the block is waiting for two params, I normally do:

x.method {|a,b| a - b }

This syntax will allow us to use:

 x.method{ $1 - $2 }

So:

 x.each { p1.stg }
 x.each {|p1| p1.stg}
 x.each &:stg

would be the same.

Please consider $1 and $2 just as an example. I don't like the fact that they are global variables. It could be _1 or p1, for example:

x.method{ p1 - p2 } 
x.each{ p1 - p2 } == x.each {|p1, p2| p1 - p2 }

Or, as blocks already uses &:method it could be &:1. Or any other thing that you may consider more appropriated.

I think this syntax would be very nice for short block definitions, the downside is that it allows for bad practice on longer methods, but in the end, that's a decision that a programer should make.

Maybe this is not a valid reason, but I would like to point out that Regex is actually creating global vars as the results of match: $x vars. (for perl's historical reasons)

So why not introduce this into Ruby's syntax?

Personally I don't like either $1 nor p1. They are just the first quick things that come to my mind.

Updated by matz (Yukihiro Matsumoto) about 5 years ago

  • Status changed from Open to Rejected

We cannot use $1 etc. as they are already taken for Regexp match.
Short hand notation for block parameter itself is a nice idea though.

Matz.

Updated by nobu (Nobuyoshi Nakada) about 5 years ago

  • Description updated (diff)

What about @1?

Updated by neohunter (Arnold Roa) about 5 years ago

Yukihiro Matsumoto wrote:

We cannot use $1 etc. as they are already taken for Regexp match.
Short hand notation for block parameter itself is a nice idea though.

Matz.

Yes, I just use $1 as an example to explain the idea, by no means I think $1 would be a good choice as $ is for global variables and $1..2..3 are reserved for Regexp. The idea I wanted to point here is the short-hand syntax.

@1 is a good idea, but @ is used for instance variables. So I'm not sure if is the ideal.

On method definition we can use *args for multiple arguments, so what about *1, *2, *3?

x.method{ *1 - *2 }

Updated by nobu (Nobuyoshi Nakada) about 5 years ago

Arnold Roa wrote:

On method definition we can use *args for multiple arguments, so what about *1, *2, *3?

x.method{ *1 - *2 }

It has obvious ambiguity.
How will you interpret foo(*1), a splat or the short-hand syntax?

Updated by austin (Austin Ziegler) about 5 years ago

It gets a bit more line-noisy, but why not a couple of sigils? Maybe:

x.method { @[1] - @[2] }

Austin Ziegler * halostatue@gmail.com * austin@halostatue.ca
http://www.halostatue.ca/ * http://twitter.com/halostatue

Updated by rbjl (Jan Lelis) about 5 years ago

Nobuyoshi Nakada wrote:

What about @1?

I liked this one at first glance, but it might confuse people, because you could think the scoping would be similar to @instance variables.

Some brainstorming:

->{ puts $a, $b } # <- reasoning: $ does not mean global scope anyway

->{ puts 1st, 2nd } # <- interesting syntax trick

Updated by Hanmac (Hans Mackowiak) about 5 years ago

my problem i got with that new syntax is what does it do when i have blocks inside of blocks, specially with different arity count ...

like

{key1 => value1, key2 => value2}.each { |key, value|
  [obj1, obj2, obj3].each { |obj|

  }
}

when using that syntax:

{key1 => value1, key2 => value2}.each {
  [obj1, obj2, obj3].each {
    puts p1, p2 # what are the values of p1 and what specially are the values of p2 ?
  }
}

Updated by rbjl (Jan Lelis) about 5 years ago

Hans Mackowiak wrote:

my problem i got with that new syntax is what does it do when i have blocks inside of blocks, specially with different arity count ...

I'd say, such a implicit block parameters should only be possible for the most inner block. Somehow accessing the arguments of an outer block probably does not make the code better readable. However, having simple (unnested) blocks with implicit variables can improve the readability, because it is more concise. Like, for example, it is already possible with gsub:

"Ruby".gsub(/(.)(.)/){ $1.downcase + $2.upcase } #=> "rUbY"

Updated by ko1 (Koichi Sasada) about 5 years ago

FYI:
Kazuki Tanaka-san proposed a library Kasen.

[ruby-list:50120] [ANN] Kasen(下線) v0.1.1
Github: https://github.com/gogotanaka/_
Rubygems: https://rubygems.org/gems/kasen

It introduces special method "_" (underscore, Kasen in Japanese) and enable us to write such code.

[1, 2, 3].map &(_ + 1).to_s

# means
[1, 2, 3].map { |n| (n + 1).to_s }

Matz said he favorites this idea.

Also available in: Atom PDF