0

我试图在 Scala 中实现闭包示例,来自 Neal Ford 在 Groovy 中的功能性思维演示文稿。请参阅幻灯片 # 43 和 44 https://sea.ucar.edu/sites/default/files/Functional_Thinking.pdf

  def makeCounter : Unit = {
var localVar = 0
return { localVar += 1 }
}

此代码返回一个匿名函数。现在我想通过调用这个匿名函数来增加 localVar。

我有两个问题:
1. 如何调用匿名函数?
2.调用后如何检查localVar的值是否增加?

首先我尝试了这个 -
val c1 = makeCounter()。它抛出以下错误:
错误:单元类型的makeCounter不接受参数

然后我尝试了这个。
val c1 = makeCounter

这没有给出任何错误。仅打印 c1: Unit = ()。

然后,
print(c1) 打印了 (),而 c1() 给出了同样的错误。

4

2 回答 2

6

首先。不要使用return,它的语义在 Scala 中与在 Java 或 Groovy 中完全不同。

Unit类型不是匿名函数的同义词。这更像是副作用的迹象。

匿名函数的类型是() => A. 在您的情况下,您需要一个不返回任何内容但会导致副作用的函数。所以它的类型应该是() => Unit.

让我们看一些代码:

def makeCounter : () => Unit = { 
  var x = 0 
  { () => x = x + 1 } 
}

val counter = makeCounter
counter(); counter(); counter()

伟大的!我们让 makeCounter 给我们一个新的计数器!

只有一个问题。x是方法中的局部变量,makeCounter由于它从未返回,我们看不到它的值!曾经!例如,我们可以x从方法中删除,使其在外部范围内公开。但它不是很实用。相反,让我们让函数返回它:

def makeCounter : () => Int = { // Notice now, instead of Unit we use Int
  var x = 0
  { () => x = x + 1; x } 
}

val counter = makeCounter
println(counter(), counter(), counter())
val counter2 = makeCounter
println(counter2(), counter2(), counter2())

您将看到两次“1,2,3”。每个计数器一次。

于 2013-09-07T22:53:53.393 回答
1

我没有看演示文稿,所以我不知道这是功能性思维还是只是通向功能性思维的幻灯片之一,但是:

scala> def f: () => Int = {
     | var v = 0
     | () => v += 1 ; v }
f: () => Int

scala> val g = f
g: () => Int = <function0>

scala> g()
res0: Int = 1

scala> g()
res1: Int = 2

scala> g()
res2: Int = 3

f当然,返回的函数字面量是括号之后的所有内容。

于 2013-09-08T02:29:55.757 回答