Могу ли я ссылаться на другое пространство имен и публиковать его функции для текущих ns?

Я думал, что use сделает это, но похоже, что отображение, созданное в текущем пространстве имен, не является общедоступным. Вот пример того, что я хотел бы достичь:

(ns my-ns
  (:use [another-ns :only (another-fct)]))

(defn my-fct
  []
  (another-fct 123)) ; this works fine

Тогда у меня есть другое пространство имен, подобное этому:

(ns my-ns-2
   (:require [my-ns :as my]))

(defn my-fct-2
  []
  (my/another-fct 456)) ; this doesn't work

Я хотел бы сделать это, потому что another-ns - это библиотека для доступа к базе данных. Я хотел бы выделить все вызовы в эту библиотеку в одном пространстве имен (my-ns), таким образом все зависимые от БД функции будут изолированы в одном пространстве имен, и при необходимости будет проще переключиться на другой БД.

Некоторые из функций этой библиотеки прекрасно подходят для меня, но я хотел бы увеличить других. Пусть говорят, что функции чтения прекрасны, но я хотел бы увеличить функции записи с некоторой проверкой.

Единственный способ, который я вижу до сих пор, - вручную переписать все сопоставление в my-ns даже для функций, которые я не увеличиваю.

Ответы

Ответ 1

Помогает ли это?

(defmacro pull [ns vlist]
  `(do [email protected](for [i vlist]
           `(def ~i ~(symbol (str ns "/" i))))))

Вот пример:

(ns my-ns)

(defmacro pull [ns vlist]
  `(do [email protected](for [i vlist]
           `(def ~i ~(symbol (str ns "/" i))))))

(pull clojure.string (reverse replace))

(defn my-reverse
  []
  (reverse "abc"))

(ns my-ns-2)

(defn my-fct-2 []
  (list (my-ns/my-reverse)
        (my-ns/reverse "abc")))

(my-fct-2)

Если вы хотите просто втянуть все, то:

(defmacro pullall [ns]
  `(do [email protected](for [i (map first (ns-publics ns))]
           `(def ~i ~(symbol (str ns "/" i))))))

(pullall clojure.string)

Ответ 2

Один из способов сделать это выборочно (явно указывая каждую функцию) - использовать что-то вроде Zach Tellman Библиотека Потемкина. Пример его использования находится в lamina.core пространстве имен, который служит точкой публичной точки для Lamina, импортируя ключевые публичные функции из всех других внутренние пространства имен.

Вы также можете использовать clojure.contrib.def/defalias:

(use 'clojure.contrib.def/defalias)
(defalias foo clojure.string/blank?)
(foo "")

Ответ 3

Чтобы вытащить все из пространства имен, которые могут иметь макросы, определенные внутри, используйте

(defmacro pullall [ns]
  `(do [email protected](for [[sym var] (ns-publics ns)]
           `(def ~sym ~var))))