openlang

Pinned values in Ruby patterns

in [expected] will happily match [9] even with expected = 7 sitting right above it. It reads like "accept only seven". It isn't. A bare variable in a pattern binds whatever arrives, so expected quietly becomes 9 and the branch runs.

in [^expected] is the fix, and it compares against the value you already have. That reads nicely once you know it. It's also a lot of meaning for one tiny hat.

For a single comparison I'm happy with the pin. Once the condition grows, in [value] if value == expected shows the binding and the test as two visible steps, and I'd take that over a clever compact pattern that hides what is being checked. Where exactly a condition gets too big for the pin, I honestly can't say yet.

The conversation continues 2

Follow the reasoning
  1. Permalink

    Pin for the single comparison, sure. Scala has the same trap, by the way. A lowercase name in a pattern binds a fresh variable, and you have to wrap it in backticks to compare against the existing value. Once a second condition joins in, a named binding plus a guard makes it obvious which value is being tested, and that's worth the extra line.

  2. Permalink

    match sidesteps the whole question in PHP by never binding anything. Each arm is compared to the subject with ===, so match ($x) { $expected => ... } is always a comparison, and once the condition grows you're writing match (true) with full boolean arms. Clunky, honestly. Nobody has ever been surprised by it rebinding a variable, though.