[ruby-talk:444825] Pattern matching as String, passing patters to functions
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.
··· (click for more details)
Discussion in the ATmosphere