Załóżmy, że chcę zbudować dużą bibliotekę klauzurową z kilkoma komponentami. Jako programista chciałbym zachować wiele komponentów w osobnych przestrzeniach nazw, ponieważ wiele funkcji pomocniczych może mieć podobne nazwy. Niekoniecznie chcę robić rzeczy prywatne, ponieważ w ekstremalnych przypadkach mogą one być użyteczne, a utrudnienia prywatne nie są dobre. (Innymi słowy, chciałbym zasugerować użycie kodu, nie całkowicie uniemożliwić użycie).W jaki sposób organizujesz nazwy funkcji podczas budowania bibliotek clojure do użytku publicznego?
Chciałbym jednak, aby użytkownicy biblioteki działali w przestrzeni nazw z połączeniem podzbioru wielu funkcji w każda biblioteka podrzędna. Jaki jest idiomatyczny lub najlepszy sposób na zrobienie tego? Jednym z rozwiązań, które przychodzi mi do głowy, jest napisanie makra, które generuje: wymaga i tworzy nowe mapowanie var, definiując podaną listę nazw zmiennych (zobacz pierwszy przykład kodu). Czy istnieją kompromisy z tą metodą, takie jak to, co dzieje się z rozszerzaniem typów? Czy istnieje lepszy sposób (lub wbudowany)?
Makro przykład (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])
Ponownie, w celu wyjaśnienia, ostatecznym celem byłoby mieć jakiś plik w innych projektach tworzonych przez użytkowników myLib aby być w stanie dokonać coś jak (src/someproject/core.clj):
(ns someproject.core
(:require [mylib.public :as mylib]))
(mylib/mapper 'foo 'bar)
@Jeremy Wall, pamiętać, że proponowane rozwiązanie nie napełnić moje potrzeby. Załóżmy, że istnieje następujący kod.
myLib/a.clj:
(ns mylib.a)
(defn fa [] :a)
myLib/b.clj:
(ns mylib.b)
(defn fb [] :b)
myLib/public.clj:
(ns mylib.public
(:use [mylib.a :only [fa]])
(:use [mylib.b :only [fb]]))
somerandomproject/core.clj (Zakładamy, że ścieżki klasy są ustawione prawidłowo)
(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
Jeśli zauważysz, że funkcje "using" w pliku mylib/public.clj NIE zezwalają public.clj na DOSTARCZENIE tych zmiennych do pliku użytkownika somerandomproject/core.clj.
Dobra odpowiedź. To jest więcej, czym byłem szukałem. Próbowałem już stylu compojure.core, ale zostałem dotknięty ograniczeniami, o których mówisz, więc szukałem potencjalnych alternatyw. Zbadam blaszkę i sprawdzę, jak to działa, zanim zaakceptujesz. – bmillare
Cascalog jest zorganizowany wzdłuż podobnych linie do Laminy, ale trochę mniej ściśle - wiele z głównych rzeczy, których potrzebujesz, jest albo w aliasach w cascalog.api ns, ale możesz także sięgnąć do podstawowych ns dla bardziej zaawansowanych funkcji. –