定义用于在Lisp中评估中缀表达式的函数

pra*_*mus 2 lisp common-lisp infix-notation

我在Lisp中不是很好,我需要做一个允许评估中缀表达式的函数.例如:(+ 2 3) -> (infixFunc 2 + 3).我尝试了一些变种,但都没有成功.

其中之一:

(defun calcPrefInf (a b c)
  (funcall b a c))
Run Code Online (Sandbox Code Playgroud)

Mar*_*ark 12

好吧,让我们这样做只是为了好玩.首先,让我们定义操作的优先顺序,因为当处理中缀表示法时,它是必要的.

(defvar *infix-precedence* '(* / - +))
Run Code Online (Sandbox Code Playgroud)

很好.现在假设我们有一个函数to-prefix将中缀符号转换为抛光前缀表示法,因此Lisp可以处理它并计算出一些事情.

to-prefix为了美观原因,让我们编写简单的reader-macro来包装我们的调用:

(set-dispatch-macro-character
 #\# #\i (lambda (stream subchar arg)
           (declare (ignore sub-char arg))
           (car (reduce #'to-prefix
                        *infix-precedence*
                        :initial-value (read stream t nil t)))))
Run Code Online (Sandbox Code Playgroud)

现在,让我们编写一个非常简单的函数to-prefix,它将在给定符号的给定列表中将中缀表示法转换为前缀表示法.

(defun to-prefix (lst symb)
  (let ((pos (position symb lst)))
    (if pos
        (let ((e (subseq lst (1- pos) (+ pos 2))))
          (to-prefix (rsubseq `((,(cadr e) ,(car e) ,(caddr e)))
                              e
                              lst)
                     symb))
        lst)))
Run Code Online (Sandbox Code Playgroud)

好好.功能rsubseq可以定义为:

(defun rsubseq (new old where &key key (test #'eql))
  (labels ((r-list (rest)
             (let ((it (search old rest :key key :test test)))
               (if it
                   (append (remove-if (constantly t)
                                      rest
                                      :start it)
                           new
                           (r-list (nthcdr (+ it (length old))
                                           rest)))
                   rest))))
           (r-list   where)))
Run Code Online (Sandbox Code Playgroud)

现在是时候尝试了!

CL-USER> #i(2 + 3 * 5)
17
CL-USER> #i(15 * 3 / 5 + 10)
19
CL-USER> #i(2 * 4 + 7 / 3)
31/3
CL-USER> #i(#i(15 + 2) * #i(1 + 1))
34
Run Code Online (Sandbox Code Playgroud)

等等