Skip to content

Instantly share code, notes, and snippets.

@sambatriste
Last active July 21, 2016 03:14
Show Gist options
  • Save sambatriste/5726faa9970e646fc0d3713235c67458 to your computer and use it in GitHub Desktop.
Save sambatriste/5726faa9970e646fc0d3713235c67458 to your computer and use it in GitHub Desktop.

Clojure in 30 min

完全初心者がイベント開始30分前でClojureをなんとなくわかるようにがんばる!

  • スライドのコード片を見てなんとなくイメージが湧くこと

Clojureの特徴

JVMで動作する

  • Java API呼び出し
  • Java資産の活用
  • ポータビリティ

Lisp系の関数型言語

Lispをベースにしながらも洗練された文法

  • カッコが数が少なめ
  • カッコの種類が多め
    • ()
    • []
    • {}
  • Lispの(歴史的経緯による)イマイチ?なところをomit

関数型言語?

厳密な定義、コンセンサスがあるわけではありません(炎上注意!)。

  • 関数が一級市民である
  • 副作用がない

Clojure(Lisp)は副作用を許容している。

イミュータブル(immutable)

  • 状態の変更ができない。
  • 参照を付け替えることはできる。

リンク

とりあえずのリンク

Lisp経験者はDifferences with other Lisps も参考に…

文法

  • S式
    • 改行にほとんど意味は無い
  • 前置記法

簡単ルール

I. 一番左の要素が関数、残りがその引数として評価される

+が関数で、1, 2, 3, 4, 5が引数

(+ 1 2 3 4 5) ;=> 15

II. カッコの内側左側から評価される

(3 + 4) * ((5 - 2) + 3)

(* (+ 3 4) (+ (- 5 2) 3)) ;=> 42

III. I, IIのルールに従わないやつがいる(特殊形式:special form)

(if true (println "TRUE!") (println "FALSE!"))

(if false (println "TRUE!") (println "FALSE!"))

ルールI,IIを適用するとTRUE!とFALSE!両方が表示されそうな気がしますが、 実際はTRUE!かFALSE!一方だけが表示されます。

関数定義

  • defnで関数を定義します(defunではない)。
(defn hello [name]
  (str "Hello " name "!"))

(hello "clojure")  ;;=> "Hello clojure!"

リテラル

文字列

  • ダブルクォーテーションで括ります。
    • 改行を含むことができます。
(def s
"aaa
bbb")

s  ;;=>"aaa\nbbb"

リスト

'(1 2 3)

(first '(1 2 3)) ;;=> 1
(rest '(1 2 3))  ;;=> (2 3)
  • クォートを付けずに評価すると先頭の1が関数と見なされてエラーになります。

ベクタ

(def v [1 2 3])
(first v) ;;=> 1
(nth v 1) ;;=> 2

(cons 0 v)   ;;=> [0 1 2 3]
(conj v 4 5) ;;=> [1 2 3 4 5]

マップ

(def m {:a "A" :b "B" :c "C"})
(m :a)     ;;=> "A"
(get m :c) ;;=> "B"
(:c m)     ;;=> B

(assoc m :d "D")           ;;=> {:a "A", :b "B", :c "C", :d "D"}
(merge m {:d "D" :e "E"})  ;;=> {:a "A", :b "B", :c "C", :d "D", :e "E"}

名前空間

(ns aaa)
(def name "aaa")

(ns bbb)
(def name "bbb")

name     ;;=> "bbb"
aaa/name ;;=> "aaa"

Javaコード呼び出し

;; "TIS".length()
(.length "TIS")          ;;=> 3
(. "TIS" contains "IS")  ;;=> true

高階関数

  • 関数の引数に関数を渡す
  • 関数の戻り値に関数を返す

要素いっこいっこに関数を適用する

(defn nibai [num] (* num 2))
(map nibai [1 2 3 4 5]) ;;=> (2 4 6 8 10)

要素を抜き出す

(defn big? [num] (> num 3))
(filter big? [1 2 3 4 5])  ;;=> (4 5)

集約する

(reduce + [1 2 3 4 5]) ;;=> 15

組み合わせ

(reduce + (filter big? (map nibai [1 2 3 4 5])))  ;;=> 28
おまけ:スレッディングマクロ
(->> [1 2 3 4 5] (map nibai) (filter big?) (reduce +)) ;;=> 28

(macroexpand '(->> [1 2 3 4 5] (map nibai) (filter big?) (reduce +))) ;;=> (reduce + (filter big? (map nibai [1 2 3 4 5])))

無名関数

前述の高階関数として使います。

(defn long? [s] (> (count s) 5))
(long? "abc") ;;=> false
(long? "abcdef") ;;=> true

(filter long? ["a" "abc" "abcdef"]) ;;=> ("abcdef")
;; fn 
(filter (fn [s] (> (count s) 5)) ["a" "abcde" "abcdef"])
;; #
(filter #(> (count %1) 5) ["a" "abcde" "abcdef"])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment