F # Как сохранить ленивый / скопировать невынужденное ленивое утверждение - PullRequest
1 голос
/ 01 апреля 2019

Выход снизу 15,9,9, но я хочу 15,9,21 Я хочу сохранить ленивую версию, чтобы я мог добавить новую версию функции в составную функцию.

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"

1 Ответ

1 голос
/ 02 апреля 2019

Я не думаю, что вам нужны ленивые значения - ленивое значение вычисляется один раз, когда это необходимо, но впоследствии его значение не изменяется.В вашем случае вам нужно Force для переоценки значения в случае изменения некоторых зависимостей.Вы можете определить что-то вроде этого:

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

let delay f = Delayed f

Это представляет задержанное значение (на самом деле, просто функция) с помощью метода Force, который будет оценивать его при каждом обращении к нему.Если вы переписываете код, используя delay, он ведет себя так, как вы хотели:

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"

В отличие от lazy, это не делает никакого кэширования, поэтому двойной вызов Force просто сделает все это дважды.Вы можете добавить некоторое кэширование, отслеживая граф зависимостей вычислений, но это усложняется.

...