这是我关于后缀在scheme中的代码:
(define (stackupdate e s)
(if (number? e)
(cons e s)
(cons (eval '(e (car s) (cadr s))) (cddr s))))
(define (postfixhelper lst s)
(if (null? lst)
(car s)
(postfixhelper (cdr lst) (stackupdate (car lst) s))))
(define (postfix list)
(postfixhelper list '()))
(postfix '(1 2 +))
但是当我试图运行它时,编译器说它取错了。我试着检查了一下,但还是找不到错误的原因。有人能帮我吗?非常感谢!编译器是这样说的:
e: unbound identifier;
also, no #%app syntax transformer is bound in: e
eval
从来没有任何关于变量的信息,这些变量在某种程度上是在与它使用的相同作用域中定义的。因此,e
和s
不存在。通常eval
是错误的解决方案,但如果您要使用eval,请尽可能少地使用它:
;; Use eval to get the global procedure
;; from the host scheme
(define (symbol->proc sym)
(eval sym))
现在代替(eval '(e (car s) (cadr s)))
你做((symbol->proc e) (car s) (cadr s))
。现在你应该试试(postfix '(1 2 pair?))
我做了很多解释器,没有一个使用eval
。下面是我通常会做的事情:
;; Usually you know what operators are supported
;; so you can map their symbol with a procedure
(define (symbol->proc sym)
(case sym
[(+) +]
[(hyp) (lambda (k1 k2) (sqrt (+ (* k1 k1) (* k2 k2))))]
[else (error "No such operation" sym)]))
这修复了(postfix '(1 2 pair?))
问题。我在你的代码中看到的一件事是,你总是假设两个参数。但是你怎么做一个double
呢?例如,一个参数的两倍。在这种情况下,symbol->proc
可以返回更多信息:
(define (symbol->op sym)
(case sym
[(+) (cons + 2)]
[(double) (cons (lambda (v) (* v v)) 1)]
[else (error "No such operation" sym)]))
(define op-proc car)
(define op-arity cdr)
在你的代码中,如果它不是一个数字,你可以这样做:
(let* ([op (symbol->op e)]
[proc (op-proc op)]
[arity (op-arity op)])
(cons (apply proc (take s arity)
(drop s arity)))
take
和drop
不是R5RS,但它们很容易创建。