2010-04-25 12 views
5

Czy byłoby możliwe przesłonięcie polecenia "wymagaj", aby próbował pobrać określony zasób, jeśli nie został znaleziony na komputerze lokalnym. Na przykład:Przesłanianie "wymagać" w Clojure?

(require 'examples.introduction) 
; if not found => download from the net 
; (url: http://media.pragprog.com/titles/shcloj/code/examples/introduction.clj) 

Odpowiedz

4

Można zastąpić funkcję require i oczywiście wariant nadpisane mogli sciagac czy nazw został poproszony o nie jest dostępny na ścieżce klasy. Przesłonięcie drogi :require działa w formularzach AFAIK jest niemożliwe z powodu sposobu, w jaki obsługiwane jest ns.

Należy pamiętać, że takie pobieranie "" nie byłoby zbyt pomocne, gdyby użytkownik chciał umieścić nowe ścieżki w ścieżce klas (w tym nowe słoiki), ponieważ wtrysk ścieżki klasy Closspath nie działa niezawodnie w Clojure (z powodu problemów z maszyną JVM) . Jest tam jestclojure.core/add-classpath ... ale został oznaczony jako przestarzały, ponieważ na zawsze teraz, jego użycie jest zdecydowanie odradzane, nie ma żadnych gwarancji, że zadziała ono dla ciebie i ta sytuacja prawdopodobnie nie zmieni się w najbliższym czasie. Z drugiej strony, jeśli chcesz umieścić nowe pliki źródłowe w katalogu, który był już obecny w ścieżce klas, to powinno działać poprawnie.

W przypadku, gdy chce się bawić z nadrzędnym require, jeśli masz foo nazw, można zrobić

(ns foo 
    (:refer-clojure :exclude [require]) 
    ; other stuff; any :requires here will work as usual! 
) 

Następnie zdefiniować własne wymagać, używając clojure.core/require gdy właściwe:

(defn require [ns-symbol] 
    (do-stuff-to-obtain-the-namespace)) 

clojure.contrib.find-namespaces Przestrzeń nazw może być pomocna w ustaleniu, co jest dostępne w ścieżce klas. (Albo można użyć funkcji the-ns i zobacz czy to zgłasza wyjątek po początkowej próbie wymagające nazw poprzez clojure.core/require.)

Należy zauważyć, że podejście binding co może przyjść do głowy pierwszy ((binding [require ...] ...)) nie będzie działać, ponieważ require zwykle rozpoznaje zmienną internowaną w przestrzeni nazw clojure.core i Vars z przestrzeni nazw, których nazwy zaczynają się od clojure, są obecnie bezpośrednio połączone przez kompilator (co oznacza, że ​​w czasie wykonywania nie jest wykonywane rzeczywiste wyszukiwanie Var, więc ponowne wiązanie tych zmiennych nie ma wpływu na kod) .

(:refer-clojure :exclude [require]) w ns formie do swojego nazw zapobiega require od rozstrzygnięcia do clojure.core/require i pozostawia swobodę definiowania Var tej nazwy w swojej własnej przestrzeni nazw. Jak wspomniano powyżej, nie uniemożliwia to dostępności clojure.core/require Var, jeśli wypiszesz w pełni kwalifikowany symbol.

+0

Interesujące. Myślę, że może lepiej użyć innej nazwy funkcji, np. "Enhanced-require", aby uniknąć użycia obejść przestrzeni nazw. (Jestem totalnym noobem, więc popraw mnie, jeśli mówię bzdury.)) – StackedCrooked

+0

Wręcz przeciwnie, wydaje się, że jest to lepszy sposób na zrobienie tego. –