（少し）Java使い向け、簡単なClojure入門

暇を持て余しているJava廃人はClojureで遊ぼう

# 準備

* [ClojureDocs](http://clojuredocs.org) （API、サンプルコード参照）
* [Clojure Japanese Documentation](https://sites.google.com/site/clojurejapanesedocumentation/about-japanese-translations) （日本語ドキュメント。詳しく知りたいときに）
* [Light Table](http://www.lighttable.com) （エディタ、実行環境）
* [Leiningen](http://leiningen.org) （Mavenのようなもの。あとでいい）

# Light Table 動作確認
* プロキシ環境の場合、環境変数HTTP_PROXYとHTTPS_PROXYを事前に設定

1. 新しいファイルを作成
1. ctrl-space
    + コマンドバーが開く
1. syn
    + Syntax設定
1. clo
    + Clojure選択
1. エディタで適当にコード入力
    + (map - (range 10))
1. ctrl-enter (cmd-enter)
    + コード実行

![スクリーンショット 2014-05-08 14.38.46.png](https://qiita-image-store.s3.amazonaws.com/0/40558/19190f10-04dd-9f5b-8bcc-19b18480b606.png)


* 困ったときはctrl-space、あとはググれ
* [キーマップ設定](http://qiita.com/kurogelee/items/7c04c77742ba7c0b2433)と[ビヘイビア設定](http://qiita.com/kurogelee/items/d15c65906c0cd6fc78ac)はしたければする
* 関数の詳細を簡単に知りたいときは、関数のところでctrl-d

![スクリーンショット 2014-05-08 21.33.14.png](https://qiita-image-store.s3.amazonaws.com/0/40558/513ef98b-7228-bff9-ec1b-51fb926bd6e4.png)

* 関数実行を止めたいときは、ctrl-space後、cancelかdisconnectでコマンド探す

# 基本のデータ型
* 有理数のリテラルがある（2/3など）
* 基数(radix)として2〜36まで指定できる数値リテラルがある（2r101、36rxyZなど）

![スクリーンショット 2014-05-08 14.48.24.png](https://qiita-image-store.s3.amazonaws.com/0/40558/596ea1ba-ffd0-1d68-a63c-2b492f749a5b.png)

* 整数はLong、浮動小数点数はDoubleになる
* NをつけるとBigI **n** t、MをつけるとBigDeci **m** al

![スクリーンショット 2014-05-08 14.55.08.png](https://qiita-image-store.s3.amazonaws.com/0/40558/0c318e33-682b-0d68-f36f-32ceb6798a13.png)

* 項目はスペースで区切る。カンマはスペースと同じ
* 文字列の連結は`str`で。`\ａ`などで文字を表す

![スクリーンショット 2014-05-08 15.35.13.png](https://qiita-image-store.s3.amazonaws.com/0/40558/178eb9b7-a6d8-fc68-3f96-05bb60f469d7.png)

* 特殊な文字として\return \newline \tab \space \backspace \formfeedがある
* defで変数定義（Clojureは基本的にイミュータブルなので変更されないけど）
* 文字列の一致比較は`=`でできる

![スクリーンショット 2014-05-08 15.29.28.png](https://qiita-image-store.s3.amazonaws.com/0/40558/eaf4dcff-87dc-2592-39a9-6e430d3b6973.png)

* 文字列と似て非なるものとしてキーワードがある（Rubyにあるシンボルのようなもの）。`:abc`のようにコロンを先頭につける
* 文字列と違い、連結や切り出しはできない。また文字列は文字のシーケンスとして扱えるが、キーワードはシーケンスではない

![スクリーンショット 2014-05-08 15.42.44.png](https://qiita-image-store.s3.amazonaws.com/0/40558/3b8b2130-4d2e-84af-6393-e51f33d65419.png)

# シーケンス、コレクション

* リスト（LinkedListのようなもの）
    + `(1 2 3)`
* ベクタ（ArrayListのようなもの）
    + `[2 3 4]`
* マップ（HashMapのようなもの。LinkedHashMapではない）
    * `{:a 1 :b 2}`
* セット（HashSetのようなもの。LinkedHashSetではない）
    * `#{:a :b :c}`

&nbsp;

* これらはシーケンスという抽象化した構造として様々な関数で統一的に扱うことができる。
    * マップはclojure.lang.MapEntryのシーケンスとなる。MapEntryはclojure.lang.IPersistentVectorであるためベクタでもあり、java.util.Map.Entryでもある

![スクリーンショット 2014-05-08 17.17.45.png](https://qiita-image-store.s3.amazonaws.com/0/40558/871c154f-fcbf-47c7-4257-e7c55ad434bb.png)

* なお、Iterableもシーケンスとして扱える

# シンボルとクオート、評価
* リストは中身が1つ以上のときに評価されると、先頭の要素が関数として扱われるため`(1 2 3)`のようなリストを実行（評価）すると例外が発生する

![スクリーンショット 2014-05-08 17.45.01.png](https://qiita-image-store.s3.amazonaws.com/0/40558/e8b6861e-7c3e-c5ac-c380-61aae57da3f1.png)

* 例外を発生させないためにはクオートをつけて、評価を1回行わないようにすることができる

![スクリーンショット 2014-05-08 17.52.18.png](https://qiita-image-store.s3.amazonaws.com/0/40558/8569e8ab-5360-3b8b-833e-209e738787d6.png)

* `(str :a :b)`のようなコードの`str`の部分はシンボル（clojure.lang.Symbol）であり、シンボルが関数として評価されると現在の環境から解決された（特定された）関数が実行される

* クオートをつけると、その部分全体の評価が行われないので`(def v 9) '[1 v]`の結果は、`[1 9]`ではなく`[1 v]`になるというところに注意

![スクリーンショット 2014-05-08 19.33.12.png](https://qiita-image-store.s3.amazonaws.com/0/40558/739bc676-7a99-e59e-c96f-5ca41e4e3578.png)

# 変数と関数の定義
* 関数は`defn`で定義できる
* `:pre`と`:post`で複数個の事前条件と事後条件（`%`が戻り値を表す）を指定できる

![スクリーンショット 2014-05-08 20.02.22.png](https://qiita-image-store.s3.amazonaws.com/0/40558/9d72dc36-e2dc-8adc-6383-f10bc3fff1f5.png)

* 関数では複数の引数定義を行える
* `&`の後ろは可変長引数を表す

![スクリーンショット 2014-05-08 20.45.48.png](https://qiita-image-store.s3.amazonaws.com/0/40558/dad1b15a-6ef3-f8f1-426e-122fabd5b3e7.png)

* privateな関数は`defn-`で、privateな変数は`def ^:private`で定義できる
* 関数内のローカル変数は`let`で定義できる

![スクリーンショット 2014-05-08 20.13.32.png](https://qiita-image-store.s3.amazonaws.com/0/40558/cb043fe1-d9c1-ea64-e7b5-85e94de53352.png)

# Javaメソッド呼び出し

* `(Math/pow 2 3)`のようにjava.langパッケージにある（Clojure 1.6.0ではJava 6に存在する）クラスのstaticメソッドはimportなしに呼び出せる
* インスタンスメソッドはメソッド名の前に`.`をつけて呼び出せる
* importをするとjava.lang以外のパッケージのクラス名を（パッケージ名つけずに）使える
* クラス名の後に`.`をつけるか、`new`を使うことで新しいオブジェクトを構築できる

![スクリーンショット 2014-05-08 22.49.36.png](https://qiita-image-store.s3.amazonaws.com/0/40558/1c6ad2c9-2243-87a7-9181-845b538b94f1.png)

* インスタンスメソッドは`.`を使っても呼び出せる
* `..`を使うとメソッド呼び出しを連鎖できる
* `doto`を使うと同じオブジェクトに対する複数回メソッド呼び出しが簡単にできる

![スクリーンショット 2014-05-08 23.46.45.png](https://qiita-image-store.s3.amazonaws.com/0/40558/0050ed2d-972b-f3a4-3f1f-4255d77000ce.png)

# filter, map, reduce, for
* `filter`と`remove`は逆の動作をする
* `fn`で無名関数を作れる

![スクリーンショット 2014-05-09 12.54.13.png](https://qiita-image-store.s3.amazonaws.com/0/40558/a9cc3274-bab4-3ef7-10f7-40f88c3008c1.png)

* `#(...)`の形式でも無名関数を作れる。`%`または`%1`が第一引数、`%2`が第2引数、`%&`は残りの引数を表す
* `keep`は`map`と似ているが、値がnilとなる結果は含まれない。

![スクリーンショット 2014-05-09 13.03.00.png](https://qiita-image-store.s3.amazonaws.com/0/40558/83c74f63-e6b6-abb2-c29a-42a9a5a91f32.png)

* `reduce`には初期値を与えることもできる
* `reduce`を途中で止めたい場合は`reduced`を使える
* `if`や`when`などの条件で"真"と判定されるのは`false`と`nil`以外のすべて

![スクリーンショット 2014-05-09 13.17.39.png](https://qiita-image-store.s3.amazonaws.com/0/40558/6ff0b975-0fae-37b3-0fe4-a76924182edd.png)

* 多重ループ的な処理をしたい場合は、`for`が便利
* `:while`は入れる場所によって動作が変わるので注意

![スクリーンショット 2014-05-09 14.08.37.png](https://qiita-image-store.s3.amazonaws.com/0/40558/f42b0196-5bb2-a332-2e62-b14b08687078.png)

* 結果をベクタにする`filterv`, `mapv`もある

# スレッディングマクロ
* `->>`, `->`, `as->`などを用いることで、深いネスト構造の式をフラットに記述することができる

![スクリーンショット 2014-05-09 18.10.55.png](https://qiita-image-store.s3.amazonaws.com/0/40558/5ac8ad69-74e9-8665-5766-18f49a3c2229.png)

![スクリーンショット 2014-05-09 18.15.52.png](https://qiita-image-store.s3.amazonaws.com/0/40558/a67870fb-42c1-6fe9-b76e-9d322d58ccee.png)

# 副作用と遅延シーケンス
* 関数本体や`let`本体など、複数の式が書ける場所では`println`などの副作用がある式をそのまま挟み込める
* `do`を使えば、どこにでも副作用がある式を入れられる。（`do`全体の結果は最後の式の結果となる）

![スクリーンショット 2014-05-09 15.19.05.png](https://qiita-image-store.s3.amazonaws.com/0/40558/440a7215-df8c-7f3b-47f9-119fa3b5e6da.png)

* `println`によってConsoleには以下のような表示がされる

![スクリーンショット 2014-05-09 15.20.12.png](https://qiita-image-store.s3.amazonaws.com/0/40558/f2391fd3-caa1-4cd4-a551-437905b48c8e.png)

* Javaのオブジェクトに対する操作をするときもそうだが、Clojureのオブジェクトでも`atom`, `ref`, `with-local-vars`などを用いて副作用がある操作をすることがある
* Light Tableで式の途中の値が知りたい場合は、Watchの機能が使える

![スクリーンショット 2014-05-09 17.04.19.png](https://qiita-image-store.s3.amazonaws.com/0/40558/be4923af-c796-a2ac-eeb0-ea688053e314.png)

* `map`や`filter`などの関数では結果は遅延シーケンスとして返されるため、スレッドローカルな値を扱う関数と組み合わせると期待した値にならないことがある

![スクリーンショット 2014-05-09 17.29.17.png](https://qiita-image-store.s3.amazonaws.com/0/40558/1655b480-ffb0-7e3d-c7d6-d2d011fe69c5.png)

* 遅延シーケンスを即時評価するには`doall`を使うか、ベクタやマップに変換するなどの手が使える

![スクリーンショット 2014-05-09 17.32.07.png](https://qiita-image-store.s3.amazonaws.com/0/40558/c45f5558-8d36-4782-bd1b-a7bb6800e6c1.png)

* 副作用だけが必要な場合は`doall`の代わりに`dorun`が使える
* 無限（遅延）シーケンスを評価するときには`take`などでその一部を取得する

![スクリーンショット 2014-05-09 17.44.00.png](https://qiita-image-store.s3.amazonaws.com/0/40558/8044c79e-4bce-eccc-5e6d-43120fc4f2f3.png)

# 分配束縛
* `let`や`defn`など変数に値を束縛するところでは分配束縛ができる
* `:as`を使うとそのベクタ全体の値を束縛できる。（`defn`直下のベクタでは`:as`は使えない）

![スクリーンショット 2014-05-09 19.11.48.png](https://qiita-image-store.s3.amazonaws.com/0/40558/a37bfb5d-4fde-600e-c85b-459e573c3155.png)

* `:keys`を使うとキーワード引数のような関数呼び出しを扱える。`:or`でデフォルト値を指定できる

![スクリーンショット 2014-05-09 19.29.33.png](https://qiita-image-store.s3.amazonaws.com/0/40558/43e8985c-a5df-810c-5817-2c217205632b.png)

* `:keys`の代わりに`:strs`と`:syms`で文字列とシンボルも扱えるがあまり使われない（?）

![スクリーンショット 2014-05-09 19.36.45.png](https://qiita-image-store.s3.amazonaws.com/0/40558/bb8ef73f-1617-324f-e588-beea98441445.png)

# ネームスペース
* `ns`でネームスペースを定義できる。`:require`でClojureのネームスペースを利用。`:import`でJavaのパッケージを利用

![スクリーンショット 2014-05-09 20.54.43.png](https://qiita-image-store.s3.amazonaws.com/0/40558/e8a2dcf3-a99e-aebd-1090-4517e3d00f00.png)

# 入出力と正規表現
* `spit`と`slurp`で文字列の書き込み、読み込みができる
* `:append`などのオプションを指定できる。`:encoding`でエンコーディング指定可能（デフォルトはUTF-8）

![スクリーンショット 2014-05-10 11.45.36.png](https://qiita-image-store.s3.amazonaws.com/0/40558/12ed7853-4041-87fa-46cf-77cf4e1281ce.png)

* clojure.java.ioの`writer`と`reader`を使うとBufferedWriter, BufferedReaderでの処理ができる
* 確実にcloseするために、`with-open`を使用している
* `line-seq`は遅延シーケンスを返すため、`with-open`の外まで遅延したまま持って来れないことに注意

![スクリーンショット 2014-05-10 11.47.43.png](https://qiita-image-store.s3.amazonaws.com/0/40558/eb20f8eb-5779-c5f2-11d8-5fee69ca418e.png)

* `re-find`と`re-seq`で正規表現マッチができる。
* 大文字小文字の区別を排除するには（java.util.regex.Patternで定義済みの）`(?i)`などの埋め込みフラグ表現を使う

![スクリーンショット 2014-05-10 12.12.51.png](https://qiita-image-store.s3.amazonaws.com/0/40558/5e23703b-ec66-eaaf-8259-247fc64ed553.png)

# マクロ
* 制御構造の操作を伴う処理をしたい場合などにマクロを定義する
* マクロの本体にシンタックスクオート`｀`をつけ、マクロの引数にアンクオート`~`をつけるのがまずは簡単な作り方

![スクリーンショット 2014-05-10 2.08.08.png](https://qiita-image-store.s3.amazonaws.com/0/40558/a40146d7-86cf-04ea-32d1-42d6f339eaec.png)

* マクロの展開結果を知りたいときは、`macroexpand-1`などを使う
* Light Tableのkeymapに`"ctrl-e" [(:eval.custom "(macroexpand-1 '__SELECTION__)")]`などを登録すると選択箇所のマクロ展開に便利

![スクリーンショット 2014-05-10 2.16.53.png](https://qiita-image-store.s3.amazonaws.com/0/40558/48a0b81b-4b41-9e46-77b1-2ca83f7a5988.png)

* マクロ本体で変数を使う場合、変数名の後に`#`をつけてユニークな名前にする。（`gensym`される）
* スプライシングアンクオート`~@`を使うとリストが展開されてからアンクオートされる

![スクリーンショット 2014-05-10 3.05.44.png](https://qiita-image-store.s3.amazonaws.com/0/40558/35387247-a371-3ca8-76f9-437019a870ae.png)

# Leiningenの使用

* REPLの起動  
`lein repl`
    * `(doc map)`や`(source filter)`でドキュメントやソースを表示
    * Light Tableでソース見たいときはkeymapに`"alt-s" [(:eval.custom "(with-out-str (clojure.repl/source __SELECTION__))" {:verbatim true})]`などを登録すると便利
* プロジェクトの作成  
`lein new app myproject1`
    * lein new `テンプレート名` `プロジェクト名`の形式。`テンプレート名`は省略するとデフォルトのテンプレート（ライブラリ用？）が使用される。`app`はアプリケーション用
    * 生成されたproject.cljの`:dependencies`で依存するライブラリを記述（Maven, Clojarsリポジトリから自動ダウンロード）
* standalone.jarの作成  
`lein uberjar`
    * （Clojureのjarも含む）すべての依存ライブラリをまとめた単独実行可能なjarファイルを作成する
* ヘルプ  
`lein help`
`lein help new`
`lein help uberjar` ...

# よく使う関数
よく使う関数で説明をあまりしてないものはこんなところでしょうか。

1. apply
1. cond, if-let, when-let
1. some, every?
1. first, second, last
1. cons, concat, list* 
1. mapcat, map-indexed, keep-indexed
1. repeat, repeatedly, cycle
1. interleave, partition
1. identity, comp, partial
1. take, take-last, drop, drop-last

他にもよく使う関数あるけど、まず取っ掛かりとしてこれだけわかればClojureで簡単なプログラム書けるでしょう〜