Eval不在Racket中工作

时间:2016-08-01 03:31:47

标签: scheme racket

我正在使用从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

问题出在哪里?如何解决?感谢。

1 个答案:

答案 0 :(得分:3)

您是否从以前的问题的答案中学到了什么?不要使用set!,这不是好的Scheme / Racket风格。它在这里特别令人震惊,因为它完全没有任何作用;如果您愿意,可以将其取出并使用let(或localblock与内部定义。)

除此之外,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))]))