3 ms·
I have been envious of pattern matching for decades. It is one of those language features I saw (almost certainly in OCaml) and just desired it. I have not work
by zoogeny 3y ago
I have been envious of pattern matching for decades. It is one of those language features I saw (almost certainly in OCaml) and just desired it. I have not worked professionally in any language that supports it.
One tiny annoyance I have with many implementations of this feature:
# standalone `in` just returns `false` the pattern doesn't match, useful in `if`:
if point in [x, y]
# it was a 2-element array, and we checked and deconstructed it
# ...
end
This pattern, where `x` and `y` are introduced into the block is a pretty common way to expose a kind of pattern matching guard. You can be sure that inside the `if` block you have valid non-null references to both `x` and `y`.
But I hate nesting. In most cases when I am asserting some form of data what I want to do is exit the function if the data is invalid, perhaps with some error code.
So what I want is:
unless point in [x, y]
log.error("Invalid point")
return /* ideally some Option/Result */
end
# code assuming valid x & y
This is one of those "wouldn't it be nice" kinda syntax sugar things, but if I have a series of guards that are progressively narrowing types it ends up feeling much nicer to me.
- twiss 3y agoJakt [1] shares your design philosophy, and has implemented syntax like this: [2] guard foo is Bar(x) else { println("not matched") return -1 as! c_int } println("hello there: {}", x) [1]: https://github.com/SerenityOS/jakt https://github.com/SerenityOS/jakt [2]: https://github.com/SerenityOS/jakt/blob/main/samples/guard/is_guard.jakt https://github.com/SerenityOS/jakt/blob/main/samples/guard/i...
- masklinn 3y agoSwift has that feature as well, restricted to optionals guard let (a, b) = foo else { return whatever } Rust recently, finally, stabilised a full pattern matching version: let Ok((a, b)) = foo else { return whatever; } Although it's been available as a third-party macro (https://crates.io/crates/guard https://crates.io/crates/guard) for years: guard!(let Ok((a, b)) = foo else { return whatever; });
- zoogeny 3y agoI was thinking of `guard` in Swift when I was writing but I haven't used it so I was unsure of its exact semantics. It is a bit of a shame it is only useable on optionals and not on arbitrary types. Nice to see a full pattern matching guard in Rust. I think the terminating `?` operator makes it a bit less necessary as I would guess a large portion of cases where I would want that early-return behavior I would just take advantage of that operator. But their choice to reuse `else` makes a lot of sense and the pattern reads well. I was watching the recent Rust stream by Jon Gjengset where he builds a BitTorrent implementation [1]. One thing he did frequently was add a `.context` method to function invocations that would terminate in `?`. My assumption just looking at that pattern is that it would allow the error system to tag the errors to help guide the programmer to the specific line the error was generated from, almost like an annotated stack trace. But again, I don't have direct experience programming large Rust applications. The reason I consider this topic is because this kind of error handling would be ideal in Go. I often end up with the classic pattern: if value, err := someFunc(); !err { // value is useable } // handle err And I would just really, really like if Go would let me: if value, err := someFunc(); err != nil { // handle err } // value is useable But, I suppose due to Go block scoping `value` is only valid within the if block. 1. https://www.youtube.com/watch?v=jf_ddGnum_4&t=9465s&ab_channel=JonGjengset https://www.youtube.com/watch?v=jf_ddGnum_4&t=9465s&ab_chann...
- hosh 3y agoI use it in Elixir. My Ruby has gotten functional these days so pattern matching is a welcome addition for me. The other half of pattern matching is function clauses …