常见的lisp和中缀包

时间:2018-05-06 18:30:19

标签: common-lisp eval infix-notation

有常见的lisp的中缀包(参见http://www.cs.cmu.edu/afs/cs/project/ai-repository/ai/lang/lisp/code/syntax/infix/infix.cl),它将中缀形式转换为前缀。

例如:

(string->prefix "1+2") ;; => (+ 1 2)

它还提供了读者宏#I,它可以评估中缀形式,例如,

#I(1+2) ;; => 3

但我不想使用这个阅读器宏。

我写了一个简单的函数,它使用cl-ppcre来替换带有数字的字符串,即

(prepare-form "1+x*x" "x" 3) ;; => "1+3*3"

最后,我有一个评估中缀形式的函数

(defun eval-infix (form &rest args)
  (eval (string->prefix (apply #'prepare-form form args))))

可以在不使用eval函数的情况下实现eval-infix函数吗? 我的最终目标是像这样调用eval-infix:

(eval-infix "1+x*x" "x" (+ 1 2))

1 个答案:

答案 0 :(得分:2)

我觉得你想要使用的是string->prefix。这将实习符号,以避免污染您自己的包,让我们定义一个。最后,您可以通过定义自己的eval来避免eval的安全问题。仍然存在一个问题,其中包含来自其他包的符号,这让我感到难过。还有一个问题是,中缀阅读器可以逃到可以进行任意评估的Lisp阅读器。这是解决方案部分的草图。我可能以错误的顺序得到了一些函数的参数。

(defpackage infix-vars)
(defun read-infix-string (s) (let ((*package* (find-package "INFIX-VARS"))) (string->prefix s)))
(defun substitute-var (expr v val)
   (let ((v (etypecase v (symbol v) (string (intern v (find-package "INFIX-VARS"))))))
    (subst expr v val)))
(defun eval-expr (e)
  (etypecase e
    (number e)
    (list
      (ecase (car e)
        (+ (apply #'+ (mapcar #'eval-expr (cdr e))))))))