2010-04-25 32 views
5

Wäre es möglich, den Befehl 'require' zu überschreiben, um zu versuchen, eine bestimmte Ressource herunterzuladen, wenn sie nicht auf dem lokalen Rechner gefunden wurde. Zum Beispiel:Außer Kraft setzen in Clojure?

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

Antwort

4

könnten Sie überschreiben die require Funktion und natürlich könnte die überschriebenen Variante Zeug herunterladen, wenn der Namensraum nicht verfügbar gefragt wurde auf dem Classpath ist. Überschreiben der Art und Weise :require funktioniert in (ns ...) Formulare ist, AFAIK, jetzt unmöglich wegen der Art und Weise, in der ns behandelt wird.

Beachten Sie, dass solch ein "Herunterladen require" nicht sehr hilfreich wäre, wenn Sie neue Pfade auf dem Klassenpfad platzieren möchten (einschließlich neuer JARs), da die Classpath-Injektion in Clojure nicht zuverlässig funktioniert (aufgrund von JVM-Problemen). . Dort istclojure.core/add-classpath ... aber es ist als veraltet seit für immer jetzt markiert, seine Verwendung wird dringend abgeraten, gibt es keine Garantien, dass es für Sie arbeiten wird und diese Situation wird sich wahrscheinlich nicht bald ändern. Wenn Sie andererseits neue Quelldateien in ein Verzeichnis einfügen möchten, das bereits im Klassenpfad vorhanden ist, sollte das problemlos funktionieren.

Falls Sie mit zwingenden require rumspielen wollen, wenn Sie einen foo Namespace haben, Sie

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

tun könnte, dann definieren Sie Ihre eigenen erfordern, mit clojure.core/require bei Bedarf:

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

clojure.contrib.find-namespaces Namespace kann hilfreich sein, um herauszufinden, was im Klassenpfad verfügbar ist. (Oder Sie könnten die the-ns Funktion verwenden und sehen, ob es eine Ausnahme nach einem anfänglichen Versuch wirft bei der Namespace durch clojure.core/require erfordern.)

Beachten Sie, dass der binding Ansatz, der zuerst in dem Sinne kommen könnte ((binding [require ...] ...)) wird nicht funktionieren, da require löst normalerweise zu einem Var im clojure.core Namespace und Vars von Namespaces, deren Namen mit clojure beginnen, sind derzeit direkt vom Compiler verbunden (was bedeutet, dass keine tatsächliche Var-Lookup zur Laufzeit durchgeführt wird, so Rebind dieser Vars hat keine Auswirkungen auf den Code) .

Die (:refer-clojure :exclude [require]) in der ns Form für Ihren Namensraum verhindert require zum clojure.core/require Lösung und lassen Sie einen Var dieses Namen in Ihrem eigenen Namensraum zu definieren. Wie oben erwähnt, verhindert dies nicht, dass die Variable clojure.core/require Var zugänglich ist, wenn Sie das vollständig qualifizierte Symbol eingeben.

+0

Interessant. Ich denke, es könnte besser sein, einen anderen Funktionsnamen wie "enhanced-require" zu verwenden, um die Namespace-Problemumgehungen zu vermeiden. (Ich bin ein totaler Noob, also korrigiere mich, wenn ich Unsinn spreche. :)) – StackedCrooked

+0

Im Gegenteil, das scheint ein besserer Weg zu sein.Ich muss jedoch sagen, dass der beste Weg, Leiningen/Maven, irgendwelche Bibliotheksabhängigkeiten zu bekommen, und für Dinge wie Quellcode begleitende Bücher, gehen Sie einfach und laden Sie es von Hand herunter ...: -) Nicht, dass es etwas aus dem Spaß nimmt, einen funky Require zu schreiben, der das alleine machen würde! –

Verwandte Themen