没有局部变量的状态表示思想的名称

Name of this state representation idea without local variables

我知道这可能是个奇怪的想法,但我想不妨试试在这里问一下。

我在 Racket 中试验没有局部变量的状态表示。 这个想法是定义一个打印它的参数值的函数,如果再次调用它会给我另一个值。由于使用相同参数调用的纯函数总是产生相同的结果,我的变通方法得到了以下结果。

(define (counter n)
  (displayln n)
  (λ () (counter (add1 n)))) ; unapplied lambda so it doesn't go in a loop

然后我设计了一个函数来调用 counter 及其生成的 lambda 一定次数。

(define (call proc n)
  (unless (zero? n)
    (let ([x (proc)])
      (call x (sub1 n)))))

结果是:

> (call (counter 0) 5)
0
1
2
3
4
5

这里应用的概念叫什么名字?可能它是您在实际应用程序中一直需要的微不足道的东西,但由于我在这方面还没有经验,所以我无法为它确定一个名称。或者也许我只是把一些非常简单的事情复杂化了,但我还是很感激你的回答,这样我就可以进一步研究它了。

抱歉,如果我的问题不够清楚,但英语不是我的母语,问一些我不知道的事情让我感到有点不确定。

您正在使用 closures 来保存状态:lambda 表单存储定义它的环境,并且您不断重新定义过程(在您的代码中称为 x ), 所以每次 "remembers" 都是 n.

的新值

另一种方法是让过程本身跟踪值 - 换句话说,counter 应该在两次调用之间记住当前的 n 值。这就是我的意思:

(define (counter initial)
  (let ((n (sub1 initial)))
    (lambda ()
      (set! n (add1 n))
      n)))

在上面的代码中,counter 的第一次调用 returns 关闭了 n 的新 lambda,并且每次调用 lambda修改 n 和 returns 其新值。等价地,我们可以使用 Racket 特定的语法进行柯里化和 begin0 特殊形式来达到相同的效果:

(define ((counter n))
  (begin0
    n
    (set! n (add1 n))))

无论哪种方式,请注意过程如何 "remembers" 它的先前值:

(define proc (counter 0))
(proc)
=> 0
(proc)
=> 1

我们会 call 像这样:

(define (call proc n)
  (unless (zero? n)
    (displayln (proc))
    (call proc (sub1 n))))

(call (counter 0) 5)
=> 0
   1
   2
   3
   4

另请注意,上面的代码修复了最初在您的代码中的一个差一错误 - 该过程被调用 六次(从 05) 而不是预期的五次,这是因为 call 调用了 counter 五次,但是你在计算 (counter 0) 时又在外面调用了一次 counter