lisp如何决定是评估列表还是将其用作数据?

dje*_*lin 0 lisp elisp

如果您编写类似的东西(+ 2 3),则将+其视为函数,如果+没有与之关联的任何函数定义,则会发生错误.

如果你写的东西(let (a b c)),(a b c)读作数据.

lisp如何决定?

dje*_*lin 6

这里有两个基本的lisp概念:

  1. 阅读和评估之间的区别
  2. 特殊形式
  3. 符号

阅读v.评估

读取是将文本转换为lisp对象的行为.诸如数字和列表之类的Lisp对象具有所谓的读取形式,这是一种可以读入对象的文本表示.它通常与打印格式相同.如果您来自Java等语言,toString()会提供对象的打印形式.没有相同的读取概念,因为Lisp具有有趣且强大的属性,Lisp源代码是一个lisp对象.

重要的是要注意阅读与评估不同,尽管许多对象都是自我评估的.例如,数字是一个在评估时返回自身的对象.更常见的是说许多表单都是自我评估的,但你应该记住,上下文中的"表单"通常与"lisp对象"同义,其含义是对象将被评估.

考虑在REPL中运行简单程序时会发生什么可能是有用的.回想一下,"REPL"代表"读取,评估,打印,循环",而Lisp是这些步骤之间的差异真正清晰的语言.

考虑列表程序:

161
Run Code Online (Sandbox Code Playgroud)

在REPL中运行它时,结果如下:

161
Run Code Online (Sandbox Code Playgroud)

这里发生的是以下内容:

  1. 读取:读取形式 "161"转换为Lisp中的数字161的对象.
  2. 评估:数字161是一种自我评估的形式.所以161评估为161.
  3. 打印:数字161的打印表示为"161".所以打印这个号码.
  4. 循环:再次提示输入.

符号:不是自我评估的形式

符号的读取形式将是文本abc.符号评估它们所持有的变量.让我们abc在REPL中运行程序:

abc
Run Code Online (Sandbox Code Playgroud)

该程序实际上产生错误:

eval-last-sexp-1:符号作为变量的值为void:abc

这里发生的是:

  1. 读取s表达式"abc"
  2. 它是符号abc的读取形式,因此创建了对象.
  3. 符号abc计算其变量,但是,它当前没有变量(使用"void"),因此它出错

特殊形式setq将符号设置为指向变量.更多关于以下内容.

特殊形式

从这里开始,Lisp就像大多数语言一样.调用(+ 1 (+ 2 3))plus(1, plus(2,3))使用带有加号函数的命令式语言执行相同的操作.整个表达式将为红色以构建列表对象(+ 1 (+ 2 3 )),列表对象是三个元素的列表+,1以及列表(+2 3).然后,外+,作为一个函数调用,将导致解释评价的对象1,这是自我评估和(+ 2 3),这将最终评估为5.然后+将两个评价对象,1并且5,并将其添加和返回6.

但是,Lisp具有所谓的特殊形式.特殊表单可能会跳过评估步骤,只使用原始对象.例如,setq是一个评估第二个参数但不是第一个参数的特殊形式.

(setq a (+ 2 3))
Run Code Online (Sandbox Code Playgroud)

不会评估符号"A",但将采取符号"A",并将其分配到什么(+ 2 3)计算结果为,即5号.然后,调用

a
Run Code Online (Sandbox Code Playgroud)

在REPL中将打印5.

所以回答原来的问题......"让"是一个特殊的形式,所以它的参数不会立即评估:)

宏也不评估他们的论点,但对原始问题可能没有必要进行全面讨论.