Is it possible to use a normal order estimate in F #

In Scala, you can choose between an applicative or regular order estimate, see " Scala call-by-name (=>) vs call-by-type " for an example.

def byName(a: => Unit) = { for (i <- 0 until 10) {println(a)} } def byValue(a: Unit) = { for (i <- 0 until 10) {println(a)} } var i = 1; byValue(i = i + 1) println(i); // 2 byName(i = i + 1) println(i) // 12 

Is the same possible in F #?

+4
source share
2 answers

As Lee noted, F # does not allow you to specify a strategy for evaluating function arguments. This is certainly a useful function, but I think sometimes it can be confusing - for example, if you have a first-class function like int -> int , then the type does not tell you which evaluation strategy to use, so you either need to do types are more complex or restrict this for named functions.

In addition to working with lambda functions explicitly, F # also provides support for lazy evaluation (that is, evaluates lazily, but caches the result) using the lazy and Lazy<'T> keywords:

 let foo (a:Lazy<int>) (b:Lazy<int>) = if a.Value = 0 then 0 else b.Value 

This function will evaluate the second argument only if the first is nonzero:

 foo (lazy (printfn "a"; 0)) (lazy (printfn "b"; 10)) // Prints just 'a' foo (lazy (printfn "a"; 10)) (lazy (printfn "b"; 10)) // Prints both 'a' and 'b' 

This is a little more syntactically easy than using functions, but it still requires explicit specification on the client site, and not just on the declaration site.

+4
source

As far as I know, there is no built-in support for this, so the closest you can emulate it is by delaying the calculation using the function.

 let cnst ab = a let apply (f: unit -> unit) = Seq.iter (fun i -> printfn "%A" (f())) [1..10] let byName (f: unit -> unit) = apply (cnst (f())) let byValue (f: unit -> unit) = apply f 

Then your example:

 let i = ref 1 byValue (fun _ -> do i := !i + 1) printfn "%d" !i i := 1 byName (fun _ -> do i := !i + 1) printfn "%d" !i 
+3
source

All Articles