我们可以说函数闭包是将状态保存到函数中,每次我们为函数分配一个新状态时都会产生一个新函数吗?

Can we say function closure is saving a state to a function, and every time we assign a new state to the function it will result in a new function?

在以下 Scala 中调用 inc 的函数中执行增量操作。

def inc(more:Int) = {
  def helper(x:Int) = x+more
  helper _
}

每当调用 inc 函数时,它都会 return 绑定传递给它的参数的另一个函数。例如,inc(1) 将 return 另一个类型为 Int => Int 的函数,其中变量 more 与 1 绑定。

inc(1) // This is of type Int => Int

所以我们可以说 more 是 returned 函数的状态变量,当我们调用 inc(1) 时,1 被分配给 more 吗?

这里有更多的阐述,

由于我来自 OO 编程范例,当我说状态时,我将它与 class 的实例相关联,后者在给定时间具有特定状态。让我们首先考虑 class 在 Java 调用 IncHelper 如下:

class IncHelper{
    private int more;
    public IncHelper(int more){
        this.more = more;
    }

    public int inc(int x){
        return x+this.more;
    }
}

如果我创建上述class的不同实例如下:

IncHelper inc1 = new IncHelper(1);  
// This instance will always increase a value by 1
inc1.inc(10);     // output will be 11

如果我创建上述class的不同实例如下:

IncHelper inc2 = new IncHelper(2);  
// This instance will always increase a value by 2
inc2.inc(10);     // output will be 12

所以在以上两种情况下,两个实例 inc1 和 inc2 包含两个不同的状态变量值。我为 Scala 函数式编程给出的示例也是如此:

val inc1 = inc(1)
inc1(10)                   // Will return 11

如果我创建另一个值如下:

val inc2 = inc(2)
inc2(10)                    // Will return 12

所以在这两种情况下,即 OO 编程,当我创建 2 个 IncHelper 实例时,它会记住在构造它时传递的变量。同样,我们创建的两个函数字面量也是如此,其中创建函数字面量时传递的两个变量 inc1 和 inc2 存储了值。

函数的闭包存储有关 context 的信息 - 此上下文是否由 mutable and/or immutable 组成数据是另一回事。

我们会调用函数 stateful 只是其中有一些可观察到的可变状态(使函数不是引用透明的;像打印这样的副作用算作可变状态)。因此,除非您有一些可能会发生变异的数据(var 那里永远不会发生变异使它们有效不可变),否则根据通常的术语,您的函数没有状态。

你的情况:

def inc(more:Int) = {
  def helper(x:Int) = x+more
  helper _
}

inc 不存储可变数据。 x+more returns 一个新值,既不改变 x 也不改变 more 值。如果你这样做:

inc(1)
inc(1)
inc(1)
inc(1)

你每次都会得到相同的结果(Int => Int 函数具有相同的行为),没有副作用。所以根据通常接受的术语,inc 函数是 stateless 并且你不能说它具有 state。里面存储了一些数据的事实……无关紧要,因为您编写的每一段代码都会这样做,所以一切都将被称为有状态的,有状态和无状态之间的区别实际上是无用的。

现在,如果您将函数定义为:

var state = 0
def inc(more:Int) = {
  state = state + more
  val y = state // binds current value of state
  def helper(x:Int) = x + y
  helper _
}

每次调用具有相同值的 inc 都会产生不同的值(这里:函数 Int => Int 具有不同的行为),因此会有一些状态需要讨论。 (int 函数将有一个状态 - 存储在 var state 中,而返回的函数将是无状态的,因为它们只会捕获不可变的值)。

状态问题将独立于闭包的概念 - 闭包仅“表示”函数的定义使用了在创建时提供的一些数据,并且该函数在您不再可以从外部访问之后仍然可以访问这些数据

总而言之,如果在创建函数的环境中存在被该函数捕获(使用)的可变状态,我只会说(特定的)“函数的闭包将状态保存到函数中”。在其他情况下,我不会这样说,因为没有要捕获的“状态”。然而,由于这是一个非常不精确的陈述(函数是否捕获了自身不可变的可变状态的快照?或者函数是否捕获了对某些可以在其外部发生突变的可变数据的引用?)我会完全避免它。