Skip to content

Pattern matching support for arguments #515

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

Merged
merged 1 commit into from
May 30, 2025

Conversation

rgarner
Copy link
Contributor

@rgarner rgarner commented Sep 18, 2023

Implement Rake::TaskArguments#deconstruct_keys. This means in an idiomatic ruby 3.x rake task we can use rightward assignment to say:

task :get, %i[tenant id] do |_t, args|
  args => {tenant:, id:}
  ...
end

... and omit the .to_h from args, raising NoMatchingPatternError if either of the two params is absent from the task args.

@hsbt hsbt force-pushed the task-arguments-deconstruct-keys branch from 23fa4d4 to bc17eee Compare March 15, 2024 00:40
@rgarner rgarner force-pushed the task-arguments-deconstruct-keys branch 4 times, most recently from 9ca8f32 to cbd2e35 Compare April 2, 2024 12:22
Implement `Rake::TaskArguments#deconstruct_keys` for use in Ruby 3.1
and up. This means in an idiomatic rake task we can use rightward
assignment to say:

```
task :get, %i[tenant id] do |_t, args|
  args => {tenant:, id:}
  ...
end
```

... and omit the `.to_h` from `args`, raising `NoMatchingPatternError`
if either of the two params is absent from the task args.
@hsbt hsbt force-pushed the task-arguments-deconstruct-keys branch from cbd2e35 to cff7664 Compare May 30, 2025 05:49
@hsbt hsbt merged commit fcc1f86 into ruby:master May 30, 2025
30 checks passed
Copy link

@nevans nevans left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#deconstruct_keys should handle keys == nil, or **rest will be broken.

# normal behavior:
{a: 1, b: 2, c: 3} => {a:, **rest}
a     # => 1
rest  # => {b: 2, c: 3}

# without handling `keys == nil`
class Example
   def initialize(hash) = @hash = hash
   def deconstruct_keys(keys) = @hash.slice(*keys)
end

Example.new({a: 1, b: 2, c: 3}) => {a:, **rest}
# !=> #<Example:0x00007479b6b781b8 @hash={a: 1, b: 2, c: 3}>: key not found: :a (NoMatchingPatternKeyError)

(My apologies for not creating a PR... I can do that later today.)

Comment on lines +97 to +99
def deconstruct_keys(keys)
@hash.slice(*keys)
end
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should handle the nil case, too:

Suggested change
def deconstruct_keys(keys)
@hash.slice(*keys)
end
def deconstruct_keys(keys)
keys ? @hash.slice(*keys) : @hash.dup
end

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

?

omit "No stable pattern matching until Ruby 3.1 (testing #{RUBY_VERSION})" if RUBY_VERSION < "3.1"

ta = Rake::TaskArguments.new([:a, :b, :c], [1, 2, 3])
assert_equal ta.deconstruct_keys([:a, :b]), { a: 1, b: 2 }
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should check the nil case, too:

Suggested change
assert_equal ta.deconstruct_keys([:a, :b]), { a: 1, b: 2 }
assert_equal ta.deconstruct_keys(nil), { a: 1, b: 2, c: 3 }
assert_equal ta.deconstruct_keys([:a, :b]), { a: 1, b: 2 }

@nevans
Copy link

nevans commented Jun 2, 2025

Okay, I did create a small PR to handle the nil case: #635.

Thanks for this PR, @rgarner! I'm a big fan of adding #deconstruct and/or #deconstruct_keys everywhere they make sense. 🙂

@rgarner
Copy link
Contributor Author

rgarner commented Jun 2, 2025

Great shout @nevans, thanks for spotting. I rarely use the **rest case and was unaware of the nil semantics but will take this lesson with me!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants