I feel awkward writing mathematical functions as s-exps
Clojure's thread-first macro eases the pain a bit..
..but it's still pretty loaded with parens, and not very clear.
Edit: Here's the original gist.
(defn quadratic-1 [a b c]
(let [d (* 4 a c),
D (Math/sqrt (- (* b b) d)),
t (* 2 a), -b (- b)]
[(/ (+ -b D) t)
(/ (- -b D) t)]))
Clojure's thread-first macro eases the pain a bit..
(defn quadratic-2 [a b c]
(let [d (* 4 a c),
D (-> (* b b) (- d) Math/sqrt),
t (* 2 a), -b (- b)]
[(-> -b (+ D) (/ t))
(-> -b (- D) (/ t))]))
..but it's still pretty loaded with parens, and not very clear.
We need a math DSL that looks infixy and uses fewer parens.
Luckily, we can hack one for ourselves in no time.
~*~
Step 1- Thread mathematical expressions
Step 2- Allow temporary bindings(defmacro math-> "(math-> 1 + 5 * 2 / 3) ;=> (-> 1 (+ 5) (* 2) (/ 3)) ;=> 4" [exp & f-x-pairs] (if (even? (count f-x-pairs)) `(-> ~exp ~@(for [[f x] (partition 2 f-x-pairs)] (list f x))) (throw (Exception. "f-x-pairs should be even."))))
Step 3- Profit?(defmacro maya "(maya 1 + 5 :as six, six * 2 :as twelve, twelve / 3 * 2) ;=> 8" [& exprs] (let [[exp [_ ?as & next-exprs :as E]] (split-with #(not= :as %) exprs)] (if (empty? E) (cons `math-> exp) `(let [~?as (math-> ~@exp)] (maya ~@next-exprs)))))
(defn quadratic [a b c]
(maya 4 * a * c :as d,
b * b - d -> Math/sqrt :as D,
2 * a :as t, (- b) :as -b,
-b + D / t :as x1,
-b - D / t :as x2,
[x1 x2]))
~*~
Edit: Here's the original gist.
No comments:
Post a Comment