defn
=公开defn-
=私人
也许我的 Clojure 编码风格不好——但我发现我在 Clojure 中编写的大多数函数都是我不想公开的小型辅助函数。
是否有一些配置选项,其中:
defn
= 默认情况下是私有的,- 为了公开某些事情,我必须做
defn+
什么?
谢谢!
defn
=公开defn-
=私人也许我的 Clojure 编码风格不好——但我发现我在 Clojure 中编写的大多数函数都是我不想公开的小型辅助函数。
是否有一些配置选项,其中:
defn
= 默认情况下是私有的,defn+
什么?谢谢!
不,那里没有。
另一种可能对您有用或可能不起作用的方法是声明一个foo.bar.internal
命名空间,其中包含您的命名空间使用的所有私有助手foo.bar
。当您想在宏扩展中使用私有函数时,这比私有函数声明具有优势。
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) )
如果“辅助函数”很可能只使用一次,您可以选择将它们设为较大函数的本地函数,或者将它们编写为匿名函数。请参阅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"