-
Notifications
You must be signed in to change notification settings - Fork 21
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow pattern matching for exceptions in match expressions #895
Comments
I like this idea, but it would be even nicer if the completeness checker could use information of the function to help telling if we miss an exception (something like Java has had for a long time). That would require adding raising exceptions to the meta data, or tagging functions with something like The same completeness check for exceptions could be added to try/with. Maybe the rule ought to be that all exception cases should come last. I wonder how the same syntax should be used in conjunction with F# exceptions (the ones you can already match over). |
It should be noted that OCaml has this exact feature. |
The argument in that post that it helps with tail recursion inside a try is a good one. 👍 @ebresafegaga, you may want to add that to the pros, it's a strong argument, I think. |
Thanks, done! |
A more orthogonal (and simpler to imlement) variation is that what follows
This is important for two reasons
BTW I'm sold on this feature solely because it helps people write more accurate code where the exception handling doesn't cover too many things. I don't think it's particularly beautiful nor for beginners - it's for more advanced users |
BTW those interested in programming language archeology may want to know that AFAIK the first people to propose this kind of construct were Nick Benton and Andrew Kennedy at Microsoft Research (though they integrated with https://www.cs.tufts.edu/~nr/cs257/archive/nick-benton/exceptional-syntax.pdf |
I marked this approved in principle, subject to this comment #895 (comment) I'm not planning to work on it myself though may be able to give some guidance. I don't think it would be too hard to implement |
I totally agree with you. |
Awesome! A lot of great ideas have come from MSR. I'll definitely check this out. |
I'd very much like to help with implementing this. For a while now I've been trying to hack on the F# compiler, but it seemed so daunting. So I think this would be a good opportunity for me to do that and I would definitely need some guidance. Thanks!. |
@ebresafegaga The next step would be an RFC here: https://github.com/fsharp/fslang-design Although starting off with some coding isn't a bad idea either, it's often a good idea to flesh out a preliminary design before diving into a trial implementation. You can look at RFCs like https://github.com/fsharp/fslang-design/blob/master/RFCs/FS-1090-Generic-struct-type-whose-fields-are-all-unmanaged-types-is-unmanaged.md as an example of the level of detail. |
There's an important difference between the 2 snippets. The second one catches exceptions in |
Exception handling shouldn't be part of your typical program flow. Would this encourage writing manual exception handling more, when the business logic program flow should be handled without rising exceptions? Typically F# attitude has been failwith, fail fast and hard, don't try to recover. I know there are libraries raising exceptions like business-as-usual, but that will not justify this, just like C# libraries returning nulls don't justify C# becoming language optimized for null-handling: more and more keywords to make anti-patterns easier. Not only performance implications, exception-handling is like goto-clauses causing random not-clear paths between nodes of your program. Besides that they make debugging .NET harder, when you can't just break on each CLR exception. |
I think the feature should mention that it works the same for the @Thorium while I think vanilla f# we love doesn't lean strongly on exception declaration nor finegrained handling via There are trade-offs, but f# and I assume ocaml earlier on, endorsed usage of exceptions, unlike go, rust, some dialect of c++. Having this supported, doesn't preclude to, one day, having an f# checker / attribute, that would enable an "pure exceptionless f#" ecosystem (for soundness or performance reasons), but keeping in mind that f# is foremost used on runtimes that endorse usage of exceptions, and that there are wins in expressivity with this feature, while still making You may be interest in my point about exceptions, in this feature suggestion: #830. |
Side note, maybe f# semantic colouring should have something similar to mutable, around all constructs related to exceptions ( |
Is that correct? In the case of Unless what you're piping into the function is a |
@realparadyne you are right for the match input! That said, @kerams comment also gave me some food for thoughts, I think the exception occuring on Those nuances make me a bit uncomfortable along same line as @Thorium, but still think, the construct for total match, including any exception that occurs in evaluation, from top to bottom, in a single scope has value for expressivity, enough to not down vote the issue. I think the RFC should put emphasis on aspects pertaining to how introducing Aside, what about |
This could be interesting for working with BCL/.NET-style exceptions when combined with the object/property patterns from #968, which would address (1) in Don's comment above #895 (comment). match f x with
| y -> Ok y
| exception SomeException (InnerException = null) as e
| exception SomeException (InnerException = e)
| exception e -> Error e match f x y with
| z -> …
| exception ArgumentException (Message = m, ParamName = "x") -> …
| exception ArgumentException (Message = m, ParamName = "y") -> …
| exception e -> … Ideally we might also want to try to do #957 at the same time, so that we could avoid a mismatch in pattern syntax between OCaml-style exceptions (which currently require semicolons if you want to use named patterns to deconstruct their arguments) and BCL/.NET/class-style exceptions. |
I propose we allow pattern matching for exceptions in match expressions when the expression to be matched is a function call (or indexer/ property)
For example,
The existing way of approaching this problem in F# is :
Even though this isn't bad I think the former is clearer, more succinct and even easier to read (say, a new team member)
Pros and Cons
The advantages of making this adjustment to F# are
1. Expressiveness
2. Clear and concise code (favoring readers over writers)
3. It Improves pattern matching in general
4. It's a nice and beautiful syntax
5. It's intuitive
6. Efficient code via tail recursion
The disadvantages of making this adjustment to F# are
1. Implementation costs in the compiler
2. Multiple ways on doing the same thing
3. Might not be familiar to developers from other ecosystems (e.g C#) just learning F#
Extra information
Estimated cost (XS, S, M, L, XL, XXL): M
Affidavit (please submit!)
Please tick this by placing a cross in the box:
Please tick all that apply:
The text was updated successfully, but these errors were encountered: