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

lisp如何决定是评估列表还是将其用作数据?,lisp,elisp,Lisp,Elisp,如果编写类似于(+23),则+将被视为一个函数,如果+没有任何与之关联的函数定义,则会发生错误 如果您编写类似于(let(abc)),则(abc)将被读取为数据 lisp是如何决定的?这里有两个基本的lisp概念需要理解: 阅读与评价的区别 特殊形式 象征 读。评价 阅读是将文本转换为lisp对象的行为。Lisp对象(如数字和列表)具有所谓的读取形式,即可以读入对象的文本表示形式。它通常与打印表单相同。如果您来自Java之类的语言,则toString()提供对象的打印形式。没有等效的阅读概念,因

如果编写类似于
(+23)
,则
+
将被视为一个函数,如果
+
没有任何与之关联的函数定义,则会发生错误

如果您编写类似于
(let(abc))
,则
(abc)
将被读取为数据


lisp是如何决定的?

这里有两个基本的lisp概念需要理解:

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

    值得注意的是,阅读与评估并不相同,尽管许多物体都是自我评估的。例如,数字是一个对象,在求值时返回自身。更常见的说法是,许多形式都是自我评估的,但您应该记住,上下文中的“形式”通常与“lisp对象”同义,这意味着将对对象进行评估

    当我们在一个RePL中运行一个简单的程序时,考虑一下发生了什么可能是有用的。回想一下,“REPL”代表“Read,evaluate,print,loop”,Lisp是这些步骤之间的区别非常明显的语言

    考虑列表程序:

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

    161
    
    这里发生的情况如下:

    161
    
  • 读取:读取格式“161”转换为Lisp中数字161的对象
  • 评估:数字161是一个自评估表单。因此,161评估为161
  • 打印:数字161的打印表示为“161”。所以这个数字是打印出来的
  • 循环:再次提示输入
  • 符号:非自我评估形式 符号的读取形式将是类似于
    abc
    的文本。符号的计算结果取决于它们所持有的变量。让我们在REPL中运行程序
    abc

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

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

    这里发生的是:

  • s-表达式“abc”为
  • 它是符号abc的读取形式,以便创建对象
  • 符号abc的计算结果为其变量,但它当前不包含任何变量(“使用了void”),因此它会出错
  • 特殊形式
    setq
    将符号设置为指向变量。下面将详细介绍

    特殊形式 从这里开始,Lisp就像大多数语言一样工作。调用
    (+1(+23))
    将执行与带有plus函数的命令式语言中的
    plus(1,plus(2,3))
    相同的操作。整个表达式将为红色,以构建列表对象
    (+1(+23))
    ,它是一个由三个元素组成的列表
    +
    1
    和列表
    (+23)
    。然后,作为一个函数调用的外部
    +
    ,将导致解释器计算对象
    1
    ,这是自评估,以及
    (+23)
    ,最终计算为5。然后,
    +
    将获取两个评估对象,
    1
    5
    ,并添加它们,然后返回
    6

    然而,Lisp有所谓的特殊形式。特殊表单可能会跳过求值步骤,只使用原始对象。例如,
    setq
    是一种特殊形式,用于计算第二个参数,而不是第一个参数

    (setq a (+ 2 3))
    
    不会计算符号“a”,但会将符号“a”分配给
    (+23)
    计算的对象,即数字5。然后,打电话

    a
    
    在REPL中,将打印
    5

    所以要回答最初的问题。。。“let”是一种特殊形式,因此不会立即计算其参数:)

    宏 宏也不会评估它们的参数,但可能不需要对原始问题进行充分讨论

    如果您编写类似(let(abc)),则(abc)将作为数据读取

    不是真的。一切都是一样的。首先读取Lisp表单。充分地评估时间较晚。评价起作用

    LET
    表达式是一种特殊形式,该形式根据特殊规则求值

    请参阅Emacs Lisp手册:

    口齿不清

    • 函数调用类似于
      (*ab)
    • 特殊形式
      (let((a 1))a)
      。这些表单通常是内置的,用户无法扩展
    • 宏表单类似于
      (defun foo()nil)
    • 再加上Lisp方言的其他功能

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

    Lisp宏也(并且必须)不计算其参数。结果是,如果您还不知道某个给定调用是否会计算其参数,则无法通过查看该调用的代码来判断。也就是说,在大多数情况下,您可以从上下文中进行很好的猜测。将读取、计算+的参数,然后将其馈送到+,。没有交叉阅读。在求值之前已读取完整表达式。似乎,
    也立即求值,根据。正如所说,符号本身的初始值为零。