在构建公共消费的clojure库时,如何组织函数名称?

bmi*_*are 9 namespaces clojure

假设我想构建一个包含多个组件的大型clojure库.作为开发人员,我想将许多组件保存在不同的命名空间中,因为许多辅助函数可以具有相似的名称.我并不一定想把事情变得私密,因为在极端情况下它们可能具有实用性,并且私人背后的解决方案并不好.(换句话说,我想建议代码使用,而不是完全阻止使用.)

但是,我希望库的用户在命名空间中操作,并在每个子库中使用许多函数子集的并集.什么是惯用或最好的方法呢?我想到的一个解决方案是编写一个生成的宏:需要并通过定义一个给定的var名称列表来创建一个新的var映射(参见第一个代码示例).是否存在使用此方法的权衡,例如扩展类型会发生什么?有没有更好的方法(或内置)?

宏示例(src/mylib/public.clj):

 (ns mylib.public
    (:require [mylib.a :as a])
    (:require [mylib.b :as b]))

 (transfer-to-ns [+ a/+
                  - b/-
                  cat b/cat
                  mapper a/mapper])
Run Code Online (Sandbox Code Playgroud)

再次,澄清一下,最终目标是在mylib用户创建的其他项目中创建一些文件,以便能够创建类似(src/someproject/core.clj)的内容:

 (ns someproject.core
     (:require [mylib.public :as mylib]))

 (mylib/mapper 'foo 'bar)
Run Code Online (Sandbox Code Playgroud)

@Jeremy Wall,请注意您提出的解决方案并未满足我的需求.让我们假设存在以下代码.

MYLIB/a.clj:

 (ns mylib.a)

 (defn fa [] :a)
Run Code Online (Sandbox Code Playgroud)

MYLIB/b.clj:

 (ns mylib.b)

 (defn fb [] :b)
Run Code Online (Sandbox Code Playgroud)

MYLIB/public.clj:

 (ns mylib.public
     (:use [mylib.a :only [fa]])
     (:use [mylib.b :only [fb]]))
Run Code Online (Sandbox Code Playgroud)

somerandomproject/core.clj :(假设类路径设置正确)

 (ns somerandomproject.core
     (:require [mylib.public :as p])

 ;; somerandomproject.core=> (p/fa)
 ;; CompilerException java.lang.RuntimeException: No such var: p/fa, compiling:     (NO_SOURCE_PATH:3) 
 ;; somerandomproject.core=> (mylib.a/fa)
 ;; :a
Run Code Online (Sandbox Code Playgroud)

如果您注意到,mylib/public.clj中的"using"函数不允许public.clj将这些变量提供给用户文件somerandomproject/core.clj.

Ale*_*ler 9

您可能会发现有趣的是看看像CompojureLamina这样的图书馆如何组织其"公共"API.

叶片有一个像"公共"的命名空间lamina.api投放到别名(使用扎克进口-FN从他的波将金号库)从像"内部"的命名空间功能lamina.core.pipeline.通过一些文档,这可以清楚地描述面向公众的ns与可能发生变化的内部结构.我发现这个策略的主要缺点是import-fn使得从使用函数到其实现中走路(在emacs中)变得更加困难.或者要知道使用clojure.repl/source的函数.

像Compojure这样的库使用私有变量来分离函数的公共/私有部分(例如,参见compojure.core)."私有"功能的主要缺点是您以后可能会发现要暴露它们或者它使测试更复杂.如果您控制代码库,我发现私有方面并不重要.通过使用#'foo.core/my-function来引用私有函数,可以轻松解决测试问题.

一般来说,我倾向于使用更像Compojure的风格而不是Lamina的东西,但听起来你更喜欢像Lamina这样的东西.