Skip to content

eloyrobillard/clj-nand-2-tetris

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

108 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Clojure Hack Assembler

NAND2TETRIS コースに登場する アセンブリから Hack 機械語へのアセンブラー。

Getting Started

Using Neovim/Conjure

Install clj and Clojure: official instructions.

Start a REPL:

clj -M:repl/conjure

Conjure 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の独特な機能 Clojure's special features

契約プログラミング

Clojure で condition map という機能を使い、 関数の定義に引数・返り値に対する assert を組み込むができる。

(defn kelvin-to-celsius [K]
  {:pre [(>= K 0)]     ; 負数のケルビンはありえない
  :post [(float? %)]}  ; 返り値はかならず浮動小数点数になる
  (+ K 273.15))

アサーションの利点の一つは、あとから単体テストでアサーションの内容を確認する必要をなくす。 condition map により、引数・返り値の値に契約を課し、バグが起こりうる箇所を簡単に減らすことができる。

Clojure/Javaにおける意味不明なエラー Cryptic errors in Clojure/Java

No matching method write found taking 1 args for class java.io.BufferedWriter

"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であるwwriteメソッドがないというような内容に聞こえる。

だが、実は大事なのは1行目のIllegalArgumentExceptionであり、本当のエラーを示す。

すなわち、BufferedWriterwriteにブールを渡すのは間違いだということ。

class <module>$<function>$sym__<number> cannot be cast to class java.lang.<Class>

このエラーは下記のコードで連発していた:

(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が返される。

同じく、(->)`に匿名関数をそのまま渡すと実行されず関数として解釈されていない可能性がある。

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors