2013-08-02 29 views
1

一个呼叫按姓名是expensiveOperation()将不会在下面的例子得到运行好处:斯卡拉的call-by-名字 - 声明参数未使用

呼叫按值:

def test(x: Int, y: Int): Int = x * x 

// expensiveOperation is evaluated and the result passed to test() 
test(4, expensiveOperation()) 

的call-by-名称:

def test(x: Int, y: => Int): Int = x * x 

// expensionOperation is not evaluated 
test(4, expensiveOperation()) 

我的问题,虽然是你为什么要声明一个函数参数(在我的情况下,y),当你不打算使用它呢?

+0

接不接'y'作为参数?你想要什么 – Jatin

+0

准确!我只是重复Martin Odersky在函数式编程课程中给出的例子 - https://www.coursera.org/course/progfun –

回答

4

你的例子是有点做作,考虑下面的代码

def test(x: Boolean, y: => Int): Int = if(x) y else 0 

// expensionOperation is not evaluated 
test(false, expensiveOperation()) 

当第一个参数是假的你节省大量的时间不评估昂贵的操作。

+0

啊,我明白了。非常感谢!! –

2

这仅仅是一个人为的例子来说明名称调用的思想,即如果从不调用传入的参数,则永远不会对其进行评估。

也许一个更好的例子是以下几点:

trait Option[+T] { 
    def getOrElse[B >: A](default: => B): B 
} 

如果OptionSome,然后包裹值返回和default不会求。如果它是None并且仅当它是None时,default将被评估(并因此返回)。

2

使用记录是一个更好的例子:

def debug(msg: String) = if (logging.enabled) println(msg) 

debug(slowStatistics()) // slowStatistics will always be evaluated 

虽然呼叫按姓名的情况下:

def debug(msg: => String) = if (logging.enabled) println(msg) 

debug(slowStatistics()) // slowStatistics will be evaluated only if logging.enabled 
+0

在日志中使用名义形式参数的问题是,他们经常会使它更加昂贵。例如,像logger.debug(“Made it”)这样的常见用法需要实例化编译器生成的thunk类,以保存实际上是编译时常量(无论是否启用“调试”级别)。 –

+0

@RandallSchulz可悲的是,没错。该名称参数通过相对昂贵的关闭来捕获。 –