Project

General

Profile

Feature #16460

External names for keyword parameters in method definitions

Added by harrisonb (Harrison Bachrach) 11 months ago. Updated 11 months ago.

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

Description

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

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:

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.

Others have suggested that this could also be helpful if the keyword params collide with reserved keywords in Ruby, e.g.:

def reserve_appointment(when:)
  Appointment.create(time: when) #=> SyntaxError: unexpected `when', expecting `end'
end

Currently, one must use local_variable_get to get around this issue, e.g.:

def reserve_appointment(when:)
  time = local_variable_get(:when)
  Appointment.create(time: time)
end

Syntax options:

  1. No arrow syntax (original proposal)

    def name(external_name internal_name: default_value)
    # ...
    end
    # Example
    def move(from source: 'src/', to destination: 'dist/', at time:)
    # ...
    end
    
  2. Infix arrow syntax

    def name(external_name => internal_name: default_value)
    # ...
    end
    # Example
    def move(from => source: 'src/', to => destination: 'dist/', at => time:)
    # ...
    end
    
  3. Postfix arrow syntax (suggested by zverok (Victor Shepelev))

    def name(external_name: default_value => internal_name)
    # ...
    end
    # Example
    def move(from: 'src/' => source, to: 'dist/' => destination, at: => time)
    # ...
    end
    

Also available in: Atom PDF