请考虑以下代码段:
json
所以,根据我的观察,
model/collection
的符号值是REPL的最后一个输入。 [1]> (symbol-value '+)
NIL
[2]> +
(SYMBOL-VALUE '+)
[3]> (symbol-value '/)
((SYMBOL-VALUE '+))
[4]> (symbol-value '+)
(SYMBOL-VALUE '/)
[5]> *
(SYMBOL-VALUE '/)
的符号值是括号中REPL的最后一个输出。+
的符号值是REPL的最后一个输出。似乎没有理由检查你的最后一个输入,最后一个输出是什么,因为它已经在REPL上了。
那么,这些运营商的这种行为是否有任何具体原因?
这些运营商的/
是否具有历史意义?
任何帮助表示赞赏。
答案 0 :(得分:6)
根据HyperSpec:
变量*,**和***由Lisp read-eval-print循环维护,以保存每次循环打印的结果值。
*的值是最近打印的主要值,**的值是前一个值*,***的值是以前的值**。
变量/,//和///由Lisp read-eval-print循环维护,以保存在循环结束时打印的结果值。
/的值是打印的最新值的列表,//的值是/的先前值,而///的值是//的先前值。
最后是+ and friends:
变量+,++和+++由Lisp read-eval-print循环维护,以保存最近评估过的表单。
+的值是最后评估的形式,++的值是前一个值+,+++的值是++的前一个值。
你在问:
这是什么原因?
REPL是一个交互式文本环境:在许多此类系统中,如unix shell,总是有一些方便的方法可以重复最后一个命令,或使用最后一个值,而无需明确复制这样的值或重新输入它们(例如考虑旧的文本终端,其中没有可用的复制/粘贴操作)。所以这些变量是这个时代的遗物(但是,尽管如此,对于像我这样的懒人仍然有用,首先尝试获得某个值,然后,例如,通过简单的方式将全局变量分配给这样的值按键*
,而不必复制和粘贴打印的值。
答案 1 :(得分:4)
符号值
(symbol-value '*some-special-var*)
和*some-special-var*
之间没有区别。尽管它们是不同的表达式,但两者都计算相同的值。
CL-USER 47 > 1
1
CL-USER 48 > 2
2
CL-USER 49 > 3
3
CL-USER 50 > (list (list * (symbol-value '* ))
(list ** (symbol-value '** ))
(list *** (symbol-value '***)))
((3 3) (2 2) (1 1))
这些变量的一个原因:在REPL中重复使用不可读的对象
在Lisp中,可以创建无法可读打印的对象。 Lisp不仅是一种文本语言,也是一种数据语言。拥有最后结果的变量,输入......使重用这些对象稍微方便一些。一些Lisp侦听器具有更广泛的机制来引用对象或其中的一部分。 Common Lisp标准化了一个简单的变体。
没有或没有完整可读文本打印表示的对象的示例是CLOS对象,闭包和函数对象,流,哈希表,某些数组,外部数据,......这些类型的对象可以打印,但输出不会读者可以使用它来获取原始对象或重建类似的对象。
通常可以回读文本表示,但不会创建相同的对象 - 这有时会很有用。
CL-USER 41 > (lambda (a) (1+ a))
#<anonymous interpreted function 4060000984>
CL-USER 42 > 42
42
CL-USER 43 > (funcall ** *)
43
如您所见,在上面的示例中,如果计算结果41只是文本,则无法粘贴和回读。
CL-USER 44 > #<anonymous interpreted function 4060000984>
Error: Subcharacter #\< not defined for dispatch char #\#.
1 (abort) Return to level 0.
2 Return to top loop level 0.
必须有一些机制来记住它的价值。将结果分配给标准变量是一种方法。另一种方法是复制子表单并重新计算对象:
CL-USER 45 > (funcall (lambda (a) (1+ a)) 42)
43
但是在某些情况下(结果可能无法重现)这可能不起作用,或者可能需要大量的计算时间(取决于执行的计算)。
注意:保留对象的这些引用可以防止对象被垃圾收集,而这些引用存在。