Переопределение 'требовать' в Clojure? - PullRequest
5 голосов
/ 25 апреля 2010

Можно ли переопределить команду 'require', чтобы попытаться загрузить определенный ресурс, если он не был найден на локальном компьютере. Например:

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

Ответы [ 2 ]

4 голосов
/ 25 апреля 2010

Вы можете переопределить функцию require и, конечно, переопределенный вариант может загрузить материал, если запрошенное пространство имен недоступно в пути к классам. Переопределение способа работы :require в (ns ...) формах, AFAIK, пока невозможно из-за способа обработки ns.

Обратите внимание, что такая «загрузка require» не будет очень полезной, если вы хотите разместить новые пути в пути к классам (включая новые jar-файлы), поскольку внедрение пути к классам не работает надежно в Clojure (из-за проблем с JVM ). Там есть clojure.core/add-classpath ... но он помечен как устаревший, так как навсегда, его использование настоятельно не рекомендуется, нет никаких гарантий, что он будет работать для вас, и эта ситуация вряд ли изменится в любое время скоро. С другой стороны, если вы хотите поместить новые исходные файлы в каталог, который уже присутствует в пути к классам, это должно работать нормально.

Если вы хотите поиграть с переопределением require, если у вас есть пространство имен foo, вы можете сделать

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

Затем определите свое собственное требование, используя clojure.core/require, когда это необходимо:

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

clojure.contrib.find-namespaces Пространство имен может быть полезно для определения того, что доступно на пути к классам. (Или вы можете использовать функцию the-ns и посмотреть, генерирует ли она исключение после первоначальной попытки запросить пространство имен через clojure.core/require.)

Обратите внимание, что подход binding, который может прийти в голову первым ((binding [require ...] ...)), не будет работать, так как require обычно разрешает Var, интернированный в пространстве имен clojure.core, и Vars из пространств имен, имена которых начинаются с clojure в настоящее время напрямую связаны компилятором (что означает, что в реальном времени поиск Var не выполняется, поэтому повторное связывание этих Vars не влияет на код).

(:refer-clojure :exclude [require]) в форме ns для вашего пространства имен препятствует разрешению require в clojure.core/require и позволяет вам определять переменную с этим именем в вашем собственном пространстве имен. Как упомянуто выше, это не препятствует тому, чтобы clojure.core/require Var был доступен, если вы вводите полностью квалифицированный символ.

1 голос
/ 26 апреля 2010

На самом деле, (add-classpath "http://foo/bar/baz/src/") или (add-classpath" http://www.foo.com/bar.jar"), разрешит требовать удаленного содержимого.

Предупреждения Михала действительно применяютсяхотя: Используйте это только для игры в репле ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...