符号值+,/和*

时间:2017-06-20 04:19:07

标签: operators common-lisp read-eval-print-loop

请考虑以下代码段:

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上了。
那么,这些运营商的这种行为是否有任何具体原因? 这些运营商的/是否具有历史意义? 任何帮助表示赞赏。

2 个答案:

答案 0 :(得分:6)

根据HyperSpec

  

变量*,**和***由Lisp read-eval-print循环维护,以保存每次循环打印的结果值。

     

*的值是最近打印的主要值,**的值是前一个值*,***的值是以前的值**。

/ and friends

  

变量/,//和///由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

但是在某些情况下(结果可能无法重现)这可能不起作用,或者可能需要大量的计算时间(取决于执行的计算)。

注意:保留对象的这些引用可以防止对象被垃圾收集,而这些引用存在。