1

Clojure 中是否有模拟 Mathemaica 函数播种/收割的函数?播种和收割的主要用法涉及收集在评估过程中生成的表达式。

例子)

Mathematica 中的输入: Reap[Sow[w = 2];w+=Sow[w^3];w=Sqrt[w + w^3]]

输出:{Sqrt[1010], {{2, 8}}}

给出中间结果 2 和 8。

4

1 回答 1

10

像 clojure 这样的谐音语言的美妙之处在于,您可以根据需要定义新的语法。

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

为简单起见,我使用 jvm interop 进行数学运算,而不是 clojure.numeric-tower 所以我们得到浮点而不是精确输出:

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

编辑:现在我看到了 sow 的文档,它还支持标记和按标记选择

因为这是 clojure 通过键抓取东西是微不足道的,所以我将只展示一个制作标签的变体:

(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)}]
于 2013-11-14T00:27:09.370 回答