11.3 重构计算顺序

来源:互联网 发布:java从入门到精通mobi 编辑:程序博客网 时间:2024/06/04 20:05

11.3 重构计算顺序

 

我们已经看了如何在使用不可变数据结构的代码中,跟踪函数之间的依赖关系。一旦我们知道了依赖关系是什么,有时就可以调整操作的顺序,使程序更有效,而保持原来的意思不变。清单11.12 就是这种类型优化的一个简单例子。

 

清单11.12 重构程序中的计算(C#)

var num = Calculate1(10);   [1]

var test = TestCondition();

if (test == true)

   return Calculate2(num);

else return 0;

var test = TestCondition();

if (test == true) {

   var num = Calculate1(10);   [2]

   return Calculate2(num);

} else return 0;

 

在第一个版本中,我们是在程序开始时调用Calculate1 函数[1],而调用的结果只在TestCondition 返回true 时使用;如果不是这种情况,我们就没有任何理由执行Calculate1 函数,浪费CPU 时间!在第二个版本中,我们把这个计算移到了if 条件内[2],所以,只在需要这个结果时才计算。

这个修改很简单,你可能有写过更有效的版本,只是没有思考过。随着程序逐渐增长,像这样的优化变得更加难以发现。清单11.13 是一个稍微复杂的例子。

 

清单11.13 传递计算结果给函数(C#)

int TestAndCalculate(int num) {

  vartest = TestCondition();   [1]

  if (test== true)

    returnCalculate2(num);   [2]

  elsereturn 0;

}

 

TestAndCalculate(Calculate1(10));    [3]  <-- 在后面的程序中使用

 

在这个例子中,函数的参数为值num,但函数可能根本就不需要这个值。如果条件[1]的计算结果为false,函数返回0,num 值就没有意义了;当调用此函数时[3],函数Calculate1 总是会执行,即使我们后来发现不需要它的结果。

在Haskell(另一种流行的函数式语言)中,如果代码不需要Calculate1 的结果,不会调用Calculate1;因为,Haskell 使用了不同的计算策略(evaluation strategy)。在回到优化清单11.13 之前,我们要讨论几种策略。

0 0
原创粉丝点击