, public/private, defaults
defn
= public defn-
= private Perhaps I have bad Clojure coding style -- but I find that most functions I write in Clojure are small helper functions that I do not want to expose.
Is there some configuration option, where:
defn
= private by default, defn+
? Thanks!
No. There is not.
An alternative approach which might or might not work for you is to declare a foo.bar.internal
namespace containing all the private helpers which is used by your foo.bar
namespace. This has advantages over private function declarations when you want to use private functions in macro expansions.
As stated by @kotarak, there is no way (as far as I know) to do that, nor is it desirable.
Here is why I dislike defn-
:
I found out that when using various Clojure libraries I sometimes need to slightly modify one function to better suit my particular needs. It is often something quite small, and that makes sense only in my particular case. Often this is just a char or two.
But when this function reuses internal private functions, it makes it harder to modify. I have to copy-paste all those private functions.
I understand that this is a way for the programmer to say that "this might change without notice".
Regardless, I would like the opposite convention :
defn
, which makes everything public defn+
(that doesn't exist yet) to specify to the programmer which functions are part of the public API that he is supposed to use. defn+
should be no different from defn
otherwise. Also please note that it is possible to access private functions anyway :
;; in namespace user
user> (defn- secret []
"TOP SECRET")
;; from another namespace
(#'user/secret) ;;=> "TOP SECRET"
The beauty of Clojure being a Lisp, is that you can build and adapt the language to suit your needs. I highly recommend you read On Lisp, by Paul Graham. He now gives his book away for free.
Regarding your suggestion of defn+ vs defn vs defn-. This sound to me like a good case for writing your own Macro. defn
is a function and defn-
is a macro. You can simply redefine them as you wish, or wrap them in your own.
Here follows a suggestion to implementation, based mainly on Clojure's own implementation - including a simple utility, and a test.
(defmacro defn+
"same as Clojure's defn, yielding public def"
[name & decls]
(list* `defn (with-meta name (assoc (meta name) :public true)) decls))
(defmacro defn
"same as Clojure's defn-, yielding non-public def"
[name & decls]
(list* `defn (with-meta name (assoc (meta name) :private true)) decls))
(defn mac1
"same as `macroexpand-1`"
[form]
(. clojure.lang.Compiler (macroexpand1 form)))
(let [ ex1 (mac1 '(defn f1 [] (println "Hello me.")))
ex2 (mac1 '(defn+ f2 [] (println "Hello World!"))) ]
(defn f1 [] (println "Hello me."))
(defn+ f2 [] (println "Hello World!"))
(prn ex1) (prn (meta #'f1)) (f1)
(prn ex2) (prn (meta #'f2)) (f2) )
链接地址: http://www.djcxy.com/p/82568.html
上一篇: 在Clojure中定义的目的
下一篇: ,公/私,默认