我正在使用从Solving Infix Arithmatic in LISP修改的以下代码,并将Check if an argument is a list or an atom中的atom定义为具有中缀算术求解器:
(define atom? (or/c number? symbol? boolean? string?))
(define (solve expression)
(define templist '())
(println expression)
(if (atom? expression)
expression
(begin
(set! templist (list (second expression)
(solve (first expression))
(solve (third expression)) ))
(println templist)
(eval templist) ) ) )
(solve '(3 + 2))
输出如下:
'(3 + 2)
3
2
'(+ 3 2)
+: unbound identifier;
also, no #%app syntax transformer is bound in: +
因此,临时列表可以正确创建(+ 3 2),但在eval级别存在错误。为什么' +'被视为未绑定的标识符'? eval函数在DrRacket的命令行中运行良好:
> (eval '(+ 3 2))
5
问题出在哪里?如何解决?感谢。
答案 0 :(得分:3)
您是否从以前的问题的答案中学到了什么?不要使用set!
,这不是好的Scheme / Racket风格。它在这里特别令人震惊,因为它完全没有任何作用;如果您愿意,可以将其取出并使用let
(或local
或block
与内部定义。)
除此之外,eval同样是邪恶的,你在这里不需要它。功能是一流的;创建符号和函数之间的映射,然后只使用映射来获取要调用的相关函数。
(define (operator->procedure op)
(case op
[(+) +]
[(-) -]
[(*) *]
[(/) /]
[else (error 'operator->procedure "unknown operator ~v" op)]))
(define (solve expression)
(if (atom? expression)
expression
((operator->procedure (second expression))
(solve (first expression))
(solve (third expression)))))
为了更清楚,您可以使用Racket的模式匹配表单match
:
(define (solve expression)
(match expression
[(? atom) expression]
[(list a op b)
((operator->procedure op) (solve a) (solve b))]))