Skip to content

Instantly share code, notes, and snippets.

(walk/postwalk
#(do (print (str % " ")) %)
[:add 1 [:mul "x" 2]])
:add 1 :mul x 2 [:mul "x" 2] [:add 1 [:mul "x" 2]]
(defn print-expr [expr]
(walk/postwalk
(fn algebra [e]
(cond
(cst? e) (str e)
(sym? e) e
(add? e) (str "(+ " (string/join " " (rest e)) ")")
(mul? e) (str "(* " (string/join " " (rest e)) ")")
:else e))
expr))
(def expr
(add
(cst 1) (cst 2)
(mul (cst 0) (sym "x") (sym "y"))
(mul (cst 1) (sym "y") (cst 2))
(add (cst 0) (sym "x"))))
(print-expr expr)
=> "(+ 1 2 (* 0 x y) (* 1 y 2) (+ 0 y))"
(defn evaluate [env e]
(walk/postwalk
(fn [e]
(cond
(sym? e) (get env e)
(add? e) (reduce + (rest e))
(mul? e) (reduce * (rest e))
:else e))
e))
(defn dependencies [e]
(walk/postwalk
(fn [e]
(cond
(cst? e) #{}
(sym? e) #{e}
(op? e) (apply set/union (rands e))
:else e))
e))
(defn optimize-add [e]
(if (add? e)
(optimize-op e + 0)
e))
(defn optimize-mul [e]
(if (mul? e)
(if (some #{(cst 0)} e)
(cst 0)
(optimize-op e * 1))
(defn- make-op
[rator rands]
(if (< 1 (count rands))
(into [rator] rands)
(first rands)))
(defn- optimize-op
[[rator & rands] binary-op neutral]
(let [{csts true vars false} (group-by cst? rands)
sum-cst (reduce binary-op neutral csts)]
(defn optimize [e]
(walk/postwalk
(comp optimize-mul optimize-add)
e))
(defn replace-var
[env x]
(if (string? x) (get env x x) x))
(defn partial-eval
[env e]
(walk/postwalk
(comp optimize-mul optimize-add #(replace-var env %))
e))
(ns arithmetic
(:require
[clojure.string :as string]
[clojure.set :as set]
[clojure.walk :as walk]
))