Clojure,defn,defn-,公共/私有,默认值 defn=公共 defn-=private
也许我的Clojure编码风格不好——但我发现我在Clojure中编写的大多数函数都是我不想公开的小助手函数 是否有一些配置选项,其中:Clojure,defn,defn-,公共/私有,默认值 defn=公共 defn-=private,clojure,Clojure,也许我的Clojure编码风格不好——但我发现我在Clojure中编写的大多数函数都是我不想公开的小助手函数 是否有一些配置选项,其中: defn=默认情况下为私有 为了公开一些东西,我必须执行defn+ 谢谢 没有。没有 另一种可能适用于您,也可能不适用于您的方法是声明一个foo.bar.internal名称空间,其中包含foo.bar名称空间使用的所有私人助手。当您希望在宏扩展中使用私有函数时,这比私有函数声明有优势。如果“帮助函数”很可能只使用一次,您可以选择将它们作为较大函数的局部函
=默认情况下为私有defn
- 为了公开一些东西,我必须执行
defn+
foo.bar.internal
名称空间,其中包含foo.bar
名称空间使用的所有私人助手。当您希望在宏扩展中使用私有函数时,这比私有函数声明有优势。如果“帮助函数”很可能只使用一次,您可以选择将它们作为较大函数的局部函数,或者将它们作为匿名函数编写。请参见letfn
:和
我自己几乎从不使用
letfn
。正如@kotarak所说的,没有办法(据我所知)做到这一点,也不可取
这就是为什么我不喜欢defn-
:
我发现在使用各种Clojure库时,有时需要稍微修改一个函数以更好地满足我的特殊需要。
这通常是很小的事情,只有在我的特殊情况下才有意义。通常这只是一两个字符
但是,当这个函数重用内部私有函数时,它就更难修改了。我必须复制粘贴所有这些私有函数
我理解这是程序员说“这可能会在不通知的情况下更改”的一种方式
不管怎样,我想要相反的惯例:
- 始终使用
,这会使所有内容公开defn
- 使用
(还不存在)向程序员指定哪些函数是他应该使用的公共API的一部分defn+
应与defn+
相同,否则defn
Clojure作为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) )
不只是没有,它会让其他Clojurian人看这些代码时的思维混乱。即使它是可行的,我也会阻止它。我认为这些助手函数的大小无关紧要。如果它们被多次使用,那么它们真的应该被抽象为代码。我真的看不出有什么理由让它们成为本地/匿名的,除非它们在本地只使用一次。这是真的。我将修改答案。我曾尝试为我的助手使用
letfn
,但这使我的代码太乱。因此,在很短的一段时间后,我切换回defn-
。根据我使用Ruby的经验,Ruby允许不受限制地访问所有内容(只需使用#send for private方法)。结果是一团糟,经验不足的开发人员往往会通过做一些非常糟糕的事情来滥用这种“自由”。在编写了一个大的clojure代码库之后,我实际上为privatedefn-
案例找到了一些价值。我还没有完全尝试使用defn+
。如果我在修改别人的函数时出错,那是我的错。作为一名程序员,阻止我修改内部代码是一种侮辱。一切都应该公开。只要正确记录任何潜在的问题,就不需要私人文件。@Rebs哇,我有完全相反的观点。API应该保护用户不受其内部复杂性的影响。我可能受到我强大的面向对象背景的影响,但我真的不认为自由修改库的内部内容是一个好主意。曾经。@Dici有时您需要添加或修改其他人代码的内部。没有什么比找到一个需要扩展的类更糟糕的了,但是一切都得到了保护。作为一名程序员,你不可能想到所有可能的事情。将内部标记为“请不要碰”Python风格(\u var,\u method),但不要阻止我。设置的障碍越多,我的代码就必须越详细,才能克服这些障碍。编写具有层次而非屏障的API。增加价值,不要删除它。你真的不信任其他程序员吗?为什么要编写偏执狂库代码?
(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) )