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)
等等