方案读取功能的行为

时间:2018-08-14 14:20:22

标签: scheme mit-scheme guile

我无法理解此方案read函数的行为。

gosh> (null? '())
#t
gosh> (null? (read))
'()
#f
gosh> (define a (read))
'()
a
gosh> a
'()
gosh> (null? a)
#f

当我输入(null? (read))时,我期望#t'()(真)。不仅Gauche,而且MIT-Scheme和GNU / Guile的行为都如此。

1 个答案:

答案 0 :(得分:0)

read函数不会计算给定的文本,而是将其视为未求值的表达式,并将表达式树作为数据返回。例如:

(read)  ;input: (+ 4 5)

等效于(list '+ 4 5)

> (read)  ;input: (+ 4 5)
(+ 4 5)
> (list '+ 4 5)
(+ 4 5)
> (equal? (read) (list '+ 4 5))  ;input: (+ 4 5)
#t

从现在开始,我将使用;=语法来演示如何使用list之类的构造函数来编写它。

> (read)  ;input: (+ 4 5)
;= (list '+ 4 5)
(+ 4 5)

现在,由于read返回其给定表达式的数据表示形式,因此它“添加了引号级别”。我的意思是要编写一个等效的表达式,您必须将quote包裹起来。

> (read)  ;input: (+ 4 5)
;= (list '+ 4 5)
;= '(+ 4 5)
> (read)  ;input: (quote (+ 4 5))
;= (list 'quote (list '+ 4 5))
;= '(quote (+ 4 5))
;= ''(+ 4 5)

由于readwrite处理的是未求值的表达式,因此read函数似乎增加了引号级别,而write函数似乎会删除报价等级:

> (write '(+ 4 5))
;output: (+ 4 5)
> (write ''(+ 4 5))
;output: '(+ 4 5)
> (write '''''(+ 4 5))
;output: ''''(+ 4 5)

read函数的作用相反,似乎增加了引号级别。但是,由于Scheme Repl使用write(又将其“删除”)这一事实,因此变得更加晦涩。但是,如果您专注于;=表达式,则更清楚为什么readwrite是相反的:

> (read)  ;input (+ 4 5)                  (no quotes)
;= '(+ 4 5)                               (one quote)
(+ 4 5)                                   (the `write` function removes a quote)
> (read)  ;input '(+ 4 5)                 (one quote)
;= ''(+ 4 5)                              (two quotes)
'(+ 4 5)                                  (the `write` function removes a quote)
> (read)  ;input '''(+ 4 5)               (three quotes)
;= ''''(+ 4 5)                            (four quotes)
'''(+ 4 5)                                (the `write` function removes a quote)

现在回到您的示例:

> (read)  ;input: '()
;= ???
???

由于read添加了引号以将表达式表示为数据,因此读取'()等效于''()

> (read)  ;input: '()
;= ''()
;= (list 'quote (list))
'()
> (define a (read))  ;input: '()
> a
;= ''()
;= (list 'quote (list))
'()
> (equal? a ''())
#t
> (equal? a (list 'quote (list)))
#t

要实际获得等于'()的东西,使其变为null?,必须输入()作为输入。

> (read)  ;input: ()
;= '()
;= (list)
()
> (define a (read))  ;input: ()
> a
;= '()
;= (list)
()
> (equal? a '())
#t
> (null? a)
#t