我无法理解此方案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的行为都如此。
答案 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)
由于read
和write
处理的是未求值的表达式,因此read
函数似乎增加了引号级别,而write
函数似乎会删除报价等级:
> (write '(+ 4 5))
;output: (+ 4 5)
> (write ''(+ 4 5))
;output: '(+ 4 5)
> (write '''''(+ 4 5))
;output: ''''(+ 4 5)
read
函数的作用相反,似乎增加了引号级别。但是,由于Scheme Repl使用write
(又将其“删除”)这一事实,因此变得更加晦涩。但是,如果您专注于;=
表达式,则更清楚为什么read
和write
是相反的:
> (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