有关lambda语法的疑问

此表达式返回 t

(funcall (list 'lambda nil t))

此表达式返回什么?

(funcall (list (make-symbol "lambda") nil t))

又到了我第二喜欢的 Elisp 小问题时间

(let ((print-circle t)
      (print-gensym t))
  (eq 'lambda (make-symbol "lambda")))
;;=> nil

实现上,Qlambda(make-symbol "lambda") 不是一个东西。

可抛开实现不谈 [狗头保命],当我们在求值lambda的时候,lambda究竟是什么?

我起初的理解是:lambda表达式等于以lambda符号为car的list。

然而,这里似有种 此 'lambda 非 彼'lambda 的异样感。

于是,我又想问了:作为上层用户,语义上说,两个都是symbol,都是lambda symbol;为什么不让它们表现一致呢?

就是符号。

确实不是一个东西, 'lambdaintern 的符号,而 make-symbol 没有

因为解释器只认得 internlambda

如果让解释器忘掉intern与unintern会怎么样?intern和unintern对lexical binding有影响吗,或者说,intern和unintern之分是dynamic binding的产物吗?

如果每次读入的 symbol 都是 uninterned ,那代码中的符号就是不固定的,符号的指向不明确。

当然你的意思应该是所有的符号都是 intern 的,或者说我感觉这更合理一点。但这样的话宏的名字冲突问题可能更难避免。

没有关联

我之前的理解无intern和unintern之分。intern似出于实现方便而将symbol这个概念进一步分化出的结果。

宏名和函数名有差异吗,有什么例子吗?我目前(未必正确的)感觉,“宏名”应该和“函数名”同属于“符号”范畴。按理说(在不考虑elisp的历史遗留代码的前提下),它们应只存在于定义它们的范围内,类似于存在某个定义他们的package内;应该在引用的位置用类似python/java之类的import的方式引入“缩写名”。

可以说,elisp把符号命名空间的事情全扔给用户考虑了(也无可厚非)。

我对你这句话的理解是「intern 的出现是因为这样实现 symbol 更加方便」,如果理解有误,可以展开详细讲讲。

(defmacro hello (x)
  `(lambda (y) (+ ,x y)))

(defmacro hello* (x)
  (let ((y (make-symbol "y")))
    `(lambda (,y) (+ ,x ,y))))

对前者有以下例子说明名字冲突:

(setq y 20)
(setq a (hello y))
(funcall a 30)
;;=> 60, not 50

嗯,差不多,我是拍脑袋想的,没细究过。可能unintern似为后续不同范围内的符号binding而生出的东西。我拍脑袋想:最初只有一个全局obarray,现在开始分化符号定义的范围,允许用户定义obarray,而emacs内置的那个算intern?

两个例子似乎都是60?在ielm中执行的话。

考虑到 Elisp 某种意义上来说是 Common Lisp(和 MacLisp)的阉割版,也许最好看一下 Common Lisp 中有没有类似的东西,然后 Emacs Lisp 把它阉割了,这个可能性应该大一点。

你的lexical-binding启用了吗?

因为原始的 lisp 是没有 string 类型的,intern 的本意就是把字符串比较简化成指针比较,再把它变回逐个字符比较不就白优化了

unintern? 提供一个删除定义的方法罢了。

不影响已经定义的函数对 symbol 被 unintern 的函数的调用,因为被 unintern 的 symbol 的地址并没有改变。

当然是有可能把 Emacs 环境破坏到不重启解决不了的程度的。

之前我贴的一版是错的。

这事情最痛苦的在于:各家都有各家的说法,而作为Emacs用户,只能把自己绑在elisp上。

你需要写出来实际运用到这些实现细节的代码吗?不需要的话,Emacs 怎么实现和你无关。需要的话,直接读 Emacs 代码就行。

这事情最痛苦的在于,有人试图用在脑内运行代码得到的不存在不一致不合理的想当然行为去要求改变实际实现存在即合理的行为。

www,完全没必要这么想,因为这些差异对写 Elisp 来说没什么太大的影响。

:joy:赞同。

嗯,只是了解下,看看有没有人遇到过类似的疑问。

写法一:

上述的写法属于有问题(或者说,不推荐)的一类,是吗?

我目前理解是: lambda 的参数(自由变量 y,是一个符号,“符号y” )解绑了 ,x 求值出的“符号y” 在 defmacro 外部的绑定—— (setq y 20) 。因为 elisp 把这两个 y 当成同一个“符号y”;而下面的写法因为 make-symbol 导致 ,Y,x 求值出的 “符号y” 并非同一个东西。

写法二:

如果从一开始 ,x 求值出的 “符号y” 和 lambda 的自由变量 y 不是同一个东西的话,写法一的问题也就不存在了;或者说,(lambda (y) ...)y 不应该绑定到默认的 interned y ,而是每一个自由变量都应该生成一个 y+counter

这样就不会有写法二;或者说,写法二才是写法一本应实现的样子。

(这句是我的暴论)而对于用户用 make-symbol 创建的任意symbol,就应该和字面 (quote symbol) 或者 'symbol 是同一个东西。

可能有点关系吧,涉及代码生成的。