私は最初のClojureプログラムでNPEに苦労しています。NullPointerException in Clojure reduceメソッド
call-elem
が含む構造体である: -
:id
次のように、some.packagename.SomeClass.someMethod
:calls
(子供)のような文字列は、他の構造体call-elem
のベクトルが定義される:
(defstruct call-struct :id :calls)
(defn- class-name [call]
(let [id (call :id)]
(.substring id 0 (.lastIndexOf id "."))))
(defn- method-name [call]
(let [id (call :id)]
(.substring id (inc (.lastIndexOf id ".")))))
私はまた、foo
という方法を持っており、これは引数としてclass-map
とcall-elem
をとります。 class-map
はclass-name
〜method-map
の地図です。 method-map
は、method-name
のマップとvariation
のリストです。各variation
は、キーが:class-name
,:method-name
、:calls
のマップです。 :calls
は他のバリエーションのリストです。 foo
関数は、2つの要素を持つベクトルを返す必要があります: -
- 最初の要素は2番目の要素は引数に対応したバリエーションマップで新しい
call-elem
に対応するエントリとその子 - とクラスマップですここで
call-elem
はコードです:
(declare foo' add-new-variation)
(defn foo [class-map call-elem]
(let [children (call-elem :calls)
class-name (class-name call-elem)
method-name (method-name call-elem)]
(if (empty? children)
(let [new-variation {:class-name class-name
:method-name method-name
:calls []}
new-class-map (add-new-variation class-map
class-name method-name
new-variation)]
[new-class-map new-variation])
(let [[new-class-map child-variations-list]
(reduce #(foo' %1 %2) (class-map '()) children)
new-variation {:class-name class-name
:method-name method-name
:calls child-variations-list}
new-class-map' (add-new-variation new-class-map
class-name method-name
new-variation)]
[new-class-map' new-variation]))))
(defn foo' [[class-map variations-list] call-elem]
(let [[new-class-map new-variation] (foo class-map call-elem)]
[new-class-map (cons new-variation variations-list)]))
(defn add-new-variation [class-map class-name method-name variation]
(let [method-map (if (contains? class-map class-name)
(class-map class-name) {})
variations-list (if (contains? method-map method-name)
(method-map method-name) [])
new-variations-list (conj variations-list variation)
new-method-map (assoc method-map method-name new-variations-list)]
(assoc class-map class-name new-method-map)))
私はFOを実行しようとするとllowingコード:私は次のような結果を得る
(try
(let [call-elem
(struct call-struct "Class1.method1"
[(struct call-struct "Class2.method1" [])])]
(second (foo {} call-elem)))
(catch Exception ex
(.printStackTrace ex)))
:
(try
(let [call-elem
(struct call-struct "Class1.method1"
[(struct call-struct "Class2.method1"
[(struct call-struct "Class3.method1" [])])])]
(second (foo {} call-elem)))
(catch Exception ex
(.printStackTrace ex)))
:私は1つのレベルより深い呼び出しを高め、次のコードを実行しようとすると
{:class-name "Class1",
:method-name "method1",
:calls ({:class-name "Class2", :method-name "method1", :calls []})}
しかし、私はNullPointerException
取得します
ここにスタックトレースがあります:
java.lang.NullPointerException
at first.simple$foo.invoke(NO_SOURCE_FILE:46)
at first.simple$foo_SINGLEQUOTE_.invoke(NO_SOURCE_FILE:55)
at first.simple$foo$fn__1986.invoke(NO_SOURCE_FILE:46)
at clojure.lang.ArrayChunk.reduce(ArrayChunk.java:58)
at clojure.core.protocols$fn__5565.invoke(protocols.clj:30)
at clojure.core.protocols$fn__5543$G__5538__5552.invoke(protocols.clj:11)
at clojure.core$reduce.invoke(core.clj:5995)
at first.simple$foo.invoke(NO_SOURCE_FILE:46)
at first.simple$eval2010.invoke(NO_SOURCE_FILE:6)
at clojure.lang.Compiler.eval(Compiler.java:6465)
at clojure.lang.Compiler.eval(Compiler.java:6431)
at clojure.core$eval.invoke(core.clj:2795)
at clooj.repl$create_clojure_repl$repl_thread_fn__578$fn__589.invoke(repl.clj:147)
at clojure.main$repl$read_eval_print__5967.invoke(main.clj:244)
at clojure.main$repl$fn__5972.invoke(main.clj:265)
at clojure.main$repl.doInvoke(main.clj:265)
at clojure.lang.RestFn.invoke(RestFn.java:1523)
at clooj.repl$create_clojure_repl$repl_thread_fn__578.invoke(repl.clj:145)
at clojure.lang.AFn.run(AFn.java:24)
at java.lang.Thread.run(Thread.java:680)
スポットオン!ありがとう!コードの改善に関する推奨事項はありますか?私が言ったように、これはClojureでの私の最初の試みです。だから、どんな提案も大歓迎です。 :) –