Elisp: 在使用let*和(lambda)时符号作为变量的值为空。

4

声明:我今天开始尝试使用elisp进行编码。

我真的很想知道为什么会出现以下错误:

Symbol's value as variable is void: response

使用以下代码:
(let* ((response (cons 'dict nil)))
  (nrepl-request:eval
   code 
   (lambda (resp) 
      (print resp (get-buffer "*sub-process*"))
      (nrepl--merge response resp))
   (cider-current-connection) 
   (cider-current-session)))

我的理解是,当从 lambda 函数调用时,responselet* 子句的作用域内...但显然不是这样。 这段代码也似乎在工作。所以我对为什么会出现这种错误感到有些困惑,不知道该怎么做。

使用动态绑定,response 的值在定义 lambda 时被绑定,但显然该函数不会在同一作用域内被调用,因此 response 在那个时候没有值(除非它在其他地方被绑定)。 - phils
1个回答

10

您需要指定词法绑定,通过在源文件中将全局变量lexical-binding设置为文件本地变量。请在文件的第一行放置以下行:

;;;  -*- lexical-binding: t -*-

要么这样做,要么使用lexical-let*代替let*
或者,如果在调用匿名函数时您不需要变量response作为变量,也就是说,如果您只需要其在定义函数时的值,则可以使用以下方法:
(let* ((response (cons 'dict nil)))
  (nrepl-request:eval
   code 
   `(lambda (resp) 
      (print resp (get-buffer "*sub-process*"))
      (nrepl--merge ',response resp)) ; <===== Substitute value for variable
   (cider-current-connection) 
   (cider-current-session)))

使用词法变量,当你对文件进行字节编译时,Lambda表达式会被编译。如果没有变量(即只有其值),Lambda表达式不会被编译 - 它只是一个列表(其中car为lambda等)。


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