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


Answering to 4 different posts in one go, sorry.


bozhidar (Bozhidar Batsov) wrote:

> Btw, using `%1`, `%2`, `%3` is fine, right? How do people feel about that one in general. I'm kind of used to it, because that's how Clojure does it, but I'm curious if it feels very weird in general. 

I definitely prefer `@1` over `%1` for Ruby, because for me it 'rhymes' with `@instance_var` and `@@class_var`, as jeremyevans0 has explained.


pascalbetz (Pascal Betz) wrote:

> I know that this feature was not made out of thin air. But out of a 8 year old request that does not show a real benefit (other than "it's a bit shorter").

Well, the original request in definitely 8 years old. But there was quite some discussion recently. And if I remember correctly, there were also other proposals in the same direction. I think this comes from the fact that even more programmers than before get familiar with functional programming.


bozhidar (Bozhidar Batsov) wrote:

> Every language change obviously comes at a cost - it affects every tool that does some AST-based analysis, it adds cognitive overload, it opens up potential for misuse of the features, etc, so language changes are definitely not for free.

Yes indeed. But let's for a moment look at cognitive overload. For a much more familiar example, let's look at
a simple assignment expression: `a -= b`, which we all understand is a shortcut for `a = a - b`. This is very old and well-known from C.

There are actually companies that forbid this because (probably for their average programmer) it's too complicated. But most programmers use it, even though one could say it adds 'cognitive overload'. For people coming from `a = a - b`, it indeed adds cognitive overload because when they see `a -= b`, they first translate it to `a = a - b`. But after a while, that cognitive overload goes away, because `a -= b` is read simply as "substract `b` from `a`", whereas now the cognitive overhead is with `a = a - b`, which is read "assign to `a` the difference between `a` and `b`", which is longer and where the fact that `a` appears twice has a special significance.

Now after that little example from the past, let's look again at something like `{ |n| n-1 }`. We see that `n` appears twice, but we couldn't care less about the actual choice of variable name (except a faint scent that `n` may be an integer, or a number, or so). Once we get used to it, `{ @1-1 }` may look much more direct. In both cases, it's a block (anonymous function) that subtracts 1. In Haskell, a fundamentally functional language, this special case is even shorter, just `(-1)`, and is called an operator section. `(1-)` is the reverse, `{ 1-@1 }` or `{ |n| 1-n }` in Ruby. (Other cases need explicit argument names in Haskell.)

There is an additional cognitive issue involved: There are studies that say that whatever the language, programmers are able to grasp about the same amount of code (e.g. number of lines) at a time. That means that whenever code can be truly shortened (not just squeezed by eliminating spaces and newlines,...) there is a gain
in the actual functionality that can be grasped. That's where the productivity gains e.g. from C to Ruby,
and from plain Ruby to e.g. Rails,..., mostly come from.


maedi (Maedi Prichard) wrote:
> I think the usefulness of this feature is when there's only one parameter. When there's multiple parameters it becomes more confusing to read `@1`, `@2`, `@3` and less confusing to just name the variables.

I agree that _most_ of the usefulness of this feature is with `@1`. But something like
`array1.zip(array2).map { @1 - @2 }` (or better yet, `array1.zip_with(array2) { @1 - @2 }`, once `zip_with` makes it into Ruby, see issue #4539) can also be quite useful.

But I can imagine having Rubocop rules that limit the use of `@1` and friends to some contexts such as one-liners. There are many Ruby features that are very helpful when used in moderation, but are counterproductive when overused. This is no exception. But we will have to learn where the boundary between usefulness and overuse is.

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

* 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>