Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Support for Non-Symbol Keyowrds #1645

Open
sampersand opened this issue Nov 24, 2023 · 0 comments
Open

Add Support for Non-Symbol Keyowrds #1645

sampersand opened this issue Nov 24, 2023 · 0 comments

Comments

@sampersand
Copy link
Contributor

(Originally posted as a discussion, #1609, I think this is better as an issue)

While working on Kernel#system, I came across a limitation of RBS: it only lets you specify symbol keyword arguments, and not any other type.

Normal keyword arguments in Ruby are passed via key: value, such as gets(chomp: true). However, this syntax is actually sugar for gets(:chomp => true), and Ruby is capable of accepting other values for keys.

Take this contrived example:

def add_one(**kw)
  raise ArgumentError, "missing `0`" unless kw.key?(0)
  raise ArgumentError, "unknown keywords: #{kw.keys - [0]}" unless kw.keys == [0]
  kw[0] + 1
end
p add_one(0 => 3) #=> 4

Or this slightly-less-contrived example:

def add_exponentiated_numbers(**kwargs)
  sum = 0
  kwargs.each do |key, value|
    sum += key ** value
  end
end

puts add_exponentiated_numbers 2=>3, 4=>5, 6=>7 #=> 280968

There's no real way to typecheck this currently in RBS, as RBS only supports symbols for hash keys. It does have a **rest parameter, but that expects symbols as hash keys as well.

I propose we add two new pieces of syntax to function declarations:

  • <literal> => <type>, such as def add_one: (0 => Integer).
  • **<type> => <type>, such as def add_exponentiated_numbers: (**Integer => Integer).

Notably, the ** variant isn't equivalent (nor replaces) the current **<type> <variable> syntax. For example, a simplified Kernel#system (which can take integers for hash keys, which correspond to hash descriptors) could be defined as:

def system: (String cmd, **Integer => Integer, **untyped other_options) -> bool
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

1 participant