为什么下面这个Scala函数被称为闭包?

3
3个回答

19
根据我的理解,randList 绝对不是闭包(维基百科 似乎也同意),因为在你提供的代码片段中,它仅依赖于局部变量(参数也被认为是局部变量)。考虑到 randList 的主体,不存在所谓的自由变量,即不从当前词法范围获得其值的变量,其中后者是指方法本身的主体。lenn 都是当前词法范围的变量,因为它们都是 randList 封闭定义的参数。
考虑以下示例:
var n = 10
val f = (x: Int) => x + n

println(f(1)) // 11

n = 20
println(f(1)) // 21

函数f是一个闭包,因为它不仅依赖于其参数,还依赖于在其词法范围外声明的变量(即n)。

维基百科的文章提到,闭包由一个函数和一个声明自由参数的词法范围组成。下面的示例说明了这一点:

// n == 20
// f as above

def foo(g: Int => Int) = {
  val n = 100
  g(1)
}

println(foo(f)) // 21
< p >虽然< code >foo定义了它自己的本地变量< code >n,人们可能会认为< code >f现在使用了这个< code >n,但< code >foo(f)的结果仍然是< code >21。然而,闭包< code >f与包围其声明的词法作用域耦合在一起,当< code >f被评估时,它从中获取< code >n的值。

维基百科的文章提到,闭包由一个函数和声明自由参数的词法作用域一起定义。但这意味着我们实际上不需要对函数定义进行任何更改。即使函数没有使用其词法作用域中声明的变量,它仍然可以访问它们(只是它不使用它们),对吗?因此,实际上不存在两个不同的东西:函数和闭包,对吗?或者我漏掉了什么? - Mahesha999

0

我同意@Malte的观点,因为randList不依赖于在函数外声明的任何变量。所以这个函数不是闭包。


-1
据我所知,闭包是指可以引用另一个函数中的状态的函数。详见此讨论串:什么是“闭包”?

在这个问题中,由于randList没有引用任何外部变量,因此它不是一个闭包...


你能给我一个在Scala中使用柯里化的函数的例子吗? 类似于:def rand5 = randList(5) 或者 val rand5 = randList(5) 在Scala中会报错。 - Minh-Triet Pham Tran
1
如果你想要实现柯里化,你应该将 randList 定义为 randList(len: Int)(n: Int) - chyx

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接