Issue #15723 has been updated by duerst (Martin Drst).


Eregon (Benoit Daloze) wrote:
> duerst (Martin Drst) wrote:

> > `array1.zip(array2).map { @1 - @2 }` (or better yet, `array1.zip_with(array2) { @1 - @2 }`)
> 
> Both of these already feel hard to read for me (and I'm implementing Ruby, so I would think I'm familiar with the Ruby syntax).
> I have to read the entire block body (which could be long), just to find out how many block arguments it takes, and even then it's only a guess because maybe some block arguments are just not used.
> `array1.zip(array2).map { |a,b| a - b }` or `array1.zip(array2).map { |(a,b)| a - b }` is so much clearer, isn't it?

What's easy or hard to read is definitely to quite some extent subjective, but just a few more points:

* You have seen the later many many times over already, but not the former, because it's new syntax. It takes some time to get used to new syntax. Of course, that's an argument against introducing new syntax in general, but we should also look at how things might feel once we get used to the new syntax.

* When I see `zip`(`_with`), I know there will be two arguments. When I see `@1-@2` (after getting used to), I know it's subtraction.

* Every one of us, and we as a collective of Ruby programmers, will have to find out where the boundaries of using these variables are. Everybody agrees that using them in long blocks is a bad idea, and using too many of them is also a bad idea. Most people agree that for a single variable in a very short block, it can be useful. But we have very little practice, at least in Ruby, about where (approximately) the boundaries are. Maybe people used to other programming languages that have such a feature (e.g. Closure) can give some hints?

> What if we had a `each_slice` which would find how many elements to yield based on the block arity, like `ary.each_slice { |a,b,c| ... }`? (FWIW, there already are methods checking the block arity)
> Then this new syntax would be pretty confusing: `ary.each_slice { do_one_thing_with(@2).and_sth_else(@3, @1) }`.

I agree for this example. `each_slice` doesn't give any hint as to arity (and that's most probably why it doesn't work that way in Ruby anyway), the block is longer, the number of parameters is higher, and they are not in order,  all of which affect the overall readability balance.

> I started pretty neutral about this issue, but ends up quite against it given how it seems to impact readability negatively.
> 
> Maybe this is a good topic to discuss at the RubyKaigi meeting? Or to make a poll during one of the talks?

Discussion is definitely a good idea. Polling may be worse than design by committee (the IETF occasionally uses humming as an alternative). The result can change very much depending on who gave what talk before the question(s), what question(s) are asked, how the question(s) are asked, who asks the question(s), and who is in the audience. But of course if Matz wants to ask his audience, that's his choice.

----------------------------------------
Misc #15723: Reconsider numbered parameters
https://bugs.ruby-lang.org/issues/15723#change-77349

* Author: sos4nt (Stefan Schler)
* Status: Feedback
* Priority: Normal
* Assignee: 
----------------------------------------
I just learned that *numbered parameters* have been merged into Ruby 2.7.0dev.

For readers not familiar with this feature: it allows you to reference block arguments solely by their *index*, e.g.

```ruby
[1, 2, 3].each { |i| puts i }

# can become

[1, 2, 3].each { puts @1 }
```

I have an issue with this new feature: I think **it encourages sloppy programming** and results in **hard to read code**.

---

The [original proposal](https://bugs.ruby-lang.org/issues/4475) was to include a special variable (or keyword) with a **readable name**, something like:

```ruby
[1, 2, 3].each { puts it }

# or

[1, 2, 3].each { puts this }
```

Granted, that looks quite lovely and it actually speaks to me  I can *understand* the code. And it fits Ruby: (quoting the website)

> [Ruby] has an elegant syntax that is natural to read and easy to write.

But the proposed `it` / `this` has limited application. It's only useful when dealing with a single argument. You can't have multiple `it`-s or `this`-es. That's why `@1`, `@2`, `@3` etc. were chosen instead.

However, limiting the usefulness to a single argument isn't bad at at. In fact, a single argument seem to be the limit of what makes sense:
```
h = Hash.new { |hash, key| hash[key] = "Go Fish: #{key}" }

# vs

h = Hash.new { @1[@2] = "Go Fish: #{@2}" }
```
Who wants to read the latter? That looks like an archaic bash program (no offense). We already discourage Perl style `$`-references: (from [The Ruby Style Guide](https://github.com/rubocop-hq/ruby-style-guide#no-perl-regexp-last-matchers))

> Don't use the cryptic Perl-legacy variables denoting last regexp group matches (`$1`, `$2`, etc). Use `Regexp.last_match(n)` instead.

I don't see how our code can benefit from adding `@1` and `@2`.

Naming a parameter isn't useless  it gives context. With more than one parameter, naming is crucial. And yes, naming is hard. But avoiding proper naming by using indices is the wrong way.

So please reconsider numbered parameters.

Use a readable named variable (or keyword) to refer to the first argument or ditch the feature entirely.



-- 
https://bugs.ruby-lang.org/

Unsubscribe: <mailto:ruby-core-request / ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>