3

我有一个 lein 项目(使用 cascalog——但这并不是特别重要)。我正在尝试将诸如文件路径之类的属性外部化,因此最终得到的代码如下所示:

(defn output-tap [path] (hfs-textline (str (get-prop :output-path-prefix) path) :sinkmode :replace))

(def some-cascalog-query 
    (<- [?f1 ?f2 ?f3] 
        ((output-tap (get-prop :output-path)) ?line)
        (tab-split ?line :> ?f1 ?f2 ?f3)))

在上面的例子中,假设函数get-prop存在;它只是使用标准 java 来读取属性值(基于此示例:在 clojure 中加载配置文件作为数据结构)。

现在我有一个加载属性值的主要方法,例如:

(defn -main [& args] (do (load-props (first args)) (do-cascalog-stuff)))

但是当我lein uberjar得到一个编译时错误说:

Caused by: java.lang.IllegalArgumentException: Can not create a Path from an empty string
at org.apache.hadoop.fs.Path.checkPathArg(Path.java:82)
at org.apache.hadoop.fs.Path.<init>(Path.java:90)
at cascading.tap.hadoop.Hfs.getPath(Hfs.java:343)

defs 是否总是在编译时评估(而不是运行时评估)?还是我误解了这个错误?

4

2 回答 2

3

那么,您希望在运行时进行属性查找吗?那么是的,您需要定义some-cascalog-query为函数或宏。baredef导致在加载代码时评估表达式,而不是在取消引用 var 时。

这可以在 REPL 中非常简单地说明:

user=> (def foo (do (println "Hello, world!") 1))
Hello, world!
#'user/foo
user=> foo
1

文档(强调我的):

(定义符号初始化?)

使用符号名称和当前命名空间 ( ns ) 的值的命名空间创建和实习或定位一个全局变量。如果提供了 init,则对其进行评估,并将 var 的根绑定设置为结果值。

于 2012-06-19T16:35:56.307 回答
0

该错误看起来像(get-prop :output-path) (get-prop :output-path-prefix)什么都没有返回,它被包装成一个空字符串str。也许没有找到该属性?

get-prop 是否按预期工作?

您对 defs 的理解是正确的,它们是编译时,而不是(通常)运行时。

于 2012-06-19T16:11:33.397 回答