2011-04-17 2 views
2

Я пытаюсь написать слой Clojure вокруг API Java, который выглядит следующим образом:Разовые экземпляры, созданные с материализовать причиной NPE

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 { 
     //... 
    } 
    } 

} 

Моя цель состоит в том, чтобы создать API Clojure, который позволяет выполнять a fn как тело 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-- 

Я пытался поставить некоторые значимые Java звонки в execute-as вторых параметров, которые, как я вижу, отлично исполняются с помощью отладчика.

Что случилось с этим макросом?

ответ

2

Nevermind, я понял: я неправильно использовал параметр макроса и пытался на самом деле позвонить результат выполнения формы 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))) 
+0

Спасибо за ответ на свой вопрос! Хорошо видеть разработчиков, которые готовы потратить время, чтобы внести свой вклад в сообщество, и позволить другим учиться на их опыте. –