Fsharp: Improve error message when let! _ is last statement in computation expressions

Created on 24 Apr 2018  路  7Comments  路  Source: dotnet/fsharp

Consider the following code:

let x() = async { return () }

let y = 
    async {
        let! _ = x()
    }  // compile error - Unexpected symbol }

let z = 
    async {
        do! x()
    }

If x returns anything else that unit then you can't use do! and you have to do:

let y = 
    async {
        let! _ = x()
        ()
    }

This is hard to explain to newcomers - especially given the error mesage.

Feature Improvement

Most helpful comment

I wasn't even aware you could write a computation expression without a return statement. And in my experience, as long as the return isn't there, the errors are less than useful. And more often than not, it breaks any intellisense, tooltips etc that comes after the CE.

I don't think allowing ending with a let binding is idiomatic, but better errors would be a big improvement.

All 7 comments

Isn't this exactly how a regular let works?
You cannot write let t = 2 in a regular function you have to complete the let expression.

Also there is Async.Ignore in order to use do!:

let y = x() |> Async.Ignore
//or
let y = async { do! x() |> Async.Ignore }

Actually I'm not working against async in the original code ;-)

Anyway, the minimal solutions would be to improve the error message.

We could also consider to allow do! on all values but emit a compiler warning. I guess this would match the regular code flow. This probably would be considered a language change... So yes a better compiler message is probably the first step.

I wasn't even aware you could write a computation expression without a return statement. And in my experience, as long as the return isn't there, the errors are less than useful. And more often than not, it breaks any intellisense, tooltips etc that comes after the CE.

I don't think allowing ending with a let binding is idiomatic, but better errors would be a big improvement.

In the world of task {} with many many side effects it's normal to go without return

Given that a normal let can't be the last line of an expression block, I don't necessarily like allowing let! to "finish" a computational expression.

The standard message is:

The block following this 'let' is unfinished. Every code block is an expression and must have a result. 'let' cannot be the final code element in a block. Consider giving this block an explicit result.

I fully agree that a better error message here, more like the standard one, would be very beneficial for newcomers - it'd be nice if there was some consistency in error messages when inside or outside of a computational expression.

Please convert this to an error message improvement tracking issue?

Was this page helpful?
0 / 5 - 0 ratings