“读者”的任务是什么?在 Lisp 解释期间?

发布于 2024-10-09 14:39:32 字数 413 浏览 0 评论 0原文

我想知道“读者”在解释/编译 Lisp 程序期间的目的,或者更准确地说,是“读者”的任务。

从我刚刚完成的问题前研究来看,在我看来,读者(特别是本例中的 Clojure)可以被视为“语法预处理器”。它的主要职责是读取器宏和原始形式的扩展。举两个例子:

'cheese         -->  (quote cheese)
{"a" 1 "b" 2}   -->  (array-map "a" 1 "b" 2)

读者接收程序文本(由 S 表达式组成),然后构建并返回可以直接计算的内存数据结构。

这与事实有多远(我是否过度简化了整个过程)?读者还执行哪些其他任务?考虑到 Lisps 的一个优点是它们的同像性(代码即数据),为什么需要词法分析(如果这确实与读者的工作相当)?

谢谢!

I'm wondering about the purpose, or perhaps more correctly, the tasks of the "reader" during interpretation/compilation of Lisp programs.

From the pre-question-research I've just done, it seems to me that a reader (particular to Clojure in this case) can be thought of as a "syntactic preprocessor". It's main duties are the expansion of reader macros and primitive forms. So, two examples:

'cheese         -->  (quote cheese)
{"a" 1 "b" 2}   -->  (array-map "a" 1 "b" 2)

So the reader takes in the text of a program (consisting of S-Expressions) and then builds and returns an in-memory data-structure that can be evaluated directly.

How far from the truth is this (and have I over-simplified the whole process)? What other tasks does the reader perform? Considering a virtue of Lisps is their homoiconicity (code as data), why is there a need for lexical analysis (if such is indeed comparable to the job of the reader)?

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

2024-10-16 14:39:32

通常,Lisp 中的读取器读取 s 表达式并返回数据结构。 READ 是一个 I/O 操作:输入是字符流,输出是 Lisp 数据。

打印机则相反:它获取 Lisp 数据并将其输出为字符流。因此它还可以将 Lisp 数据打印到外部 s 表达式。

请注意,解释意味着特定的事物:通过解释器执行代码。但许多 Lisp 系统(包括 Clojure)都在使用编译器。计算 Lisp 形式的值的任务通常称为评估。评估可以通过解释、编译或两者的结合来实现。

S-Expression:符号表达式。数据的外部文本表示。外部意味着 s 表达式是您在文本文件、字符串等中看到的内容。因此 s 表达式由某些介质(通常是外部介质)上的字符组成。

Lisp 数据结构:符号、列表、字符串、数字、字符...

Reader:读取 s 表达式并返回 Lisp 数据结构。

请注意,s 表达式也用于对 Lisp 源代码进行编码。

在某些 Lisp 方言中,读取器是可编程的并且是表驱动的(通过所谓的读取表)。该读取表包含字符的读取器函数。例如,quote ' 字符绑定到一个读取表达式并返回 (list 'quote expression) 值的函数。数字字符 0..9 绑定到读取数字的函数(实际上这可能更复杂,因为某些 Lisp 允许以不同的基数读取数字)。

S-表达式提供数据结构的外部语法。

Lisp 程序是使用 s-表达式以外部形式编写的。但并非所有 s 表达式都是有效的 Lisp 程序:

(if a b c d e)   is usually not a valid Lisp program

Lisp 语法通常是在 Lisp 数据之上定义的。

例如,IF 具有以下语法(在 Common Lisp 中 http://www.lispworks. com/documentation/HyperSpec/Body/s_if.htm ):

if test-form then-form [else-form]

因此它需要一个测试表单、一个 then 表单和一个可选的 else 表单。

作为 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 表达式是原始文本。当使用 READ 函数读取时,s 表达式将转换为数据。

因此,Lisp 中的基本交互顶层称为 REPL,即 Read 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 表单求值之前运行读取器(例如通过解释或编译并执行它)。

Generally the reader in Lisp reads s-expressions and returns data structures. READ is an I/O operation: Input is a stream of characters and output is Lisp data.

The printer does the opposite: it takes Lisp data and outputs those as a stream of characters. Thus it can also print Lisp data to external s-expressions.

Note that interpretation means something specific: executing code by an Interpreter. But many Lisp systems (including Clojure) are using a compiler. The tasks of computing a value for a Lisp form is usually called evaluation. Evaluation can be implemented by interpretation, by compilation or by a mix of both.

S-Expression: symbolic expressions. External, textual representation of data. External means that s-expressions are what you see in text files, strings, etc. So s-expressions are made of characters on some, typically external, medium.

Lisp data structures: symbols, lists, strings, numbers, characters, ...

Reader: reads s-expressions and returns Lisp data structures.

Note that s-expressions also are used to encode Lisp source code.

In some Lisp dialects the reader is programmable and table driven (via the so-called read table). This read table contains reader functions for characters. For example the quote ' character is bound to a function that reads an expression and returns the value of (list 'quote expression). The number characters 0..9 are bound to functions that read a number (in reality this might be more complex, since some Lisps allow numbers to be read in different bases).

S-expressions provide the external syntax for data structures.

Lisp programs are written in external form using s-expressions. But not all s-expressions are valid Lisp programs:

(if a b c d e)   is usually not a valid Lisp program

the syntax of Lisp usually is defined on top of Lisp data.

IF has for example the following syntax (in Common Lisp http://www.lispworks.com/documentation/HyperSpec/Body/s_if.htm ):

if test-form then-form [else-form]

So it expects a test-form, a then-form and an optional else-form.

As s-expressions the following are valid IF expressions:

(if (foo) 1 2)
(if (bar) (foo))

But since Lisp programs are forms, we can also construct these forms using Lisp programs:

(list 'if '(foo) 1 2) is a Lisp program that returns a valid IF form.

CL-USER 24 > (describe (list 'if '(foo) 1 2))

(IF (FOO) 1 2) is a LIST
0      IF
1      (FOO)
2      1
3      2

This list can for example be executed with EVAL. EVAL expects list forms - not s-expressions. Remember s-expressions are only an external representation. To create a Lisp form, we need to READ it.

This is why it is said code is data. Lisp forms are expressed as internal Lisp data structures: lists, symbols, numbers, strings, .... In most other programming languages code is raw text. In Lisp s-expressions are raw text. When read with the function READ, s-expressions are turned into data.

Thus the basic interaction top-level in Lisp is called REPL, Read Eval Print Loop.
It is a LOOP that repeatedly reads an s-expression, evaluates the lisp form and prints it:

READ :  s-expression ->  lisp data
EVAL :  lisp form    ->  resulting lisp data
PRINT:  lisp data    ->  s-expression

So the most primitive REPL is:

(loop (print (eval (read))))

Thus from a conceptual point of view, to answer your question, during evaluation the reader does nothing. It is not involved in evaluation. Evaluation is done by the function EVAL. The reader is invoked by a call to READ. Since EVAL uses Lisp data structures as input (and not s-expressions) the reader is run before the Lisp form gets evaluated (for example by interpretation or by compiling and executing it).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文