scala学习笔记(一)

来源:互联网 发布:apache和nginx linux 编辑:程序博客网 时间:2024/06/06 00:12

CBN Versus CBV

所有的笔记都来自于对于coursea上洛桑联邦理工学院的Scala 函数式程序设计原理课程的理解和摘录。

scala中两种求值策略, call-by-value(CBV,应用序求值)和call-by-name(CBN,正则序求值)。
如果化简表达式由单纯的表达式构成,并且它们都会终止,不陷入循环,那么两种求值策略的结果是相同的,但是它们各有优势。
CBV优势在于函数的每个参数只会被求值一次。
CBN优势在于如果函数参数在函数体中没有被调用,那么就不需要计算它。
举个例子:

def test(x: Int, y:Int) = x*xtest(2,3)test(3+4,8)test(7,2*4)test(3+4,2*4)
  • test(2,3)
    CBV和CBN一样

  • test(3+4,8)
    CBV: >test(7,8)>7×7>49
    CBN: >(3+4)×(3+4)>7×(34)>7×7>49
    CBN要多一步

  • test(7,2*4)
    CBV: >test(7,8)>7×7>49
    CBN: >7×7>49
    CBV要多一步

  • test(3+4,2*4)
    CBV: >test(7,2×4)>test(7,8)>7×7>49
    CBN: >(3+4)×(3+4)>7×(34)>7×7>49
    CBN和CBV步数一样

这下CBN和CBV的区别就清楚了,对于CBN函数的所有参数都要求完值之后再代入函数进行运算,而CBV是直接将表达式代入函数。接下来我们再来看一个不终止的例子来进一步加深对它们的理解:

def first(x: Int, y:Int) = xdef loop: Int = loopfirst(1,loop)

对于CBN,运行first(1,loop),我们将得到值1。
对于CBV,运行first(1,loop),我们将陷入循环,无法终止,因为CBV一定要求出loop的值才行。

scala中我们一般运用CBV,因为在实际的运算中,CBV往往会非常高效相较于CBN,因为它避免了大量的重复运算。如果我们有时候需要采用CBN,我们该如何操作呢。给出如下示例:

def constOne(x: Int, y: => Int) = 1

这样的话,对于参数x,我们采用CBV,而参数y,我们采用CBN。

同时在定义的时候,也有“by-name”和“by-value”的差别

def loop:Boolean = loopdef x = loopval x = loop

def的话没关系,而val的话将陷入循环,无法终止,因为val在定义的时候就要算出值来。

原创粉丝点击