为什么在 lisp 中将代码视为数据很有用

Sup*_*ver 2 lisp emacs macros eval homoiconicity

我现在学习 emacs lisp,我想知道为什么将代码视为数据可能有用。这种方法有什么好处。我看到了一种解释,因为这是对数据和代码之间存在明确分离的传统冯诺依曼架构的替代方案。我想了解这个决定的含义,明白了。

提前致谢,尼克。

Jay*_*Jay 5

您可以编写为您编写代码的代码。这可以通过两种方式完成:

  • 首先,您的程序可以创建新代码作为列表并将其传递给eval函数,该函数将在运行时评估新代码(但是,eval您不应该滥用它——实际上,它应该很少使用,当您真正需要它时)。理论上,您可以在不具有同音性属性的语言中执行此操作,但这会困难得多。例如,在 Scheme 中你可以这样做
(define form '(x 10))
(set! form (append 'define form)
(eval form (interaction-environment)
Run Code Online (Sandbox Code Playgroud)

之后的值为x10。例如,这可以用于遗传编程

  • 您还可以定义宏。宏是一个小函数,它读取一些看起来像函数调用的东西,但在程序开始评估表单之前(即在它运行之前)被翻译(扩展)成其他东西。例如,在许多 Lisps 中or是一个宏。这段代码,
(or a b c)
Run Code Online (Sandbox Code Playgroud)

被翻译成

(let ((tmp1 a))
  (if tmp1
      tmp1
      (let ((tmp2 b))
        (if tmp2
            tmp2
            (let ((tmp3 c))
              (if tmp3
                  tmp3
                  #f))))))
Run Code Online (Sandbox Code Playgroud)

您可以实现or为一个函数,但是该函数必须在返回之前评估其所有参数。由于or是一个宏,它不一定会评估所有参数。

您可以在维基百科这本很酷的书中阅读更多关于宏的信息[除了网络上的其他几个地方,例如这里这里这里]。您可以在 Wikipedia这本好书中阅读有关 eval 的信息。

你也可以阅读 Paul Graham 的On Lisp(这本书是完全免费的),它以有点快的速度讲授了基本的 Common Lisp,然后通过宏进入了各种编程技术,之后你可以尝试Let Over Lambda(只有部分章节)免费的)。

关于eval阅读这个问题及其答案可能会很有趣。