Matrix 使第二个命名空间选择要加载的第三个命名空间
命名空间Matrix 使第二个命名空间选择要加载的第三个命名空间,matrix,clojure,dependencies,Matrix,Clojure,Dependencies,命名空间foo定义了一组用算术运算符定义的函数。这些是标量算术运算符或矩阵算术运算符,具体取决于foo是否需要标量算术或矩阵算术命名空间。(foo.cljc中没有太多的代码,但复制它就够傻的了。我知道core.matrix——这就是矩阵算术的定义——可以处理原始标量,但在这种情况下,它比Clojure的内置算术慢得多,foo函数的速度对我的ap很重要。)折叠。) 命名空间bar-s需要标量算法。名称空间bar-m需要矩阵运算。两个名称空间都需要名称空间foo中定义的函数,但是bar-s需要标量版
foo
定义了一组用算术运算符定义的函数。这些是标量算术运算符或矩阵算术运算符,具体取决于foo
是否需要标量算术
或矩阵算术
命名空间。(foo.cljc中没有太多的代码,但复制它就够傻的了。我知道core.matrix——这就是矩阵算术
的定义——可以处理原始标量,但在这种情况下,它比Clojure的内置算术慢得多,foo
函数的速度对我的ap很重要。)折叠。)
命名空间bar-s
需要标量算法。名称空间bar-m
需要矩阵运算。两个名称空间都需要名称空间foo
中定义的函数,但是bar-s
需要标量版本的函数,而bar-m
需要矩阵形式的函数。我们可以假设,在同一会话中,我将只加载bar-m
和bar-s
中的一个。(如果我不需要这个假设,那很好,但我可以接受。)
我试图找出bar-s
或bar-m
指定加载哪个版本的foo
——也就是说,如何强制foo
加载标量算术
命名空间,或加载矩阵算术
命名空间。(或者:如果有更好的、完全不同的方法来完成我想做的事情,我很乐意重新思考。)
目前,这就是我正在做的。这似乎是可行的:我有另一个名称空间,config
,在其中我定义了一个包含布尔值的原子。在bar-s
或bar-m
中,我将这个原子重置为一个值,该值将选择我想要的算术实现,然后我需要foo
foo
检查原子,然后根据原子要求标量算术
或矩阵算术
这可能是我想要的最好的方法,但这是一种奇怪的方法,我想知道是否有更好的方法。我认为,如果我只在会话开始时重置atom,我不会有问题,但我担心会有一些我不知道的问题
以下是设置的玩具版本:
(ns scalar-arithmetic)
(defmacro m* [x y] `(* ~x ~y))
;; Using (def m* *) instead would lose Clojure's special optimizations for *
(defmacro inv [x] `(/ 1.0 ~x))
;;;;;;;;;;;;;;;;;
(ns matrix-arithmetic
(:require [clojure.core.matrix :as mx]))
(def m* mx/mmul) ; matrix multiplication
(def inv mx/inverse) ; matrix inverse
;;;;;;;;;;;;;;;;;
(ns foo
(require [config]))
(if @config/use-core-matrix
(require '[matrix-arithmetic :refer [m* inv]])
(require '[scalar-arithmetic :refer [m* inv]]))
(defn fooey [r s] (m* r (inv s))) ; could have either scalar or matrix meaning
;; The next two namespaces would not both be loaded in the same session.
;;;;;;;;;;;;;;;;;
(ns bar-s
(require [config]))
(reset! config/use-core-matrix true)
(require '[foo])
;;;;;;;;;;;;;;;;;
(ns bar-m
(require [foo])) ;; default value of use-core-matrix is false, so this is enough.
可能会有帮助。这似乎是一个规范的多方法用例。为什么不使用多种方法呢?@JonahB,你可能是对的。不确定。老实说,我没有想过多种方法,但我应该想到。那会像普通的Clojure+
,-
,*
和/
一样快吗?目前,我将标量运算符定义为宏,这样与原始数学运算符相比,我就不会损失速度。(这是针对性能关键的代码)我可以运行基准测试,但考虑到我对多方法的理解,我认为它们应该更慢。我相信,我已经确定协议会更慢。@nrako,谢谢你给我这个答案的指针。似乎这应该是相关的,但我还不知道如何使用这个答案中的想法。我当然不想在每个操作符调用上都加载名称空间。对于性能敏感的操作,使用协议的基于类型的分派应该是最快的。所有jvm调度都必须是类型化的,协议提供提示并允许普通函数无法实现的缓存。可能值得分享反馈基准。对于上面的用例,请参见core.matrix及其实现。