楽しいClojureの話


これはなに?

沖縄で行われたハッカーズチャンプルー 2016の懇親会のLT大会で発表した資料です。


Clojureとは

  • Lisp方言のひとつ
  • インタラクティブな開発(REPL)
  • 関数型プログラミング
  • 並行処理をしやすい
  • 多様な実行環境(JVM、ClojureScript)

Lispの特徴

(str "カッコが多い言語です")

;; 関数をカッコの1番目に、2番目からあとにはその関数の引数をいれます
(+ 1 2 3 4) ; => 10

;; マクロを使って新しい文法を自分で追加できます
(defmacro unless [test then]
  (list 'if (list 'not test)
    then)))

(if true "then" "else") ; => "then"
(unless true "then" "else") ; => "else"


インタラクティブな開発(REPL)


基本、不変なデータ(変数じゃない)

; シンボルにデータを束縛する
(def my-name "arakaki yuji")
my-name ; => "arakaki yuji"

; レキシカルスコープ内のみで一時的に束縛
 (let [my-name "yuji"]
   my-name) ; => "yuji"

; スコープ外には影響ない
my-name; => "arakaki yuji" 

; 文字
/a 

; 文字列
"Hello World"

; list(Lispのベースとなるデータ型)
(list 1 2 3) ; => (1 2 3)

; Vector(順番を持ったコレクション)
["a" 1 'hello \a]

; Map(キーと値を対応させたコレクション)
{:name "arakaki yuji" :age 27}

; Set(値が一意になること保証したコレクション)

; シンボル
(symbol "my-name") ; my-name

; 関数
(fn [n] (+ n 5))
; => #object[user$eval19622$fn__19623 0x243a2394 "user$eval19622$fn__19623@243a2394"]


関数が第一級オブジェクト

; 関数定義
(defn hello-world [name]
  (str "Hello World, " name))

; 関数が第1級オブジェクトなので引数で関数を返せる関数作れる
(defn add-factory [number]
        (fn ([] number)
            ([n & more] (apply + (conj more n number)))))

(def add-8 (add-factory 8)
(def add-100 (add-factory 100))
(add-8 2)
; => 10
(add-100 30)
; => 130


変更可能なデータもある

基本不変データのClojureですが、変更可能なデータ型もある。
それらは用途に応じて使い分けれるように複数あります。


変更可能なデータ型の種類

  • atom
  • ref
  • agent
; atom 
(atom x 1)
x ; => #object[clojure.lang.Atom 0x757c7948 {:status :ready, :val 1}]
;; 値を参照するには@をつける
@x ; => 1
;; 単独で値を変更したいデータの時に使う
(reset! x 5)
@x ; => 5

; ref
(def y (ref 1))
y ; => #object[clojure.lang.Ref 0x3fe68e45 {:status :ready, :val 1}]
;; 値を参照するには@をつける
@y ; => 1
; refは複数の値を協調して変更したい場合に使う
(def z (ref 5))
(dosync 
  (ref-set y 10)
  (ref-set z 20))
@y ; => 10
@z ; => 20

; agent
(def a (agent 1))
a ; => #object[clojure.lang.Agent 0x307b6b7e {:status :ready, :val 1}]
@a : => 1
; agentは非同期でデータを変更したい場合に使う
(send a + 100)
; => #object[clojure.lang.Agent 0x307b6b7e {:status :ready, :val 1}]
a
; => #object[clojure.lang.Agent 0x307b6b7e {:status :ready, :val 101}]


並行処理をしやすい

Clojure自体が並行処理を前提として設計されている

  • 不変なデータ型
  • 関数型プログラミングにより副作用を減らす
  • 並行処理をサポートする機能を複数用意

並行処理用の機能

まだちゃんと勉強できていないのでこんなのあるよ〜ぐらい・・

  • agent
  • thread
  • core.async
  • future

多様な実行環境

  • Clojure(.clj)

    • JVM上で実行される
    • Javaのライブラリを使用可能
  • ClojureScript(.cljs)

    • JavaScriptにコンパイルされる(AltJS)
  • 両方でコードを共有可能(.cljc)

    • フロントエンドとサーバーサイドでロジックを共有できる
    • 各動作環境の独自機能は共有できないので注意

最後に

Clojure楽しいがまだ自分は大きなアプリケーション書いたことはないので、これから書いていきたい。

もし他にも興味ある方がいれば一緒にやりましょう^^/