Architecture clojure中协议/多方法的环境相关调度

Architecture clojure中协议/多方法的环境相关调度,architecture,clojure,Architecture,Clojure,我面临着一个问题,那就是如何构建我的软件的特定部分。 比如说,我有一个名为make temp dir(以及其他许多函数)的函数,它可以 一些黑魔法取决于当前的操作系统。我希望能够将 在单独的命名空间中为每个操作系统实现这些方法 首先,我相信协议(如果可能的话)或多方法是解决问题的方法 这然而,我从未见过将这些应用于实现的示例 跨越多个名称空间。我不知道这是怎么回事 出去 第二,如果我使用协议,我必须调用一些方法 像 不知何故,始终将操作系统作为第一个参数传递看起来并不太好 对我来说。出于语义方面

我面临着一个问题,那就是如何构建我的软件的特定部分。 比如说,我有一个名为
make temp dir
(以及其他许多函数)的函数,它可以 一些黑魔法取决于当前的操作系统。我希望能够将 在单独的命名空间中为每个操作系统实现这些方法

首先,我相信协议(如果可能的话)或多方法是解决问题的方法 这然而,我从未见过将这些应用于实现的示例 跨越多个名称空间。我不知道这是怎么回事 出去

第二,如果我使用协议,我必须调用一些方法 像

不知何故,始终将操作系统作为第一个参数传递看起来并不太好 对我来说。出于语义方面的考虑,我希望
使temp dir
变得智能化 决定取决于操作系统。当然,我可以使用一些宏并执行以下操作

(doto current-os
  (make-temp-dir arg-1 arg2))
但这感觉不对

如何做到这一点?还是我走错了路?谢谢你的帮助

编辑:好的,多亏@kotarak,我终于找到了工作。对于任何一个偶然发现这一点的人。它很好用,我想我会同意的。谢谢大家

(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]
  (...))
在启动代码中,在使用任何实用程序函数之前,必须使用alter 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)))

希望这能让您开始。

我不能肯定,但听起来您可能最终会重新发明Java为您提供的轮子。除了clojure.Java.io()中的基本工具之外,还可以尝试使用Java提供的一些方便的包装器


如果您的问题超出了特定于操作系统的分支到特定于环境的配置值,您可能会发现这一点也很有用。我写这段代码是作为我们在Draker的专有项目的一部分,我们最近刚刚将其作为自由软件发布。我们还没有正式向社区宣布,但它已经在Clojars中,可以使用了。感谢您的反馈!驱动其创建的概念是dev/test/staging/production等意义上的环境,但我认为没有理由不能使用它为不同的操作系统环境配置变量。

因此,第二段代码需要位于
您的.utils
命名空间下,对吗?还有,什么是
#'
阅读器宏-对不起,我也不知道如何用谷歌搜索它;)<代码>#'称为var引号。您可以在@kotarak找到var引号的描述,好的,非常好的解决方案。我花了这么长时间才消化,但我想我明白发生了什么。不过,我还是想听听我的第一条评论。@user100464,谢谢你的链接。正在签出。@kotarak,此解决方案是否要求所有实现名称空间都应位于同一文件中?有点违背了将它们放在不同名称空间的目的不?谢谢你的链接。我认为fs软件包会对我有用:)
(let [os (find-os)]
  (alter-var-root #'current-os (constantly os))
  (require (case os
             :mac-os-x 'your.utils.mac
             :windows  'your.utils.win)))