2012-04-23 49 views
6

我在如何架构我的软件的特定部分时遇到问题。 可以说,我有一个叫做make-temp-dir(和其他很多)的功能,它根据当前的操作系统做了一些暗黑魔法。我希望能够将每个操作系统的这些方法的 实现放在单独的命名空间中。clojure中的协议/多方法的环境相关调度

首先,我认为协议(如果可能的话)或multimethods是解决方案 这。不过,我从来没有见过一个跨越多个命名空间的实现 的例子。而且我无法弄清楚这是怎么工作的 。

其次,如果我使用的协议对于这一点,我会以某种方式调用的方法的东西 像

(make-temp-dir current-os arg-1 arg-2) 

,通过操作系统,因为所有的时间看起来并不太好 的第一个参数对我来说。出于语义的原因,我希望make-temp-dir根据操作系统采取智能的 决定。当然,我可以使用一些宏和做类似

(doto current-os 
    (make-temp-dir arg-1 arg2)) 

但觉得不妥。

应该怎么做?或者我走错了路?任何帮助赞赏。

编辑:好的,感谢吨@kotarak,我设法让一些工作。对于任何绊倒在此的人,https://gist.github.com/2477120。它的工作正常,我想我会去那。感谢大家。

回答

7
(ns your.utils) 

(def current-os) 

(defmulti make-temp-dir 
    (fn [& _] current-os)) 

(ns your.utils.mac) 

(defmethod make-temp-dir :mac-os-x 
    [a b] 
    (...)) 

(ns your.utils.win) 

(defmethod make-temp-dir :windows 
    [a b] 
    (...)) 

在你的启动代码你使用任何的效用函数之前初始化current-osalter-var-root

(let [os (find-os)] 
    (alter-var-root #'current-os (constantly os)) 
    (require (case os 
      :mac-os-x 'your.utils.mac 
      :windows 'your.utils.win))) 

希望能让你开始。

+0

那么,第二段代码需要在'your.utils'命名空间下吗?此外,什么是'#''读者宏 - 对不起,不知道如何谷歌,或者;) – 2012-04-23 16:20:51

+0

'#''被称为* var引用*。您可以在https://groups.google.com/forum/?fromgroups#!topic/clojure/jDBAJD4nWqs找到var引号的说明。 – user100464 2012-04-23 16:33:20

+0

@ kotarak,好的,真棒解决方案。花了我很长时间来消化它,但我想我明白发生了什么事情。尽管如此,我仍然想在我的第一条评论中提供一些意见 – 2012-04-23 16:40:06

1

我不能肯定地说,但它听起来像你最终可能重新发明一个Java为你提供的轮子。尝试使用https://github.com/Raynes/fs以获得Java提供的超越clojure.java.io(http://clojuredocs.org/clojure_core/clojure.java.io)中的基本工具的一些便捷包装。

如果您的问题超出特定于操作系统的分支到环境特定的配置值,您可能还会发现https://github.com/drakerlabs/milieu有用。我将这些代码作为我们在Draker的专有项目的一部分编写,最近我们将它作为免费软件发布。我们还没有正式向社区宣布它,但它已在Clojars中并可供使用。感谢您的反馈!驱动其创建的概念是在开发/测试/分期/生产等意义上的环境,但我没有理由不能为不同的操作系统环境配置变量。

+1

谢谢你的联系rplevy。我认为fs包会派上用场:) – 2012-04-24 06:52:24