コードに含まれる Clojure エラーをデバッグするのは、これまでに使用した他のすべてのプログラミング言語と比べて非常に困難です。私の主なプログラミング言語は Java で、Clojure は初めてです。私が Clojure を書いている時間の大半は、「なぜこのエラーが発生するのか?」を解明することに費やされています。私はそれを変えたいと思います。CounterClockWise をプライマリ IDE として使用しています。Emacs の使い方がわかりません (まだ?)。
次に例を示します。
(ns cljsandbox.core)
(def l [1 2 3 1])
(defn foo
[l]
(->> l
(group-by identity)
;vals ;commented out to show my intent
(map #(reduce + %))))
ここでは、 がリストのリストを返すと誤って考えていgroup-by
ましたが、実際にはマップを返す<key, list<value>>
か、Java 用語で表現したいのですが。これにより、次のようなエラー メッセージが表示されます。
ClassCastException clojure.lang.PersistentVector は java.lang.Number にキャストできません clojure.lang.Numbers.add (Numbers.java:126)
スタック トレースがないため、これはあまり役に立ちません。入力(e)
すると、次のように表示されます。
java.lang.ClassCastException: clojure.lang.PersistentVector cannot be cast to java.lang.Number
at clojure.lang.Numbers.add (Numbers.java:126)
clojure.core$_PLUS_.invoke (core.clj:944)
clojure.core.protocols/fn (protocols.clj:69)
clojure.core.protocols$fn__5979$G__5974__5992.invoke (protocols.clj:13)
clojure.core$reduce.invoke (core.clj:6175)
cljsandbox.core$foo$fn__1599.invoke (core.clj:10)
clojure.core$map$fn__4207.invoke (core.clj:2487)
clojure.lang.LazySeq.sval (LazySeq.java:42)
このエラーメッセージから、「リストのリストを渡そうと思ってmap
いたのに、実際にはマップデータ型を渡していた」という理解に至る方法がわかりません。スタック トレースは、問題が の内部でreduce
はなく の内部で報告されたことを示していますがgroup-by
、IMO は、人間としての私が間違いを犯した場所ではありません。ここで、プログラムが間違いを発見したのです。
このような問題は、解決するのに 15 分以上かかることがあります。時間を短縮するにはどうすればよいですか?
動的言語がこれらのエラーをキャッチすることを期待するのは多すぎることを私は知っています。しかし、javascript のような他の動的言語のエラー メッセージの方がはるかに役立つと思います。
私は 1 ~ 2 か月前から clojure でコーディングしており、これらの問題をより適切に解決できるようにする必要があると感じているため、ここでかなり必死になっています。関数で:pre
/を使用してみましたが、いくつか問題があります:post
:pre
/のレポート:post
はひどいものです。テストしたものを文字通り印刷するだけです。そのため、多くの労力を費やさない限り、エラー メッセージは役に立ちません。- これはあまり慣用的な感じではありません。
:pre
/を使用する唯一のコードは、/:post
の使用方法を説明する記事です。:pre
:post
- /を挿入できるように、スレッド化マクロのステップを独自
defn
の sに引き出すのは本当に面倒です。:pre
:post
- もし私がこの習慣を忠実に守っていたら、私のコードは Java のように冗長になると思います。私は手で型システムを再発明するでしょう。
次のような安全性チェックをコードに追加するところまで来ました。
(when (= next-url url)
(throw (IllegalStateException. (str "The next url and the current url are the same " url))))
(when-not (every? map? posts-list)
(throw (IllegalStateException. "parsed-html->posts must return a list of {:post post :source-url source-url}")))
最初の箇条書きのみを修正します。
私はどちらかのように感じます
- 私は非常に間違った開発プロセスを持っていて、それを知りません
- 他の誰もが知っていることを知らないデバッグツール/ライブラリがいくつかあります
- 他の誰もがこのような問題を抱えており、それは Clojure の汚い小さな秘密です / 他の誰もが動的言語に慣れており、エラーを解決するために私が行っているのと同じ努力をすることを期待しています
- CounterClockWise にはバグがあり、私の生活を必要以上に難しくしています
- Java コードよりも Clojure コードのユニット・テストの方がはるかに多くのユニット・テストを作成することになっています。使い捨てのコードを書いていても。