“读取器”的任务是什么,在Lisp解释? [英] What are the tasks of the "reader" during Lisp interpretation?

查看:120
本文介绍了“读取器”的任务是什么,在Lisp解释?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



问题研究我刚刚做了,在我看来,一个读者(特别是在这种情况下,Clojure)可以被认为是一个句法预处理器。它的主要职责是扩展读取器宏和原始形式。所以,两个例子:

 'cheese  - > (quote cheese)
{a1b2} - > (array-mapa1b2)

一个程序(由S-Expressions组成),然后构建并返回一个可以直接求值的内存中数据结构。



并且我过度简化了整个过程)?读者执行什么其他任务?考虑到Lisps的美德是他们的同性性(代码作为数据),为什么需要词汇分析(如果这确实可以与读者的工作相比较)?



谢谢!

解决方案

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



Lisp数据并将其作为字符流输出。因此,它还可以将Lisp数据打印到外部s表达式。



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



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



strong> Lisp数据结构:符号,列表,字符串,数字,字符,...



<表达式并返回Lisp数据结构。



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



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



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



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

 (如果abcde)通常不是有效的Lisp程序



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



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

 如果test-form then-form [else-form ] 

所以它期望一个测试形式,一个then形式和一个可选的else形式。 / p>

作为s表达式,以下是有效的IF表达式:

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

因为Lisp程序是表单,我们还可以使用Lisp程序构造这些表单:



(list'if'(foo)1 2)是一个Lisp程序, IF形式。

  CL-USER 24> (如果(FOO)1 2)是一个列表
0 IF
1(FOO)
2 1
3 2

此列表可以例如使用EVAL执行。 EVAL期望列表形式 - 而不是s表达式。记住s表达式只是一个外部表示。要创建一个Lisp表单,我们需要阅读它。



这就是为什么说代码是数据。 Lisp形式表示为内部Lisp数据结构:列表,符号,数字,字符串,....在大多数其他编程语言中,代码是原始文本。在Lisp中s表达式是原始文本。当使用函数READ读取时,s表达式被转换为数据。因此,Lisp中的基本交互顶层被称为REPL,Read Eval打印循环。
这是一个重复读取s表达式的LOOP,评估lisp表单并打印:

  s表达式> lisp数据
EVAL:lisp表单 - >导致lisp数据
PRINT:lisp data - > s-expression

所以最原始的REPL是:

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


$ b b

因此,从概念的角度来看,为了回答你的问题,在评估期间,读者什么都不做。它不参与评价。通过函数EVAL进行评估。读取器通过调用READ来调用。因为EVAL使用Lisp数据结构作为输入(而不是s表达式),读者在Lisp表单被评估之前运行(例如通过解释或通过编译和执行它)。


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!

解决方案

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).

这篇关于“读取器”的任务是什么,在Lisp解释?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆