我想知道在解释/编译Lisp程序时“读者”的任务是什么,或者更准确地说,是什么。
从我刚刚做的预问题研究来看,在我看来,读者(在这种情况下特别是Clojure )可以被认为是一个“语法预处理器”。它的主要职责是扩展阅读器宏和原始形式。所以,有两个例子:
'cheese --> (quote cheese)
{"a" 1 "b" 2} --> (array-map "a" 1 "b" 2)因此,阅读器接收程序的文本(由S表达式组成),然后构建并返回可直接计算的内存中数据结构。
这离事实有多远(我是否过度简化了整个过程)?阅读器还执行哪些其他任务?考虑到Lisp的一个优点是它们的相似性(代码作为数据),为什么需要词法分析(如果这确实可以与读者的工作相媲美)?
谢谢!
发布于 2010-12-27 19:06:34
通常,Lisp中的读取器读取s表达式并返回数据结构。读取是一个I/O操作:输入是一个字符流,输出是Lisp数据。
打印机做了相反的事情:它获取Lisp数据并将其作为字符流输出。因此,它还可以将Lisp数据打印到外部s表达式。
请注意,解释意味着一些特定的东西:由解释器执行代码。但是许多Lisp系统(包括Clojure)都在使用编译器。为Lisp表单计算值的任务通常称为求值。评估可以通过解释、编译或两者的混合来实现。
S-Expression:符号表达式。数据的外部文本表示。外部表示s表达式是您在文本文件、字符串等中看到的表达式。因此,s表达式是由某些介质(通常是外部介质)上的字符组成的。
Lisp数据结构:符号,列表,字符串,数字,字符,...
Lisp :读取s表达式并返回数据结构。
请注意,s-expression也用于编码Lisp源代码。
在一些Lisp方言中,阅读器是可编程的,并且是表驱动的(通过所谓的读表)。此读取表包含字符的读取器函数。例如,'quote‘字符绑定到一个函数,该函数读取一个表达式并返回(list’quote expression)的值。数字字符0..9绑定到读取数字的函数(实际上,这可能更复杂,因为一些Lisp允许以不同的基数读取数字)。
S表达式提供了数据结构的外部语法。
Lisp程序是使用s表达式以外部形式编写的。但并非所有的s-expression都是有效的Lisp程序:
(if a b c d e) is usually not a valid Lisp programLisp的语法通常是在Lisp数据之上定义的。
IF具有例如以下语法(在Common Lisp http://www.lispworks.com/documentation/HyperSpec/Body/s_if.htm中):
if test-form then-form [else-form]所以它需要一个test-form,一个then-form和一个可选的else-form。
作为s表达式,以下IF表达式有效:
(if (foo) 1 2)
(if (bar) (foo))但是因为Lisp程序是表单,所以我们也可以使用Lisp程序构造这些表单:
(list 'if '(foo) 1 2)是一个返回有效IF表单的Lisp程序。
CL-USER 24 > (describe (list 'if '(foo) 1 2))
(IF (FOO) 1 2) is a LIST
0 IF
1 (FOO)
2 1
3 2例如,该列表可以通过EVAL执行。EVAL需要列表形式,而不是s-表达式。请记住,s表达式只是一种外部表示。要创建一个Lisp表单,我们需要读取它。
这就是为什么说代码就是数据。Lisp表单表示为内部Lisp数据结构:列表、符号、数字、字符串、...在大多数其他编程语言中,代码都是原始文本。在Lisp中,s-expression是原始文本。使用函数READ读取时,s表达式将转换为数据。
因此,Lisp中最顶层的基本交互称为REPL,即Eval Print Loop。它是一个循环,重复读取s表达式,计算lisp表单并打印出来:
READ : s-expression -> lisp data
EVAL : lisp form -> resulting lisp data
PRINT: lisp data -> s-expression所以最原始的REPL是:
(loop (print (eval (read))))因此,从概念的角度来看,为了回答你的问题,在评估过程中,读者什么也不做。它不参与评估。通过函数EVAL进行求值。读取器通过调用READ来调用。因为EVAL使用Lisp数据结构作为输入(而不是s表达式),所以阅读器在Lisp表单被计算之前运行(例如,通过解释或者通过编译和执行)。
https://stackoverflow.com/questions/4537793
复制相似问题