19 clojure
defn =公众defn- =私人也许我的Clojure编码风格很糟糕 - 但我发现我在Clojure中编写的大多数函数都是我不希望公开的小辅助函数.
是否有一些配置选项,其中:
defn =默认为私有,defn+?谢谢!
kot*_*rak 17
不,那里没有.
另一种可能或可能不适合您的方法是声明一个foo.bar.internal包含命名空间使用的所有私有帮助程序的foo.bar命名空间.当您想在宏扩展中使用私有函数时,这优于私有函数声明.
如果“辅助函数”很可能被使用一次,您可以选择将它们设为更大函数的局部变量,或者将它们编写为匿名函数。请参阅letfn:http : //clojuredocs.org/clojure_core/clojure.core/letfn和http://clojuredocs.org/clojure_core/clojure.core/fn。
我几乎从不使用letfn自己。
正如@kotarak所说,没有办法(据我所知)这样做,也不可取.
这就是我不喜欢的原因defn-:
我发现当使用各种Clojure库时,我有时需要稍微修改一个函数以更好地满足我的特定需求.它通常很小,只有在我的特定情况下才有意义.通常这只是一两个字符.
但是当这个函数重用内部私有函数时,它会使修改变得更加困难.我必须复制粘贴所有这些私有函数.
我知道这是程序员说"这可能会在没有通知的情况下改变"的一种方式.
无论如何,我想要相反的惯例:
defn,这使一切都公开defn+(尚不存在)指定程序员哪些函数是他应该使用的公共API的一部分.defn+应该与defn其他方面没有区别.另请注意,无论如何都可以访问私人功能:
;; in namespace user
user> (defn- secret []
"TOP SECRET")
;; from another namespace
(#'user/secret) ;;=> "TOP SECRET"
Run Code Online (Sandbox Code Playgroud)
Clojure作为Lisp的美妙之处在于,您可以构建和调整语言以满足您的需求.我强烈建议你阅读Paul Graham的On Lisp.他现在免费赠送他的书.
关于你对defn + vs defn vs defn-的建议.这听起来像是写一个自己宏的好例子. defn是一个函数,defn-是一个宏.您可以根据需要重新定义它们,或者将它们包装在您自己的中.
以下是对实现的建议,主要基于Clojure自己的实现 - 包括一个简单的实用程序和一个测试.
(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) )
Run Code Online (Sandbox Code Playgroud)