简体   繁体   中英

F# “exit early” computation expression?

In attempting to learn more about how computation expressions work, I'm attempting to code a builder that skips the remainder of the expression after evaluating the then block of an if statement, whereupon the workflow itself would evaluate to true . The workflow should return false if none of the if statements evaluated to true .

For example:

let mutable x = 0

let result =
    earlyExit {
        if false then x <- 99
        if true then x <- 33
        if true then x <- 11
    }

Here, result should be true , and x should be 33 .

The closest I've gotten is:

type EarlyExitBuilder () =
    member this.Combine (a, b) = a || b ()
    member this.Delay fn = fn
    member this.Run fn = fn ()
    member this.Zero () = false

... which results in the workflow evaluating to false , and x to 11 .

Is this doable using the syntax in my example?

I don't think there's any good way to do this using the syntax you're proposing; inside of a computation expression, something like

if c then e

is going to get compiled to something like

if c then 
    e
    builder.Zero() 
else 
    builder.Zero()

so there's no way for the context to differentiate which branch was taken.

The smallest change that would give you the behaviour that you are looking for is probably to add return to the computation - the return construct can return true and terminate the evaluation early:

let mutable x = 0

let result =
    earlyExit {
        if false then return x <- 99
        if true then return x <- 33
        if true then return x <- 11
    }

This evaluates to true and the value of x will be 33 . The computation builder is the same as yours, with additional Return member returning true :

type EarlyExitBuilder () =
    member this.Combine (a, b) = a || b ()
    member this.Delay fn = fn
    member this.Run fn = fn ()
    member this.Zero () = false
    member this.Return( () ) = true

As mentioned in one of the referenced answers, this is somewhat related to my imperative computation builder which lets you use imperative-style return and an extended version with break and continue .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM