[ruby-core:113435] [Ruby master Feature#19634] Pattern matching dynamic key

Issue #19634 has been reported by baweaver (Brandon Weaver). ---------------------------------------- Feature #19634: Pattern matching dynamic key https://bugs.ruby-lang.org/issues/19634 * Author: baweaver (Brandon Weaver) * Status: Open * Priority: Normal ---------------------------------------- I found myself in a situation ([stable marriage problem](https://rosettacode.org/wiki/Stable_marriage_problem#top-page)) where I would like to match against a dynamic key, like so: ```ruby mentor_proposals = { mentor_name: ['mentee_1', 'mentee_2'] } mentor_name = :mentor_name mentee_name = 'mentee_1' mentor_proposals in ^key: [*, ^mentee_name, *] # SyntaxError ``` Currently this is not supported syntax, but there are some use cases in which I might see myself wanting to use it including this one. As `deconstruct_keys` currently accepts an `Array` of keys this would not break compatibility but would introduce syntactic complexity in capturing keys on hash-like matches. I believe the tradeoff is worthwhile, but would like to hear others opinions on the matter. Granted this case has some oddities of `Symbol` and `String` interchangeability as an implementation detail, and I will not be arguing for key irreverence in this issue as that's a [much more involved topic](https://dev.to/baweaver/the-case-for-pattern-matching-key-irreverence-in-rub...). -- https://bugs.ruby-lang.org/

Issue #19634 has been updated by matz (Yukihiro Matsumoto). Probably, you are proposing `mentor_proposals in ^mentor_name => [*, ^mentee_name, *]`. I still cannot imagine the case where dynamic key is useful. As far as I know, no other language support dynamic key matching. Please be more concrete to persuade us (preferably, with pseudo code). Matz. ---------------------------------------- Feature #19634: Pattern matching dynamic key https://bugs.ruby-lang.org/issues/19634#change-103135 * Author: baweaver (Brandon Weaver) * Status: Open * Priority: Normal ---------------------------------------- I found myself in a situation ([stable marriage problem](https://rosettacode.org/wiki/Stable_marriage_problem#top-page)) where I would like to match against a dynamic key, like so: ```ruby mentor_proposals = { mentor_name: ['mentee_1', 'mentee_2'] } mentor_name = :mentor_name mentee_name = 'mentee_1' mentor_proposals in ^key: [*, ^mentee_name, *] # SyntaxError ``` Currently this is not supported syntax, but there are some use cases in which I might see myself wanting to use it including this one. As `deconstruct_keys` currently accepts an `Array` of keys this would not break compatibility but would introduce syntactic complexity in capturing keys on hash-like matches. I believe the tradeoff is worthwhile, but would like to hear others opinions on the matter. Granted this case has some oddities of `Symbol` and `String` interchangeability as an implementation detail, and I will not be arguing for key irreverence in this issue as that's a [much more involved topic](https://dev.to/baweaver/the-case-for-pattern-matching-key-irreverence-in-rub...). -- https://bugs.ruby-lang.org/

Issue #19634 has been updated by marcandre (Marc-Andre Lafortune). FWIW, Elixir actually supports it, but I've not seen it used in the wild ``` elixir map = %{mentor_name: "Joe"} value = "Joe" key = :mentor_name match?(%{^key => ^value}, map) # => true ``` ---------------------------------------- Feature #19634: Pattern matching dynamic key https://bugs.ruby-lang.org/issues/19634#change-103137 * Author: baweaver (Brandon Weaver) * Status: Open * Priority: Normal ---------------------------------------- I found myself in a situation ([stable marriage problem](https://rosettacode.org/wiki/Stable_marriage_problem#top-page)) where I would like to match against a dynamic key, like so: ```ruby mentor_proposals = { mentor_name: ['mentee_1', 'mentee_2'] } mentor_name = :mentor_name mentee_name = 'mentee_1' mentor_proposals in ^key: [*, ^mentee_name, *] # SyntaxError ``` Currently this is not supported syntax, but there are some use cases in which I might see myself wanting to use it including this one. As `deconstruct_keys` currently accepts an `Array` of keys this would not break compatibility but would introduce syntactic complexity in capturing keys on hash-like matches. I believe the tradeoff is worthwhile, but would like to hear others opinions on the matter. Granted this case has some oddities of `Symbol` and `String` interchangeability as an implementation detail, and I will not be arguing for key irreverence in this issue as that's a [much more involved topic](https://dev.to/baweaver/the-case-for-pattern-matching-key-irreverence-in-rub...). -- https://bugs.ruby-lang.org/

Issue #19634 has been updated by marcandre (Marc-Andre Lafortune). Some actual examples of dynamic key matching in Elixir: https://github.com/search?q=%2F%25%5C%7B%5C%5E%2F+&type=code ---------------------------------------- Feature #19634: Pattern matching dynamic key https://bugs.ruby-lang.org/issues/19634#change-103138 * Author: baweaver (Brandon Weaver) * Status: Open * Priority: Normal ---------------------------------------- I found myself in a situation ([stable marriage problem](https://rosettacode.org/wiki/Stable_marriage_problem#top-page)) where I would like to match against a dynamic key, like so: ```ruby mentor_proposals = { mentor_name: ['mentee_1', 'mentee_2'] } mentor_name = :mentor_name mentee_name = 'mentee_1' mentor_proposals in ^key: [*, ^mentee_name, *] # SyntaxError ``` Currently this is not supported syntax, but there are some use cases in which I might see myself wanting to use it including this one. As `deconstruct_keys` currently accepts an `Array` of keys this would not break compatibility but would introduce syntactic complexity in capturing keys on hash-like matches. I believe the tradeoff is worthwhile, but would like to hear others opinions on the matter. Granted this case has some oddities of `Symbol` and `String` interchangeability as an implementation detail, and I will not be arguing for key irreverence in this issue as that's a [much more involved topic](https://dev.to/baweaver/the-case-for-pattern-matching-key-irreverence-in-rub...). -- https://bugs.ruby-lang.org/

I count 44 instances of this in our production code (~100k lines of Elixir), but I don’t think I’ve ever used key and value pinning as shown in the examples above. But dynamic key matching is precisely what is required when it is required, although it’s rare enough. Here's a sample GraphQL response parser or the Shopify Customers API: ```elixir def parse_customer_response(%{} = body, resource, action) do gql_action = resource <> String.capitalize(action) case body do %{status: 200, body: %{^gql_action => %{^resource => %{} = result, "userErrors" => []}}} -> {:ok, result} %{status: 200, body: %{^gql_action => %{"userErrors" => []} = result}} -> {:ok, result} %{errors: errors} -> {:error, Enum.map(errors, &Map.get(&1, "message"))} %{body: %{^gql_action => %{"userErrors" => errors}}} -> {:error, Enum.map(errors, &Map.get(&1, "message"))} %{body: %{^gql_action => nil}} -> {:error, [%{message: "#{gql_action} access denied"}]} %{body: nil} -> {:error, [%{message: "#{gql_action} access denied"}]} _ -> {:error, [%{message: "Unknown error"}]} end end ``` I haven’t started using pattern matching in Ruby, but I could see some simplified code with dynamic key matching. -a On Thu, May 18, 2023 at 12:39 AM marcandre (Marc-Andre Lafortune) via ruby-core <ruby-core@ml.ruby-lang.org> wrote:
Issue #19634 has been updated by marcandre (Marc-Andre Lafortune).
Some actual examples of dynamic key matching in Elixir: https://github.com/search?q=%2F%25%5C%7B%5C%5E%2F+&type=code
---------------------------------------- Feature #19634: Pattern matching dynamic key https://bugs.ruby-lang.org/issues/19634#change-103138
* Author: baweaver (Brandon Weaver) * Status: Open * Priority: Normal ---------------------------------------- I found myself in a situation ([stable marriage problem]( https://rosettacode.org/wiki/Stable_marriage_problem#top-page)) where I would like to match against a dynamic key, like so:
```ruby mentor_proposals = { mentor_name: ['mentee_1', 'mentee_2'] } mentor_name = :mentor_name mentee_name = 'mentee_1'
mentor_proposals in ^key: [*, ^mentee_name, *] # SyntaxError ```
Currently this is not supported syntax, but there are some use cases in which I might see myself wanting to use it including this one. As `deconstruct_keys` currently accepts an `Array` of keys this would not break compatibility but would introduce syntactic complexity in capturing keys on hash-like matches.
I believe the tradeoff is worthwhile, but would like to hear others opinions on the matter.
Granted this case has some oddities of `Symbol` and `String` interchangeability as an implementation detail, and I will not be arguing for key irreverence in this issue as that's a [much more involved topic]( https://dev.to/baweaver/the-case-for-pattern-matching-key-irreverence-in-rub... ).
-- https://bugs.ruby-lang.org/ ______________________________________________ ruby-core mailing list -- ruby-core@ml.ruby-lang.org To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org ruby-core info -- https://ml.ruby-lang.org/mailman3/postorius/lists/ruby-core.ml.ruby-lang.org...
-- Austin Ziegler • halostatue@gmail.com • austin@halostatue.ca http://www.halostatue.ca/ • http://twitter.com/halostatue

Issue #19634 has been updated by austin (Austin Ziegler). I count 44 instances of this in our production code (~100k lines of Elixir), but I don’t think I’ve ever used key and value pinning as shown in the examples above. But dynamic key matching is precisely what is required when it is required, although it’s rare enough. Here's a sample GraphQL response parser or the Shopify Customers API: ```elixir def parse_customer_response(%{} = body, resource, action) do gql_action = resource <> String.capitalize(action) case body do %{status: 200, body: %{^gql_action => %{^resource => %{} = result, "userErrors" => []}}} -> {:ok, result} %{status: 200, body: %{^gql_action => %{"userErrors" => []} = result}} -> {:ok, result} %{errors: errors} -> {:error, Enum.map(errors, &Map.get(&1, "message"))} %{body: %{^gql_action => %{"userErrors" => errors}}} -> {:error, Enum.map(errors, &Map.get(&1, "message"))} %{body: %{^gql_action => nil}} -> {:error, [%{message: "#{gql_action} access denied"}]} %{body: nil} -> {:error, [%{message: "#{gql_action} access denied"}]} _ -> {:error, [%{message: "Unknown error"}]} end end ``` I haven’t started using pattern matching in Ruby, but I could see some simplified code with dynamic key matching. (As a separate note, it appears that email replies to redmine aren’t necessarily working, as this should have come in by email.) ---------------------------------------- Feature #19634: Pattern matching dynamic key https://bugs.ruby-lang.org/issues/19634#change-103160 * Author: baweaver (Brandon Weaver) * Status: Open * Priority: Normal ---------------------------------------- I found myself in a situation ([stable marriage problem](https://rosettacode.org/wiki/Stable_marriage_problem#top-page)) where I would like to match against a dynamic key, like so: ```ruby mentor_proposals = { mentor_name: ['mentee_1', 'mentee_2'] } mentor_name = :mentor_name mentee_name = 'mentee_1' mentor_proposals in ^key: [*, ^mentee_name, *] # SyntaxError ``` Currently this is not supported syntax, but there are some use cases in which I might see myself wanting to use it including this one. As `deconstruct_keys` currently accepts an `Array` of keys this would not break compatibility but would introduce syntactic complexity in capturing keys on hash-like matches. I believe the tradeoff is worthwhile, but would like to hear others opinions on the matter. Granted this case has some oddities of `Symbol` and `String` interchangeability as an implementation detail, and I will not be arguing for key irreverence in this issue as that's a [much more involved topic](https://dev.to/baweaver/the-case-for-pattern-matching-key-irreverence-in-rub...). -- https://bugs.ruby-lang.org/
participants (5)
-
austin (Austin Ziegler)
-
Austin Ziegler
-
baweaver (Brandon Weaver)
-
marcandre (Marc-Andre Lafortune)
-
matz (Yukihiro Matsumoto)