Lambda 使用词汇闭包的Racket

Lambda 使用词汇闭包的Racket,lambda,racket,lexical-closures,Lambda,Racket,Lexical Closures,我在《Let over Lambda》中读到了关于词法clojures的内容,并给出了针对Common Lisp的代码示例: (let ((counter 0)) (lambda () (incf counter))) 我试着在《球拍》中写道: (let ((counter 0)) (lambda() (+ counter 1))) 当我在REPL中将其称为计数器时,它给出了错误: counter: undefined; cannot reference an identifier

我在《Let over Lambda》中读到了关于词法clojures的内容,并给出了针对Common Lisp的代码示例:

(let ((counter 0))
  (lambda () (incf counter)))
我试着在《球拍》中写道:

(let ((counter 0))
  (lambda() (+ counter 1)))
当我在REPL中将其称为
计数器
时,它给出了错误:

counter: undefined;
 cannot reference an identifier before its definition

据我所知,将let/set与lambda混合使用可以在lambda中存储一些状态,这些状态可以由其他函数处理,就像人类记忆可以通过感官输入进行处理和更改一样。我感兴趣的是在我的LISP程序中有一些代码,这些代码由于与其他函数的交互而改变。即使这不是lambda做的,我仍然想理解它(lambda函数),因为它似乎是Racket和其他LISP方言的重要部分。

对于scheme/Racket,您需要使用
set
而不是
incf
,后者是一个Lisp函数(顺便说一句,
set!
不返回新值,不像
infc
)。

(incf x)
在公共Lisp中并不等同于Racket中的
(+x1)
,而是第一次递增
x
(set!x(+1))
,然后返回新值

所以,如果你想在Racket中定义一个类似的函数,你可以这样写,例如:

(define count
  (let ((counter 0))
    (lambda () (begin (set! counter (+ counter 1)) counter))))

(count)    ; returns 1

(count)    ; returns 2

它工作得很好。我将用这个技巧重写一些我以前做过的函数,看看我是否真的理解let over lambda。谢谢