导致第二个命名空间选择要加载的第三个命名空间

时间:2016-09-21 05:32:30

标签: matrix clojure dependencies

命名空间foo定义了一组根据算术运算符定义的函数。这些是标量算术运算符或矩阵算术运算符,具体取决于foo requirescalar-arithmetic还是matrix-arithmetic命名空间。 (foo.cljc中没有很多代码,但复制它就足够了。我知道core.matrix - 这是matrix-arithmetic定义的 - 可以处理raw标量,但在这种情况下,它比Clojure的内置算法慢很多,foo函数的速度对我的应用程序来说很重要。)

命名空间bar-s需要标量算术。命名空间bar-m需要矩阵运算。两个名称空间都需要在名称空间foo中定义的函数,但bar-s需要在标量版本中使用这些函数,而bar-m需要它们的矩阵形式。我们可以假设我只会在同一会话中加载bar-mbar-s中的一个。 (如果我不需要这个假设,那很好,但我可以忍受它。)

我正在尝试找出bar-sbar-m指定要加载的foo版本的最佳方式,即如何强制foo加载scalar-arithmetic命名空间,或加载matrix-arithmetic命名空间。 (或者:如果有一种更好,非常不同的方式来完成我想要做的事情,我很乐意重新考虑它。)

目前,这就是我正在做的事情。它似乎工作:我有另一个命名空间config,我在其中定义一个包含布尔值的原子。在bar-sbar-m中,我将此原子重置为一个值,该值将选择我想要的算术实现,然后require foofoo检查原子,然后require scalar-arithmeticmatrix-arithmetic,具体取决于原子。

这可能是做我想要的最好的方法,但这是一种奇怪的方法,我想知道是否有更好的方法。我如果我只是在会话开始时重置原子,我就不会有问题,但是我担心会有一些我不知道的问题。

这是设置的玩具版本:

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

0 个答案:

没有答案