克服Clojure的'要求'?

时间:2010-04-25 18:39:08

标签: clojure

是否可以覆盖'require'命令,以便在本地计算机上找不到某个资源时尝试下载该资源。例如:

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

2 个答案:

答案 0 :(得分:4)

您可以覆盖require函数,当然,如果要求的命名空间在类路径中不可用,则覆盖变量可以下载内容。由于:require的处理方式,覆盖(ns ...)ns表单中工作的方式是AFAIK,现在是不可能的。

请注意,如果您想在类路径(包括新的jar)上放置新路径,那么'下载require'将不会非常有用,因为类路径注入在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通常会解析为clojure.core命名空间中的Var并且名称以clojure开头的名称空间的变量当前由编译器直接链接(意味着在运行时不执行实际的Var查找,因此重新绑定这些变量对代码没有影响)。

您的命名空间的(:refer-clojure :exclude [require])表单中的ns会阻止require解析为clojure.core/require,并让您自由在您自己的命名空间中定义该名称的Var。如上所述,如果您输入完全限定符号,则不会阻止clojure.core/require Var被访问。

答案 1 :(得分:1)

实际上,(add-classpath“http://foo/bar/baz/src/”)或(add-classpath“http://www.foo.com/bar.jar”),允许需要远程资料。

然而,Michał的警告确实适用:只能用这个来代替... ...