码迷,mamicode.com
首页 > 其他好文 > 详细

11.3.3 用函数模拟延迟计算

时间:2015-01-12 16:33:35      阅读:189      评论:0      收藏:0      [点我收藏+]

标签:f#   函数编程   实用函数编程   计算策略   延迟计算   

11.3.3 用函数模拟延迟计算

 

在F# 和C# 中计算顺序是提前的:作为给函数参数使用的表达式,在函数自身开始执行之前就计算好了。在C# 和F# 中,我们可以使用函数值模拟延迟计算,另外,F# 甚至有一个专门的关键字,支持延迟计算。

但首先,对于提前计算规则有一个例外,你肯定知道,并经常使用,但只是因为太常用,反而可能没有意识到它的特别。有些特定的C# 运算符,比如,逻辑或(||)、逻辑与(&&)、条件运算符(?:),以及空合并运算符(null-coalescing,??),能实现短路径(short-circuiting)行为,只计算那些计算结果需要的操作数。这样,我们不能很容易地实现与|| 运算符有同样行为的Or 方法:

 

if (Foo(5) || Foo(7))

  Console.WriteLine("True");

if (Or(Foo(5), Foo(7)))

  Console.WriteLine("True");

 

比方说,当参数小于10 时,Foo 方法返回true。这样,当计算Foo(5) 值时,内置的|| 运算符知道整体的结果肯定是true,因此,就不再计算Foo(7);相反,如果调用Or 方法,两个参数值都在方法调用前进行计算。那么,有没有办式写出这样的代码,使得如果表达式Foo(5) 的值为true 时,就不计算Foo(7) 呢?

使用函数值,可能是一个答案,即,把方法的参数类型bool,改成Func<bool>。这样,后面的代码需要这个值时,可以执行这个函数,它会再回过来计算这个表达式的值。在清单11.15 中可以看到,使用这种方法写的或操作符(现在称为LazyOr)。

 

清单11.18 使用函数的延迟或运算符(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;  <--计算 first 参数

  if (second()) return true;   <-- 计算 second 参数

  returnfalse;

}

 

if (LazyOr(() => Foo(5), () => Foo(7)))  <-- 只输出 Foo(5)

  Console.WriteLine("True");

 

我们说明问题,使用Foo 方法输出到屏幕[1],因此,可以跟踪调用的过程。原始的或运算符的参数值,现在打包在lambda 函数的里面,当方法被调用时,它的参数值提前计算,但是,而现在的参数值是函数;lambda 函数内的表达式,要等到函数被调用时,才计算。

看一下LazyOr 方法[2],在需要访问布尔值,即将要计算的地方,我们调用由参数值提供的函数。如果ifrst 函数返回true,则LazyOr 方法将立即返回True,second 函数根本不会调用。这样,代码的行为就像内置的逻辑或运算符一样了。

假设我们需要访问参数值不止一次,那么,要多次调用函数吗?这听起来就不像是个非常有效的解决方案,因此,我们可能要把结果保存起来。这在F# 中,实现起来很简单,用到一个叫延迟值(lazy values)的功能。我们会先看一些F# 代码,然后,用C# 实现同样的行为;之后,我们将看一个示例应用程序,可能会对你在自己的代码中使用这种技术提供一些帮助。

11.3.3 用函数模拟延迟计算

标签:f#   函数编程   实用函数编程   计算策略   延迟计算   

原文地址:http://blog.csdn.net/hadstj/article/details/42643469

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!