String keys do not work with pattern matching, or more specifically pattern expressions in this case. The only way to get around that is to use something to symbolize the keys.

That said, I have argued before that we should treat pattern expression keys as irrelevant, whether they are Strings or Symbols.

https://baweaver.com/writing/2022/06/11/the-case-for-pattern-matching-key-irreverence-in-ruby-1oll/

The other option is to use something like Dio to make it irreverent for you:

https://github.com/baweaver/dio

The general direction of my argument in this regard is that pattern expressions are exactly that: patterns. They are not Symbols, nor are they Strings, just as keyword arguments are keyword arguments and not Symbols either.

Regarding your second point? Patterns are not first-class objects, unlike a regular expression, for example. However, you can cheat this one a bit more elegantly:

captured_pattern = -> value { value in pattern: /match/ }

You use a function / proc / lambda / block to do it. That's also something I want, in addition to composable patterns (e.g., capturing a pattern and reusing it inside another one as a branch or a part of it.)

On Sun, May 31, 2026 at 10:14 PM botp via ruby-talk <ruby-talk@ml.ruby-lang.org> wrote:
im lazy. straight from copilot :)

🔑 Pattern Matching with String Keys
By default, Ruby’s hash pattern matching expects symbol keys. That’s why your example works when you load YAML with symbolize_names: true. If you keep string keys, you need to explicitly match them:

ruby
y = YAML.safe_load(yaml_data) # no symbolize_names

y["cards_on_hand"].each do |a_card|
  case a_card
  in { "suite" => String => captured_suite, "value" => "king" }
    puts "you have a king on your hand and its suite is #{captured_suite}"
  else
    puts "a card of no interest #{a_card.inspect}"
  end
end
Notice the difference:

suite: → matches a symbol key

"suite" => → matches a string key

So:

Use symbolize_names: true if you want to work with symbols.

Or match with "key" => if you want to keep string keys.

📦 Passing Patterns into Functions
Patterns in Ruby are objects (they’re part of the language syntax). You can’t directly “store” a pattern as a variable, but you can wrap matching logic in a method and use case ... in inside it.

Example:

ruby
def match_card(card, pattern)
  case card
  in pattern
    yield $~ if block_given? # or just return true
  else
    nil
  end
end

pattern = { suite: String => suite, value: "king" }

y[:cards_on_hand].each do |card|
  match_card(card, pattern) do
    puts "Captured suite: #{suite}"
  end
end
Another approach is to use procs/lambdas for reusable matching logic:

ruby
king_pattern = ->(card) {
  case card
  in { suite: String => s, value: "king" }
    s
  else
    nil
  end
}

y[:cards_on_hand].each do |card|
  if (suite = king_pattern.call(card))
    puts "You have a king of #{suite}"
  end
end
This way, you can pass around reusable matchers like any other object.

🚀 Key Takeaways
Use symbol: for symbol keys, "string" => for string keys.

Wrap patterns in methods or lambdas to pass them around.

Captures (=> var) work fine inside those reusable matchers.


On Tue, May 26, 2026 at 10:12 PM Marcus Poller via ruby-talk <ruby-talk@ml.ruby-lang.org> wrote:
Hi Rubyists,

is this the place to ask beginner questions?

I am confused about pattern matching. It only seems to work when the key
is of type symbol.
How would I apply pattern matching to string keys?

Example

require "yaml"

yaml_data="
cards_on_hand:
  - suite: hearts
    value: '9'
  - suite: hearts
    value: 'king'
  - suite: diamonds
    value: 'king'
"

y=YAML.safe_load(yaml_data, symbolize_names: true)
puts y.inspect

y[:cards_on_hand].each do |a_card|
   case a_card
   in { suite: String => captured_suite, value: 'king' }
     puts "you have a king on your hand and its suite is #{captured_suite}"
   else
      puts "a card of no interest #{a_card.inspect}"
   end
end

{cards_on_hand: [{suit: "hearts", value: "9"}, {suit: "hearts", value:
"king"}, {suit: "diamonds", value: "king"}]}

a card of no interest {suite: "hearts", value: "9"}
you have a king on your hand and its suite is hearts
you have a king on your hand and its suite is diamonds


Second question:

Since everything in Ruby is an object, how do I pass patterns into a
function? Even more specific, how do I handle capture when passing to a
function?


Cheers,
Marcus
______________________________________________
 ruby-talk mailing list -- ruby-talk@ml.ruby-lang.org
 To unsubscribe send an email to ruby-talk-leave@ml.ruby-lang.org
 ruby-talk info -- https://ml.ruby-lang.org/mailman3/postorius/lists/ruby-talk.ml.ruby-lang.org/
______________________________________________
 ruby-talk mailing list -- ruby-talk@ml.ruby-lang.org
 To unsubscribe send an email to ruby-talk-leave@ml.ruby-lang.org
 ruby-talk info -- https://ml.ruby-lang.org/mailman3/postorius/lists/ruby-talk.ml.ruby-lang.org/