我试图在Scala中实现闭包示例,来自Neal Ford在Groovy中的Functional Thinking演示。参见幻灯片#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()。它抛出以下错误:
错误:Unit类型的makeCounter不带参数
然后我试了这个。
val c1 = makeCounter
这没有任何错误。仅打印c1:单位=()。
然后,
print(c1)printed(),而c1()给出了同样的错误。
答案 0 :(得分: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”。每个柜台一次。
答案 1 :(得分: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
返回的函数文字当然是完成后的所有内容。