2011-09-26 3 views
15

次のClojureプログラムがNullPointerExceptionをスローするのはなぜですか?枝の内部{:status 200, :body "Hello World"} -Clojureでifステートメントの後に2つのコマンドを連続して実行します。

user=> (defn x [] 
     "Do two things if the expression is true." 
     (if true ((println "first expr") (println "second expr")) false)) 

user=> (x) 
first expr 
java.lang.NullPointerException (NO_SOURCE_FILE:0) 
second expr 

これは私がマップを返す前に、多分3つのステートメント(DBからプル値)を実行したい私の実際のユースケースの簡易版です。

+0

体内で複数の式を持つdoseqを実行しているときに[クロージャーのNullpointer]の複製が可能です。(http://stackoverflow.com/questions/1530555/nullpointer-in-clojure-when-running-doseq-with-multiple-expressionsイン・ザ・ボディ) – amalloy

答えて

31

最初のprintlnの結果を関数として処理して、2番目のprintln関数を呼び出そうとしています。

doが必要です。 (スキーム開始CLでのprogn)

(defn x [] 
    "Do two things if the expression is true." 
    (if true (do (println "first expr") (println "second expr")) false)) 

(x) 

do特殊な形態は、シーケンス内の引数の各々を実行し、最後の結果を返します。

+0

はい、一般的です。いくつかの形式はそれを意味するかもしれません(Scheme 'cond'はそれを意味しますが、Clojureのバージョンは引数がリストにないのでそうは思いません)。 '((foo ...)(bar ...))' _generally_は、fooの結果を引数として残りの引数を呼び出す関数として使用します。 – Random832

+0

これは 'do'が文を順番に実行することを意味しますか? (彼らは副作用があると仮定します)? –

+0

'do'は実際にその文を逐次実行します。 – Hugh

10

nilは他のケースでは戻り値として、暗黙のdoブロックを有しているwhenの使用を検討してOKの場合:

(defn x [] 
    "Do two things if the expression is true." 
    (when true 
    (println "first expr") 
    (println "second expr"))) 
7

ない、それはあなたの特定のケースで重要、しかし(do ...)の違いを知っていますかということそれぞれのフォームを独自のクラスローダーにロードし、空のletフォーム(let [] ...)は、単一のクラスローダーでフォーム全体を評価します。

+2

それ以外の場合は、独自のクラスローダーで各フォームを読み込むことの実際的な違いは何ですか?多分私はクラスローダーの意味を理解していないかもしれません。 –

+2

たとえば、カスタムのデフトフートと複数のクラスを定義するマクロを作成しています。最適化として、より少ないクラスローダーインスタンスが作成されるように、同じクラスローダーを使用したいと考えています。 – bmillare

関連する問題