NAND2TETRIS コースに登場する アセンブリから Hack 機械語へのアセンブラー。
Install clj and Clojure: official instructions.
Start a REPL:
clj -M:repl/conjureConjure will automatically connect to the REPL when opening Neovim.
Motions for Conjure all start with the custom prefix ,c.
Important motions include:
<prefix>eb: Interpret the entire buffer (file);- (in selection mode)
<prefix>E: Interpret the selection <prefix>lv: Open log in new vertical window
Run a file using (-M stands for main):
clj -M <file/path>Clojure で condition map という機能を使い、 関数の定義に引数・返り値に対する assert を組み込むができる。
(defn kelvin-to-celsius [K]
{:pre [(>= K 0)] ; 負数のケルビンはありえない
:post [(float? %)]} ; 返り値はかならず浮動小数点数になる
(+ K 273.15))アサーションの利点の一つは、あとから単体テストでアサーションの内容を確認する必要をなくす。 condition map により、引数・返り値の値に契約を課し、バグが起こりうる箇所を簡単に減らすことができる。
"w.txt" に "true" を書き込みたく、以下のコードを書いたとしよう。
(with-open [w (clojure.java.io/writer "w.txt")]
(.write w true))このコードを実行すると次の例外が投げられる:
Execution error (IllegalArgumentException) at user/eval8965 (REPL:1).
No matching method write found taking 1 args for class java.io.BufferedWriter
この例外によれば、java.io.BufferedWriterであるwにwriteメソッドがないというような内容に聞こえる。
だが、実は大事なのは1行目のIllegalArgumentExceptionであり、本当のエラーを示す。
すなわち、BufferedWriterのwriteにブールを渡すのは間違いだということ。
このエラーは下記のコードで連発していた:
(defn hoge [x y]
(-> x
#(fuga y %)
...))(->)のページを調べると、匿名関数は括弧に入れないと例外が発生するそうだ。したがって、以下のようになる。
(defn hoge [x y]
(-> x
(#(fuga y %)) ; 括弧に入れる
...))また、次の場合も例外が起こる:
(-> 10
(fn [n] (/ n 2))) ; 例外今回の例外の内容は違う:
Syntax error macroexpanding clojure.core/fn at (<address>).
10 - failed: vector? at: [:fn-tail :arity-1 :params] spec: :clojure.core.specs.alpha/param-list
10 - failed: (or (nil? %) (sequential? %)) at: [:fn-tail :arity-n] spec: :clojure.core.specs.alpha/params+body
直し方は変わらない:
(-> 10
((fn [n] (/ n 2)))) ; これも括弧に入れる正確な原因がわからないが、匿名関数を実行しない限り「本物」の関数(引数を引き受ける関数)に変換されないかもしれない。
たとえば、REPLに#(/ % 2) 10を入力しても返されるのは10だけであり、(#(/ % 2) 10)ならちゃんと5が返される。
同じく、(->)`に匿名関数をそのまま渡すと実行されず関数として解釈されていない可能性がある。