我正在尝试生成一个函数,该函数将表达式"树"作为其参数,并返回具有相关计算值的树代替运算符.
树的外观示例如下:
(* (+ 10 (* 4 9)) (- 6 10))
Run Code Online (Sandbox Code Playgroud)
并且函数应该返回:
(-184 (46 10 (36 4 9)) (-4 6 10))
Run Code Online (Sandbox Code Playgroud)
如果有人能为我提供一两个解决方案,并解释他们如何工作以指出我正确的方向,那将是伟大的.
(def a '(* (+ 5 (* 3 7)) (- 6 8)) )
(defn evaltree [tree] (cons (eval (first (rest tree))) tree))
Run Code Online (Sandbox Code Playgroud)
就是我到目前为止所有的一切.它会破坏列表的第一部分,但不会递归到列表的其余部分并且不替换运算符,它只会将值添加到开头.
当您想要更新任意嵌套数据结构时,clojure.walk 中的函数非常有用,以下解决方案似乎适用于这种情况。
(require '[clojure.walk :as w])
(defn op->answer [expr]
(if (list? expr)
(cons (eval expr) (rest expr))
expr))
(w/prewalk op->answer '(* (+ 10 (* 4 9)) (- 6 10)))
;;=> (-184 (46 10 (36 4 9)) (-4 6 10))
Run Code Online (Sandbox Code Playgroud)
clojore.walk/prewalk 对表达式树进行前序遍历,并用函数的返回值替换每个节点。您可以使用以下代码片段查看订单或调用。
(w/prewalk #(do (println %) %) '(* (+ 10 (* 4 9)) (- 6 10)))
;; => prints the following
(* (+ 10 (* 4 9)) (- 6 10))
*
(+ 10 (* 4 9))
+
10
(* 4 9)
*
4
9
(- 6 10)
-
6
10
Run Code Online (Sandbox Code Playgroud)