読者です 読者をやめる 読者になる 読者になる

レガシーコード生産ガイド

私に教えられることなら

少しだけClojure

clojure CommonLisp

目が覚めてしまったのでプログラミングClojure第2版を読みながら少しだけ触ったメモを書いておく。

ソースコードのダウンロード

公式のダウンロードページから落としたものはREADMEとproject.cljが入ってない。(RAKE?ファイルでどうにかするのかな) なのでgithubリポジトリからcloneしてlein depsした。

git clone https://github.com/stuarthalloway/programming-clojure.git
cd programming-clojure
lein deps

セット

user=> (conj #{} "hoge")
#{"hoge"}

わかる。*1で前の式の値が取れるみたいなので、同じものを追加してみよう。

user=> (conj *1 "hoge")
#{"hoge"}

わからん。え、なんで?

#{}はそもそも何だろう……空のセット……あ、集合か。

user=> (conj *1 "fuga")
#{"fuga" "hoge"}
user=> (conj *1 "fuga")
#{"fuga" "hoge"}

わかった。

atomって何だ

「アトムに名前をつけるにはdefを使う」え、そのまま(def hoge 1)じゃダメなの?

clojureの変数が変更不可なのと関係しているのかな。試してみよう。

user=> (def visitors_ #{})
#'user/visitors_
user=> visitors_
#{}
user=> (swap! visitors_ conj "fuga")

ClassCastException clojure.lang.PersistentHashSet cannot be cast to clojure.lang.Atom  clojure.core/swap! (core.clj:2235)
user=> (pst)
ClassCastException clojure.lang.PersistentHashSet cannot be cast to clojure.lang.Atom
    clojure.core/swap! (core.clj:2235)
    user/eval1206 (form-init9093331585345788077.clj:1)
    clojure.lang.Compiler.eval (Compiler.java:6703)
    clojure.lang.Compiler.eval (Compiler.java:6666)
    clojure.core/eval (core.clj:3028)
    clojure.main/repl/read-eval-print--6807/fn--6810 (main.clj:239)
    clojure.main/repl/read-eval-print--6807 (main.clj:239)
    clojure.main/repl/fn--6816 (main.clj:257)
    clojure.main/repl (main.clj:257)
    clojure.tools.nrepl.middleware.interruptible-eval/evaluate/fn--592 (interruptible_eval.clj:67)
    clojure.core/apply (core.clj:626)
    clojure.core/with-bindings* (core.clj:1864)
nil

ダメみたいだ。変更可能なリファレンスタイプの変数にしないといけない、ってことかな。これはそのうちわかるでしょう。

user=> (def visitors (atom #{}))
#'user/visitors

user=> visitors
#<Atom@5d8ca9e: #{}>

user=> @visitors
#{}

見やすいように改行を挟んだ。

ところでvisitorsを評価した際のこのAtomの記法は、そのまま使えるんだろうか?なんとなくダメそうな気がするけど、試してみる。

user=> #<Atom@5d8ca9e: #{}>

RuntimeException Unreadable form  clojure.lang.Util.runtimeException (Util.java:221)

CompilerException java.lang.RuntimeException: Unable to resolve symbol: Atom in this context, compiling:(/tmp/form-init9093331585345788077.clj:1:1010) 

NumberFormatException Invalid number: 5d8ca9e:  clojure.lang.LispReader.readNumber (LispReader.java:256)
#{}
#<core$_GT_ clojure.core$_GT_@1af9c8d9>

ダメか。

swap!をCommon Lispで書いてみる

ちょっと便利そう。

(defmacro swap! (var fn &rest args)
  `(setf ,var (,fn ,var ,@args)))

(defun push2 (place obj) (cons obj place))

試してみる。

CL-USER> (defvar hey '(2 1))

HEY
CL-USER> (swap! hey push2 3)
(3 2 1)
CL-USER> hey
(3 2 1)
CL-USER> (swap! hey push2 4)
(4 3 2 1)

#'heyじゃなくてheyなのが気持ち悪さを感じる。

広告を非表示にする