我正在尝试围绕Java API编写一个Clojure层,如下所示:
public class Executor {
public interface ExecutorJob<Result> {
public Result execute () throws Exception;
}
public static <R> R executeAsUser(RunAsWork<R> executorJob, String uid) {
try {
//...
R result = executorJob.execute();
return result;
}
finally {
//...
}
}
}我的目标是创建一个Clojure API,允许将fn作为ExecutorJob的execute方法的主体执行。这是我想出来的:
(defmacro execute-as
"Runs the form f while impersonating the given user"
[user f]
`(let [work# (reify Executor$ExecutorJob
(~'execute [~'this]
(~f)))]
(Executor/executeAsUser work# ~user)))不幸的是,考虑到这个调用:
user> (macroexpand '(run-as "admin" (.println System/out "test")))
(let* [work__2928__auto__ (clojure.core/reify package.to.Executor$ExecutorJob (execute [this] ((.println System/out "test"))))] (package.to.Executor/executeAsUser work__2928__auto__ "admin"))它会导致NPE:
user> (execute-as "admin" (.println System/out "test"))
No message.
[Thrown class java.lang.NullPointerException]
Restarts:
0: [QUIT] Quit to the SLIME top level
Backtrace:
0: user$eval2936$reify__2937.doWork(NO_SOURCE_FILE:1)
1: package.to.Executor.executeAsUser(Executor.java:508)
2: user$eval2936.invoke(NO_SOURCE_FILE:1)
3: clojure.lang.Compiler.eval(Compiler.java:5424)
4: clojure.lang.Compiler.eval(Compiler.java:5391)
5: clojure.core$eval.invoke(core.clj:2382)
--more--我尝试将一些有意义的execute-as调用放在Java参数中,我可以看到,使用调试器可以很好地执行这些调用。
这个宏有什么问题?
发布于 2011-04-17 16:35:40
不要紧,我明白了:我误用了宏参数,并试图实际调用表单f的执行结果。而且它的收益率为零,因此产生了NPE。
更正后的版本:
(defmacro execute-as
"Runs the form f while impersonating the given user"
[user f]
`(let [work# (reify Executor$ExecutorJob
(~'execute [~'this]
~f))]
(Executor/executeAsUser work# ~user)))https://stackoverflow.com/questions/5692307
复制相似问题