Upload
keisuke-fukuda
View
214
Download
0
Embed Size (px)
Citation preview
独自コレクションを定義しようClojure 座談会 #1 on 2015/09/12@keisukefukuda
なぜ Clojure か• Clojure は完全に趣味• なぜ Clojure か
• 趣味なので、「本質的に学ぶところがある」言語をやりたい• Go とか流行ってるけど本質的に新しくはないし• Scala 試して死んだ → そもそも俺は C++ で荒れた心を休めたいんだよ• Clojure 、 Haskell 、 Erlang ( Elixir )くらい?• といいつつある程度の実用性( JVM, Heroku )• Minecraft とかの拡張書けるんじゃね?(まだ試してない)
Clojure の思想(の 1 つ)"It is better to have 100 functions operate on one data structure than to have 10 functions operate on 10 data structures." - Alan J. Perlis
from http://clojure.org/rationale
10 のデータ構造のそれぞれに 10 個ずつ関数を作るよりも、1 個のデータ構造に 100 個の関数がある方が良い
(だいたい)なんでも map, vector, set• クラスを作ってメソッド実装というのは(あまり)やらない• だいたい map でおk• clojure の大量の関数がそのまま使える
だけど• 独自のデータ型が欲しい場合もある• 例:
• 基本的には map で良いが、一部の要素を遅延評価したい• PDF パーザーを書いているときの実体験
{:a 1 :b (delay (do-something-1)) :c (future (do-something-2)) :d 2}
(let [a (:a m)] (let [a (if (instance? clojure.lang.IDeref a) @a a)] ……))
だけど• 独自のデータ型が欲しい場合もある• 例:
• 基本的には map で良いが、一部の要素を遅延評価したい• PDF パーザーを書いているときの実体験
{:a 1 :b (delay (do-something-1)) :c (future (do-something-2)) :d 2}
(let [a (get-a m)] ……)
メソッド定義する?
そこで• Clojure の map などは、実装レベルでは Java のクラス• Clojure では Java のクラスを定義できる
• 組み込みデータ型と同じように振る舞う独自型を定義すればいいんじゃね?
http://www.rkn.io/2014/02/20/clojure-cookbook-rbt/
やってみる• clojure.lang.APersistentMap が implement しているインターフェース
• clojure.lang.Associative• clojure.lang.IPersistentMap• clojure.lang.IPersistentCollection• clojure.lang.IFn• clojure.lang.ILookup• java.util.Map• java.lang.Iterable• clojure.lang.Seqable• clojure.lang.Reversible
やってみる(deftype MyMap1 [ks f] clojure.lang.Associative clojure.lang.IPersistentMap (entryAt [this k] (if (some #{k} ks) (reify clojure.lang.IMapEntry (key [this] k) (val [this] (f k))) nil))
(assoc [this key val] this)
(assocEx [this key val] (throw (Exception. "error")))
(without [this key] this)
clojure.lang.IFn (invoke [this k] (let [v (.valAt this k)] v))
clojure.lang.ILookup (valAt [this k] (if (some #{k} ks) (f k) nil))
(valAt [this k not-found] (if (some #{k} ks) (.valAt this k)
not-found))
clojure.lang.IPersistentCollection (count [_] (.count ks)) (empty [_] (.empty ks)) (equiv [this o] (and (instance? o MyMap1) (= (keys o) ks) (= (vals o) (map f keys))))
(cons [_ v] _)
java.lang.Iterable (iterator [this] (let [s (seq this)] (reify java.util.Iterator (hasNext [this] (.hasNext s)) (next [this] (.next s)) (remove [this] (.remove s)))))
clojure.lang.Seqable (seq [_] (map #(reify java.util.Map$Entry (getKey [_] %) (getValue [_] (f %))) ks))
clojure.lang.Reversible (rseq [_] (reverse (seq _))))
ライブラリ化しよう• 作業中
ブログにも少し書きましたhttp://freak-da.hatenablog.com/
Question?