有词法作用域才有闭包,所以上面代码用elisp写就不是闭包,需要使用lexical-let
我的意思是启动词法作用域,不然我上面举的例子,就不是下面这种格式了。
(closure ((count . 0) t) nil (lambda () …))
而应该是这种格式了
(lambda () …)
看起来是而已
(let ((a (list 1 2 3))) (setq b a fn (lambda () a)))
(cl-assert (eq (eq b (funcall fn)) t))
听起来common lisp使用了引用捕捉(capture by reference),而elisp使用了值捕捉(capture by value)
lambda的词法作用域确实有这两种实现。
比如:Java就是值捕捉。
因此,如果你想在elisp里也实现引用捕捉,方法就是用另一个对象把它包起来(i.e: Box它),这种手段在Java的lambda里也经常使用,比如用一个数组把对象包起来 [你的对象]
都说了看起来是,你跑跑我上面的代码就知道了,eq可是只有引用相等的时候才能返回t的。(把list换成hash-table之流也一样)
你问为啥这么诡异?要序列化的嘛
你在回复我吗?我在提醒列表里收到了Notification。。。
这鬼论坛的回复机制有问题:
只回一楼或楼上不提示,但如果一楼和楼上不是同一个人的时候,无法区分到底回复的是谁。。。
是回复你,紫薯补丁
三楼是回复楼主的。
我在5楼反驳你是因为你觉得Elisp是值捕获,然而人家是正版的引用捕获。
你解答错了。那一句算是我自问自答
那你3楼是回复谁的?
这论坛我真看不懂。。。
我不清楚你这个代码想描述什么?
另外还有个问题,就是:楼主说Elisp和Common Lisp的实现有区别。
这里Elisp是跑Emacs里的(Emacs本身就是运行时环境),而Common Lisp是另一个语言,应该在别的运行时环境里(Emacs只是作为编辑器)。但是ELisp又支持CL宏,这导致问题复杂化。
你让我跑这段代码,到底是要我在Emacs里跑,还是在CL的专有环境里跑?
楼主的情况也类似。
我只是说听起来。。。
这么说的话Elisp也是引用捕获。
换句话说是楼主的实验结果有问题。。。
不是,你大概不懂啥叫序列化。
我之前做了点实验
说明一个闭包打印/序列化成 (closure ...)
是损失了额外的信息的。
你还不知道 Emacs 24 开始就有了 (setq lexical-binding t)
吧。
我知道有,但默认不开。
刚才测试了一下,你的这个实验在ELisp上确实没Crash。
但这并不能说明ELisp就是capture by reference,因为如果是capture by value的话,结果也是一样的。
注意:a的值实际上是list的地址,即使是capture by value,它照样获得list的地址。所以打印出来地址一样并不能说明什么。
以下证明Elisp是capture by reference
(setq lexical-binding t)
(let ((x "1" ))
(progn
(message x)
((lambda () (setq x "2" )))
(message x)))
如果是Java的话(capture by value),则对局部lambda里面的那个x修改,不会影响到外面。
有图有真相
#1 才是关键所在
Capture by value 就不会有 eq 这玩意了
好的,#1说明是capture by reference
到公司我就不用再验证了
歪楼请教个问题
里面的 “一只满嘴名言的牛” 有一句
A LISP programmer knows the value of everything, but the cost of nothing.
该如何理解这句话。
不知道,因为 LISP 是五十多年前的事了,不是当时的硬件就没有什么实感。老夫都没到五十岁。
序列化,基本上所有语言都有。你这里指的是list或object转化为可打印形式,还是指其它的什么?
你的实验倒是和我昨晚留作今天要确认的问题相关
我现在正在看Practical Common lisp,每天能抽出来的时间不多,就一天一章的消化吧。好在一章内容才十几页