I'm facing a problem in how to architecture a particular piece of my software.
Lets say, I have a function called make-temp-dir
(and many others) that does
some dark magic depending on the current OS. I want to be able to put the
implementations of these methods for each OS in a separate namespace.
Firstly, I believe protocols (if possible) or multimethods are the solution to this. However, I've never seen an example of using these with implementations spanning over multiple namespaces. And I'm not able to figure how this'd work out.
Second, if I use protocols for this, I'll have to call the methods something like
(make-temp-dir current-os arg-1 arg-2)
Somehow, passing the os as the first argument all the time doesn't look too good
to me. For semantic sake, I'd wish the make-temp-dir
take intelligent
decisions depending on the OS. Sure I can use some macros and do something like
(doto current-os
(make-temp-dir arg-1 arg2))
but that feels wrong.
How should this be done? Or am I going the wrong way? Any help appreciated.
Edit: Okay, thanks a ton to @kotarak, I managed to get something working. For anyone that stumbles on this, https://gist.github.com/2477120. Its working fine, I think I'll go with that. Thanks everyone.
(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]
(...))
In your startup code you have to initialize current-os
with alter-var-root
before using any of the utility functions.
(let [os (find-os)]
(alter-var-root #'current-os (constantly os))
(require (case os
:mac-os-x 'your.utils.mac
:windows 'your.utils.win)))
Hope that gets you started.
I can't say for certain, but it sounds like you may end up reinventing a wheel that Java provides you with. Try out https://github.com/Raynes/fs for a convenient wrapper on some of what Java provides beyond the basic tools in clojure.java.io ( http://clojuredocs.org/clojure_core/clojure.java.io ).
You may find also https://github.com/drakerlabs/milieu useful if your question extend beyond OS-specific branching to environment-specific configuration values. I wrote this code as part of our proprietary projects here at Draker, and we've just recently released it as free software. We haven't yet officially announced it to the community, but it is in Clojars and ready for use. Feedback is appreciated! The concept that drove its creation was environments in the sense of dev/test/staging/production etc, but I see no reason why it couldn't be used to configure variables for different OS environments as well.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With