关于带后缀的Scheme的问题



这是我关于后缀在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从来没有任何关于变量的信息,这些变量在某种程度上是在与它使用的相同作用域中定义的。因此,es不存在。通常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)))

takedrop不是R5RS,但它们很容易创建。

相关内容

  • 没有找到相关文章

最新更新