完全初心者がイベント開始30分前でClojureをなんとなくわかるようにがんばる!
- スライドのコード片を見てなんとなくイメージが湧くこと
- Java API呼び出し
- Java資産の活用
- ポータビリティ
- カッコが数が少なめ
- カッコの種類が多め
- ()
- []
- {}
- Lispの(歴史的経緯による)イマイチ?なところをomit
- car,cdr,cadr,cdar,cddar…
厳密な定義、コンセンサスがあるわけではありません(炎上注意!)。
- 関数が一級市民である
- 副作用がない
Clojure(Lisp)は副作用を許容している。
- 状態の変更ができない。
- 参照を付け替えることはできる。
とりあえずのリンク
Lisp経験者はDifferences with other Lisps も参考に…
- S式
- 改行にほとんど意味は無い
- 前置記法
+が関数で、1, 2, 3, 4, 5が引数
(+ 1 2 3 4 5) ;=> 15
(3 + 4) * ((5 - 2) + 3)
(* (+ 3 4) (+ (- 5 2) 3)) ;=> 42
(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"
;; "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"])