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/