Clojure
Language Update
Clojure 1.7勉強会
2015/06/27 @HaLake
@athos0220
数字で見るClojure 1.7
‣ 開発期間:2014/5/25∼ (2014/8/6 alpha1リリース)
‣ チケット数:116 /570
‣ コミット数:159 /2756
‣ コミッター:30人 /130
‣ コード行数
- *.java:58067行 (+3582, -1011)
-  *.clj:32488行 (+2530, -1296)
数値は2015/6/25現在のもの
Clojure 1.7 変更点 概観
‣ Transducers (詳細は@athos0220の発表)
対象となるデータ構造に依存しない、各要素の変換アルゴリズムの記述方法
‣ Reader Conditionals (詳細は@_ayato_pさんの発表)
Clojure/ClojureScript/ClojureCLR間での相互運用性向上のための仕組み
‣ その他新機能
‣ パフォーマンス向上
‣ 機能向上
変更点の詳細・一覧についてはChangeLogを参照のこと
その他新機能
‣ :warn-boxed-math
‣ REPLでのデータの表示方法
‣ update関数
‣ run!関数
‣ volatile
‣ etc.
update関数
‣ update-inのネストしない版
user=> (def m {:a 0})
#’user/m
user=> (update m :a inc)
{:a 1}
;; これまでは下のようにする必要があった
user=> (update-in m [:a] inc)
{:a 1}
user=>
run!関数
‣ (run! proc s) = (reduce #(proc %2) nil s)
‣ シーケンスの各要素に副作用を起こすときに便利
user=> (run! println (range 3))
0
1
2
nil
user=>
volatile
‣ Atomより効率のよい破壊的変更を実現する
‣ stateful transducerを書くために導入された
user=> (def v (volatile! 0))
#’user/v
user=> (vreset! v 42)
42
user=> (vswap! v inc)
43
user=> @v
43
REPLでのデータの表示方法
‣ 表示方法が定義されていないオブジェクトをタグ付き
リテラルとして表示
‣ nREPLなどで評価結果を受け渡すのが便利に
user=> *ns*
#object[clojure.lang.Namespace 0x13823a1f “user”]
user=> (defn f [x])
#’user/f
user=> f
#object[user$f 0x2b65f534 “user$f@2b65f534”]
user=>
:warn-on-boxed
‣ 数値演算がプリミティブ型でなくボクシングされた
型で行なわれたときに警告を出す
user=> (defn f [x] (+ x 2))
#’user/f
user=> (set! *unchecked-math* :warn-on-boxed)
true
user=> (defn f’ [x] (+ x 2))
Boxed math warning, NO_SOURCE_PATH:10:18 …
user=> (defn f’’ [^long x] (+ x 2))
#’user/f’’
パフォーマンス向上
‣ reduceの高速化
‣ キーワード・シンボルのインターン
‣ Multimethodのキャッシュ
‣ vec/setの高速化
‣ etc. etc.
reduceの高速化
‣ 以下の関数が、IReduceを実装した固有のシーケンスを返すよ
うになった
‣ repeat
‣ cycle
‣ iterate
‣ range
‣ keys
‣ vals
‣ iterator-seq
機能向上
‣ aproposの表示改善
‣ IAtomインタフェースの分離
‣ 関数クラスのマングリングルール修正
‣ etc. etc.
aproposの表示改善
‣ 結果が名前空間修飾されて返ってくるように
‣ 各シンボルがどの名前空間に含まれるか識別可能
user=> (apropos #”^replace$”) ;; ∼1.6
(replace replace replace …)
user=> (apropos #”^replace$”) ;; 1.7∼
(clojure.core/replace clojure.string/replace
clojure.zip/replace …)
user=>
IAtomインタフェースの分離
‣ アトミックな値更新操作をIAtomインタフェースと
してAtomから分離
‣ ユーザ定義型でもreset!/swap!などが使えるように
関数名のマングリングルール修正
‣ 関数に対応するクラスを生成する際の、マングリング
された名前が衝突するのを修正
code before after
(defn a []) user$a user$a
(fn []) user$evalN$fn__N user$evalN$fn__N
(fn a []) user$evalN$a__N user$evalN$a__N
(let [a (fn [])] a) user$evalN$a__N user$evalN$a__N
(let [a (fn x [])] a) user$evalN$x__N user$evalN$a_x_N
(def a (fn [])) user$a user$a
(def a (fn x [])) user$x user$a_x_N
(def ^{:foo (fn [])} a) user$fn__N user$fn__N
(def ^{:foo (fn a [])} a) user$a user$a__N
(def a (fn [] (fn []))) user$a$fn__N user$a$fn__N
(def a (fn [] (fn x []))) user$a$x__N user$a$x__N
まとめ
‣ Clojure 1.7はさまざま環境でのコードの再利用性
を向上させる試みが取り入れられたリリース
‣ ClojureScriptやcore.asyncなどとの協調がさらに
便利になっていくかも?

Clojure Language Update (2015)