方案读取函数的行为

scheme read function's behavior

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

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

当我输入 '() 时,我预计 (null? (read))#t(true)。不仅是 Gauche,MIT-Scheme 和 GNU/Guile 也是这样。

read 函数不计算给定的文本,它把它当作一个 未计算的表达式 和 returns 表达式树作为数据。例如:

(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 returns 表达式的数据表示已给定,所以 "adds a quote level"。我的意思是,要写一个等价的表达式,你必须用 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,而这又是 "removes",这一点变得更加模糊。但是,如果您专注于 ;= 表达式,就会更清楚为什么 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