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.

(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

(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 2-**Allow temporary bindings

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

**Step 3-**Profit?

(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