2012-04-23 52 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