我正在尝试定义一个读取字符串长度的读取器宏。该字符串将包含在垂直条(管道)中。例如:
|yes|
->3
||
->0
|The quick brown fox|
->19
|\||
->1
— 管道字符可以通过在它前面加一个反斜杠来转义。(let ((x |world|)) (+ |hello| x))
->10
我设法写了这个:
#lang racket
(define (handle-pipe in [count 0])
(define cur-char (read-char in))
(cond [(eqv? cur-char #\|)
count]
[else
(when (and (eqv? cur-char #\\) ; Handle escape ("\|").
(eqv? (peek-char in) #\|))
(read-char in)) ; Consume |.
(handle-pipe in (+ count 1))]))
(parameterize ([current-readtable
(make-readtable (current-readtable)
#\|
'terminating-macro
(lambda (char in src-name line col pos)
(handle-pipe in)))])
(eval (read (open-input-string "(let ((x |world|)) (+ |hello| x))"))
(make-base-namespace)))
10
正如预期的那样,这将返回。
现在的问题是:我想直接在我的 Racket 代码中使用 reader 宏,而不必将字符串输入(eval (read (open-input-string ...)))
. 例如,我想像这样使用阅读器宏:
#lang racket
(define (handle-pipe in [count 0])
(define cur-char (read-char in))
(cond [(eqv? cur-char #\|)
count]
[else
(when (and (eqv? cur-char #\\) ; Handle escape ("\|").
(eqv? (peek-char in) #\|))
(read-char in)) ; Consume |.
(handle-pipe in (+ count 1))]))
(current-readtable
(make-readtable (current-readtable)
#\|
'terminating-macro
(lambda (char in src-name line col pos)
(handle-pipe in))))
(let ((x |world|)) ; Using the reader macro directly in Racket.
(+ |hello| x))
但是,当我运行上面的程序时出现错误消息:
my-program.rkt:20:9: world: unbound identifier
in: world
location...:
my-program.rkt:20:9
context...:
do-raise-syntax-error
for-loop
[repeats 1 more time]
finish-bodys
lambda-clause-expander
for-loop
loop
[repeats 3 more times]
module-begin-k
expand-module16
expand-capturing-lifts
temp118_0
temp91_0
compile15
temp85_0
standard-module-name-resolver
我做错了什么?如何在我的代码中使用阅读器宏?