Issue #16460 has been updated by harrisonb (Harrison Bachrach).


zverok (Victor Shepelev) wrote:
> You propose to introduce the "same" construct, which means something
> completely different, but due to our intutions, **in Ruby** `external_name
> internal_name:` reads as `external_name(internal_name:)`, which is misleading.

I think at the core, I am suggesting introducing something _new_. While there
is certainly merit to discussion of what is the most "Ruby-like" way to
implement that, I don't think it should hamstring the entire conversation
surrounding the proposal. The new `case...in` feature addition in 2.7 is a
fairly radical departure from the previous semantics of Ruby:

* It performs a name binding outside of all the usual places (assignment,
  parameter list, block parameter list, `rescue` block, etc.)
* That binding is set up by a pattern (which often looks very much like an
  array/hash/etc. literal) which would previously never preform a binding

While the pattern matching feature requires one to read up about it, so do other
later added features that provide utility and expressiveness to Ruby developers.

> 1. So, it should be read this way: `(within range):`, where both words are
>    related to colon, with one being "title" and the second "explanation"?
>    This, again unlike anything else in Ruby. It slightly reminds me of some
>    documentation system links (yard, probably? with "Look also
>    [FormalClassName that class]", or something like that... and I honestly
>    never can remember which is which -- which is "link" and which is "title").

The main constant is that the identifier with the colon (`range` in the example
above) remains the one that can be referenced in the body of the method.

I am open to the arrow syntax if we conclude that it is still unclear and/or
sufficiently alien.

> 2. It works well for _some examples you constructed_, but there always can be
>    counter-examples, like: I want to use `when:` argument, renaming it to
>    `time` (becase `when` is a keyword), so... is it `time when:` or `when
>    time:`?..

I would point to the same fact above about the identifier with the colon
remaining the only valid one in the method body. Additionally, this is change
for the sake of improving readability. One can probably come up with confusing
examples, but the proposed syntax, like much of Ruby syntax, is a sharp knife
that one can use to make their code more or less readable.

> 3. It is incredibly confusing for any parser (especially "rename as it is
>    keyword" use-case) and syntax highlighter:`def foo(in time:` would be the
>    only case where standalone `in<space><something>` should be
>    parsed/hihglighted differently.

I think this could be a valid criticism of the arrow-less syntax. However,
parsers for at least two other languages accomplish this without issue, so I
don't think it's an insurmountable issue.

> Some additional point: currently keyword args definitions reads this way:
> `method(arg1: ..., arg2: ...)` -- is how it would be called (e.g. in call-site
> we'll see the same structure `method(arg1: ..., arg2: ...)` -- and everything
> after the `:` is somewhat "how it is implemented" (for example, defaults
> calculation), which `=> put_to_this_variable` follows.

I think this is a very good point and perhaps the most compelling one for the
`external_name: default_value => internal_name` syntax.

> And one more consideration: imagine Ruby introduced one of those syntaxes in
> 2.8. And some rubyist who missed the announcement, comes to a "new" codebase,
> and how they would understand it?
>
> ```ruby
> def foo(in: => time)
> ```
> "...Ugh, what is it?.. Putting something into `time`? Ah, `in` is a keyword, they want to rename it. Got it. Hate it, but got it."
> ```ruby
> def foo(in time: )
> ```
> "...Ugh what?.. What?.. Is it a new keyword?.. Some kind of type hinting?.. No idea..."
> 
> (Pure speculations, obv.)

I am going to assume good faith here in some of the phrasing. With any syntax
introduction, there is going to have to be some learning. The `case...in` syntax
also requires a similar (if not greater) amount of learning, but that was also
deemed acceptable.


----------------------------------------
Feature #16460: External names for keyword parameters in method definitions
https://bugs.ruby-lang.org/issues/16460#change-83542

* Author: harrisonb (Harrison Bachrach)
* Status: Open
* Priority: Normal
* Assignee: 
* Target version: 
----------------------------------------
Hello! This is my first time filing an issue and I was unable to find anything similar. I apologize if one already exists.

In other languages (such as JavaScript, Swift, and Crystal), it is possible to have two names for a given keyword argument: one that is used in method invocation, and one used in the method definition. Here is an example from Crystal (which has syntax very similar to Ruby):

```crystal
def increment(value, by amount)
  value + amount
end

increment(value: 5, by: 10)
```

This helps create more readable method invocations and definitions. It would be especially helpful in Ruby as the language lacks a destructuring syntax for hashes/keyword args. This is unlike JavaScript, where you can do something like:

```javascript
const { nameOfOneProperty: newNameForTheProperty, nameOfAnotherProperty: newNameForTheOtherProperty } = foo;
```

where `foo` is a JavaScript Object that has the properties `nameOfOneProperty` or `nameOfAnotherProperty` (If it did not have either of them, the corresponding identifiers (newNameForTheProperty and newNameForTheOtherProperty would be initialized to undefined).

I'm thinking that such a change would pair nicely with the new 3.0 keyword argument changes. A suggested syntax might be

```ruby
def name(external_name internal_name:)
  # ...
end




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