fsharp / fslang-suggestions

The place to make suggestions, discuss and vote on F# language and core library features
341 stars 20 forks source link

Support "Raise" keywords in computation expressions #613

Open eiriktsarpalis opened 6 years ago

eiriktsarpalis commented 6 years ago

Support "Raise" keywords in computation expressions

I propose we add support for a Raise : exn -> M<'T> computation expression method. This would address two issues:

1) Provide a native way of throwing inside computation expressions: we could write raise! Exception() instead of return raise Exception().

2) Solve an issue related to desugaring partial exception handling code. Currently the handler of try ... with pattern exn -> cexpr desugars into fun exn -> if pattern exn then cexpr else raise exn. This results in a) loss of stacktrace info and b) phantom breaks happening when debugging an application. The presense of a Raise() builder could allow the compiler to desugar a handler into fun exn -> if pattern exn then cexpr else builder.Raise exn which provides a finer grain of control to the computation expression author.

Pros and Cons

The advantages of making this adjustment to F# are stated above.

The disadvantages of making this adjustment to F# are confusion among beginners on the differences between return raise e and raise! e

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:

pblasucci commented 6 years ago

+1

dsyme commented 6 years ago

The advantages of making this adjustment to F# are stated above.

I think there are more advantages than listed - notably performance? The exception gets into the computation without actually being caught and re-raised

eiriktsarpalis commented 6 years ago

Yes, that too.

dsyme commented 6 years ago

I like this idea, I'd like to see a prototype. I don't see why we wouldn't do this. Except perhaps that it might lead to expectations that there is a failwith! and failwithf! and so on? Currently raise is just a function after all

vasily-kirichenko commented 6 years ago

Can it be implemented with a custom operation?

dsyme commented 6 years ago

@eiriktsarpalis Re this:

Can it be implemented with a custom operation?

Have you tried that? thanks

Heimdell commented 4 years ago

I want to add: that the argument of raise! shouldn't necessarily be an exn.

For instances, there is a

type ('err, 'a) either =
  | Left of 'err
  | Right of 'a

type EitherMonad() = ...

where you might want to raise! a value of type 'err.

If the argument is fixed to be an exn, this will not be possible.