【发布时间】:2014-04-12 15:27:04
【问题描述】:
我想知道如何包装一个函数(或函数定义),使它看起来似乎不知道传递给它的参数是可变的还是不可变的——但如果给定的任何参数是可变的,它应该取消引用每次调用时的参数,获取当前值。
我可以编写一个函数,该函数要求每个参数都是可变存储,然后在每次调用时取消引用。但是在 Clojure 中取消引用可变存储会导致性能下降(非常非常小,我知道!)。在我的特定用例中,这些实际上是瓶颈操作,小到足以解除引用以产生影响,并且重复了数十万到数百万次(更多关于我的用例,但现在让我们假设这很重要)。所以我不想在不需要可变数据的情况下使用可变数据。如果从外部看,代码似乎并不关心初始参数是可变的还是不可变的,那就太好了。 假设为简单起见,函数如下:
(defn foo [a b]
(fn [x] (* a b x)))
(def instance (foo 3 4))
(instance 5) ; <- 60
(instance 8) ; <- 96
我想要一个足够聪明的foo:
(def a (agent 3))
(def b (agent 4))
(foo a b) ; <- (fn [x] (* (deref a) (deref b) x))
(foo a 4) ; <- (fn [x] (* (deref a) 4 x))
(foo 3 4) ; <- (fn [x] (* 3 4 x))
但是,我第一次尝试使用引用和取消引用(自然,对吗?这是宏使用的!),它给了我一个关于在代码中嵌入对象的严重错误(一个非常相似的问题,不同的用例,是discussed here)。我的下一次尝试给了我一个奇怪的(和大量的)slowdown in runtimes。
有谁知道这样做的好方法吗?
背景
我正在研究一些机器学习算法。在典型的场景中,用户会用一组参数初始化一个算法,然后在一组数据上运行它。但有时用户/用户定义的代码可能希望在算法运行时修改参数,或者基于时间(例如,simulated annealing),或者基于在观察算法的持续性能时确定的其他一些标准。我的算法是并行的,每个线程都需要看到变化。在我更改参数时重新启动算法会破坏目的。
【问题讨论】:
标签: clojure