Question

Are there functions in the Clojure, which emulate the Mathemaica functions sow/reap? The main usage of sow and reap involve collecting expressions that were generated in the course of evaluation.

Example)

input in Mathematica: Reap[Sow[w = 2];w+=Sow[w^3];w=Sqrt[w + w^3]]

output: {Sqrt[1010], {{2, 8}}}

Giving intermediate results 2 and 8.

Was it helpful?

Solution

The wonderful thing about a homoiconic language like clojure is that you can define new syntaxes as you need them.

(defmacro reap
  [& body]
  `(let [state# (atom [])
         ~'sow (fn sow [v#] (swap! state# conj v#) v#)]
     [(do ~@body) @state#]))

For simplicity's sake I used jvm interop for math, instead of clojure.numeric-tower so we get floating point rather than exact output:

user> (reap (let [w (sow 2)
                  w (+ w (sow (Math/pow w 3)))
                  w (Math/sqrt (+ w (Math/pow w 3)))]
              w))

[31.78049716414141 [2 8.0]]
user> (= 31.78049716414141 (Math/sqrt 1010))
true

Edit: now that I see the docs for sow, it also has support for tagging and selecting by tag

since this is clojure grabbing things by key is trivial, so I will just show a variant that makes the tags:

(defmacro reap
  [& body]
  `(let [state# (atom {})
         ~'sew (fn sew [& [v# tag#]]
                 (swap! state# #(update-in % [tag#] conj v#)) v#)]
     [(do ~@body) @state#]))

user> (reap (let [w (sew 2 :a)
            w (+ w (sew (Math/pow w 3)))
            w (Math/sqrt (+ w (Math/pow w 3)))]
        w))

[31.78049716414141 {nil (8.0), :a (2)}]
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top