Sven Heinz
Sven Heinz

Reputation: 51

F# How to preserve lazy /copy a unforced lazy statement

The output from below is 15,9,9 however I want 15,9,21 I want to preserve a lazy version so I can put in a new function version in a composed function.

open System
let mutable add2  = fun x-> x+2
let mutable mult3 = fun x-> x*3
let mutable co = add2 >> mult3
let mutable com = lazy( add2 >> mult3)
let mutable com2 = com

add2<- fun x-> x
co 3|> printfn "%A"
com.Force() 3|> printfn "%A"
add2<- fun x-> x+4
com2.Force() 3|> printfn "%A"

Upvotes: 1

Views: 176

Answers (1)

Tomas Petricek
Tomas Petricek

Reputation: 243096

I don't think you need lazy values here - lazy value is evaluated once when needed, but its value does not change afterwards. In your case, you need Force to re-evaluate the value in case some dependencies have changed. You can define something like this:

type Delayed<'T> = 
  | Delayed of (unit -> 'T)
  member x.Force() = let (Delayed f) = x in f()

let delay f = Delayed f

This represents a delayed value (really, just a function) with Force method that will evaluate it each time it is accessed. If you rewrite your code using delay, it behaves as you wanted:

let mutable add2 = fun x-> x+2
let mutable mult3 = fun x-> x*3
let mutable com = delay(fun () -> add2 >> mult3)
let mutable com2 = com

add2 <- fun x -> x
com.Force() 3 |> printfn "%A"
add2 <- fun x -> x + 4
com2.Force() 3 |> printfn "%A"

Unlike lazy, this does not do any caching, so calling Force twice will just do the whole thing twice. You could add some caching by tracking a dependency graph of the computation, but it gets more complicated.

Upvotes: 1

Related Questions