5
def getStr(): String = {
  println("getStr is running")
  "str"
}

def lazyHello(para: => String) = {
  println("lazy hello is runing")
  println(para)
}

def notLazyHello(para: String) = {
  println("not lazy hello is runing")
  println(para)
}

def anoyHello(para: () => String) = {
  println("anoy hello is runing")
  println(para())
}

notLazyHello(getStr)
lazyHello(getStr)
anoyHello(getStr)

得到这个结果:

scala> notLazyHello(getStr)
getStr is running
not lazy hello is runing
str

scala>     lazyHello(getStr)
lazy hello is runing
getStr is running
str

scala>     anoyHello(getStr)
anoy hello is runing
getStr is running
str

似乎lazyHello 和anoyHello 执行相同。

那么,在 Scala 中,什么时候是使用惰性求值参数而不是使用函数作为参数的好时机呢?

4

2 回答 2

5

你的观察是正确的。lazyHello并且anoyHello实际上是相同的。这是因为para: => String是 的简写para: () => String

另一种看待这个的方式:

() => String是一个不带参数并返回字符串的函数。

=> String是计算字符串的东西,不带参数。所以本质上按名称调用是一个没有输入参数的函数。

于 2013-11-19T13:45:45.860 回答
3

基本上惰性评估参数和参数之间没有技术差异Function0。两种实施方式各有利弊。

Function0参数绝对是冗长的。因此,如果您将它们更改为惰性参数,代码将变得更具可读性。

这是一个容易出错的懒惰评估情况。

考虑以下代码

def inner = println("inner called")

def execute(f: => Unit) = {
  println("executing")
  f
}

def redirect(f: => Unit) = {
  println("redirecting")
  execute(f)
}

redirect(inner) // will print - 
                // redirecting
                // executing
                // inner called

现在想想由于某种原因您忘记放入=>执行功能。代码将正确编译,但行为会有所不同,并且可能会引入错误。

def execute(f: Unit) = {
  println("executing")
  f
} 

def redirect(f: => Unit) = {
  println("redirecting")
  execute(f)
}

redirect(inner) // will print - 
                // redirecting
                // inner called
                // executing

但如果你使用Function0,代码将无法编译。因此,Function0参数不易出错。

def inner() = println("inner called")

def execute(f:() => Unit) = {
  println("executing")
  f()
}

def redirect(f:() => Unit) = {
  println("redirecting")
  execute(f)
}

redirect(inner) // will print - 
                // redirecting
                // executing
                // inner called

==========================================

def inner() = println("inner called")

def execute(f:Unit) = {
  println("executing")
  f
}

def redirect(f:() => Unit) = {
  println("redirecting")
  execute(f)               // Will not compile.
}

此外,您可以清楚地看到何时评估该值。

无论如何,如果您非常确定自己在做什么,则可以使用其中任何一种。决定权在你。

于 2013-11-19T13:57:30.893 回答