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

时间:2015-03-27 00:08:20

标签: lisp elisp

如果您编写(+ 2 3)之类的内容,+将被视为函数,如果+没有与之关联的任何函数定义,则会发生错误。

如果你写的是(let (a b c))(a b c)被读作数据。

lisp如何决定?

2 个答案:

答案 0 :(得分:5)

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

  1. 阅读和评估之间的区别
  2. 特殊表格
  3. 符号
  4. 阅读v。评估

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

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

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

    考虑列表程序:

    161
    

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

    161
    

    这里会发生以下情况:

    1. 读取读取表单“161”将转换为Lisp中数字161的对象。
    2. 评估:数字161是一种自我评估表单。所以161评估为161。
    3. 打印:数字161的打印表示为“161”。所以打印出这个号码。
    4. 循环:再次提示输入。
    5. 符号:自我评估表单

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

      abc
      

      该程序实际上会产生错误:

        

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

      这里发生的是:

      1. 读取s表达式“abc”
      2. 它是符号abc的读取形式,因此创建了对象。
      3. 符号abc计算其变量,但是,它当前没有变量(使用“void”),因此它出错
      4. 特殊形式setq会将符号设置为指向变量。更多关于以下内容。

        特殊表格

        从这里开始,Lisp就像大多数语言一样。调用(+ 1 (+ 2 3))将使用加号函数的命令式语言执行与plus(1, plus(2,3))相同的操作。整个表达式将为红色以构建列表对象(+ 1 (+ 2 3 )),该列表对象是三个元素+1和列表(+2 3)的列表。然后,作为函数调用的外部+将使解释器评估自我评估的对象1(+ 2 3),最终将评估为5。 +将获取两个已评估的对象15,然后添加它们,并返回6

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

        (setq a (+ 2 3))
        

        评估符号“a”,但将采用符号“a”并将其分配给(+ 2 3)评估的内容,即数字5.然后,调用< / p>

        a
        
        REPL中的

        将打印5

        所以回答原来的问题......“让”是一种特殊形式,因此不会立即评估其论点:)

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

答案 1 :(得分:1)

  

如果你写(let(a b c)),(a b c)被读作数据。

不是真的。一切都是一样的。首先阅读Lisp表单。充分。评估来得更晚。评估有所不同。

LET表达式是一种特殊形式,表单根据特殊规则进行评估。

请参阅Emacs Lisp手册:Parts of let Expression

Lisp

  • 函数调用,如(* a b)
  • 特殊表单,例如(let ((a 1)) a)。这些表单通常是内置的,不能由用户扩展。
  • 宏表单,例如(defun foo () nil)
  • 加上其他任何Lisp方言提供的......

标识符是列表中的第一个元素,它告诉我们如何评估表单。