11.3.3 using function to simulate delay calculation
The order of calculation in F # and C # is advanced: As an expression used for a function parameter, it is calculated before the function itself starts executing. In C # and F #, we can use function values to simulate lazy calculations, and F # even has a special keyword that supports deferred computing.
But first of all, there is an exception to the pre-calculation rule, which you certainly know, and often use, but simply because it is too common, but may not realize it's special. There are specific C # operators, such as logical OR (| | ), Logic and (&&), conditional operator (?:), and empty merge operator (null-coalescing,??). ), the short path (short-circuiting) behavior can be achieved, and only those operands that are required to calculate the results are computed. In this way, we can not easily achieve with | | Operators have the or method of the same behavior:
if (Foo (5) | | Foo (7))
Console.WriteLine ("True");
if (Or (foo (5), Foo (7)))
Console.WriteLine ("True");
For example, the Foo method returns True when the argument is less than 10 o'clock. This way, when you calculate the Foo (5) value, the built-in | | The operator knows that the overall result is definitely true, so Foo (7) is no longer evaluated, whereas if the or method is called, the two parameter values are evaluated before the method call. So, is there any way to write this code so that if the expression foo (5) is true, Foo (7) is not evaluated?
Using the function value may be an answer, namely, to change the method's parameter type bool to func<bool>. That way, when the next code needs this value, you can execute the function, and it will return to the value of the expression. As you can see in Listing 11.15, use this method to write or operator (now called Lazyor).
Listing 11.18 using a function's delay or operator (C #)
BOOL Foo (int n) {
Console.WriteLine ("Foo ({0})", n); [1]
Returnn <= 10;
}
BOOL Lazyor (func<bool> First, Func<bool>second) {[2]
if (first ()) return true; <--calculating the first parameter
if (second ()) return true; <--Calculating Second parameters
Returnfalse;
}
if (lazyor () = foo (5), () = foo (7))) <--only output Foo (5)
Console.WriteLine ("True");
We illustrate the problem by using the Foo method to output to the screen [1], so you can track the process of the call. The parameter value of the primitive or operator is now packaged inside the lambda function, and when the method is called, its parameter value is calculated in advance, but now the parameter value is a function, and the expression inside the lambda function is evaluated only when the function is called.
Take a look at the Lazyor method [2], where you need to access the Boolean value, where you want to calculate, we call the function provided by the parameter value. If the Ifrst function returns True, then the Lazyor method will immediately return True,second function is not called at all. In this way, the code behaves like a built-in logical OR operator.
Suppose we need to access the parameter value more than once, do you want to call the function multiple times? It doesn't sound like a very effective solution, so we might want to save the results. This is easy to implement in F #, using a function called delay value (lazy values). We'll look at some F # code first, and then we'll implement the same behavior in C #, and then we'll look at a sample application that might help you with this technique in your own code.
11.3.3 using function to simulate delay calculation