Clojure 頑張る

# 1. 関数
## 1-1. 匿名関数
JS でいうところの `x => x + 1` は、Clojure では `#(+ 1 %)` となり、`x => x % 2 === 0` は、`#((= 0 (rem % 2))` となる:

```clj
(map #(+ 1 %) [1 2 3]) ; => (2 3 4)
(filter #(= 0 (rem % 2)) [1 2 3]) ; => (2)
```

## 1-2. 関数合成 / 関数適用
`comp` で関数合成するもいいけど `as->` マクロで上から順に次々適用させていくので十分なことが多い。なお、引数位置がうまくそろうなら `->`, `->>` の方がよりコンサイス:

```clj
(def comped (comp 
  (partial reduce *)
  (partial map inc)))
(comped (range 3)) ; => 6

(as-> (range 3) input
  (map inc input)
  (reduce * input)) ; => 6

(->> (range 3)
  (map inc)
  (reduce *)) ; => 6
```

seq に関数をどんどん適用していく際は `transduce` も便利

```clj
(def xf (comp
  (map inc)
  (take 3)
))
(transduce xf + (range)) ; => 6
```

## 1-3. 再帰
アリティオーバロードによる関数定義は再帰と相性が良い:

```clj
(defn rprint
  ([]
      (rprint 5))
  ([num]
      (println num)
      (if (> num 0)
        (recur (dec num)))))
(rprint) ; => 5 4 3 2 1 0が順に出力
```


`loop` を使えば関数定義なしで再帰できる:

```clj
(loop [num 5]
  (println (str "now:" num))
  (if (> num 0)
    (recur (dec num)))) ; => 5 4 3 2 1 0が順に出力
```

# 2. データ構造
## 2-1. Map
Mapのキーは通常 keyword と呼ばれるのを使う。keyword はMapのゲッター関数にもなるというなかなかイカれた仕様があるので、Map のキーにするのに最適:

```clj
(def hmap {:id 1, :name "alice", :score 20})
(hmap :id) ; => 1
(:id hmap) ; => 1

(def hmaps [{:id 1} {:id 2} {:id 3}])
(map :id hmaps) ; => (1 2 3)
```

Map も map できる。(key value) のペアに mapper をかます:


```clj
(map identity {:one 1 :two 2}) ; ([:one 1] [:two 2])
```

## 2-2. volatile & atom
volatile は時々刻々変化する値を参照する。それに加え、並列性を意識した機能を持つのが atom。`swap!` はいわゆる cas(check and swap) なのでアトミックな操作となり並列性が担保される:

```clj
(def counter (volatile! 100))
@counter ;=> 100
(vswap! counter inc) ; => 101
(vreset! counter 0) ;=> 0
@counter ;=> 0

(def counter (atom 100))
@counter ;=> 100
(swap! counter inc) ; => 101
(reset! counter 0) ;=> 0
@counter ;=> 0
```


# 3. 構造化
## 3-1. 名前空間
通常ファイル冒頭に `ns` マクロで名前空間の宣言をするのでそこで利用する他の名前空間を列挙する。REPLとかでは、 `require` + `:as` とかで簡易にアクセスするのもあり。[便利なチートシート](https://gist.github.com/ghoseb/287710/)を読む

```REPLで利用.clj
(clojure.string/join " " (range 3)) ; => "0 1 2", 直接使う

(require '[clojure.string :as s])
(s/join " " (range 3)) ; => "0 1 2", alias で使う
```

```使われる側util.clj
(ns cl.util
    (:require [clojure.string :as s]))

(defn atjoin [x]
    (s/join "@" x))
```

```使う側core.clj
(ns cl.core
  (:require [cl.util :as util])
  (:gen-class))

(defn -main [& args]
 ; 略
)

(util/atjoin (range 3)) ; => "0@1@2"
```


# 4. Misc

## 4-1. Windows
**JRE**
JRE は Oracle サイトからインストーラをポチポチやるとインストールされる上、PATHに登録される。`java -version`で動作することを確認。

**leiningen**
PATHの通るところに、`lein.bat` を配置して `lein self-install` コマンドを打てば入るとのことだが、SSL証明書周りでエラーが出るというのがFAQ。エラーメッセージに対処策が書かれている（curlの設定をコマンドラインで変更）。`lein new app <name>` でプロジェクトを作って動作確認。

**VSCode&PlugIns**
エディタは VSCode をインストーラでポチポチやって終了。そして、 clojureVSCode というプラグインをインストールする。leiningen で作ったプロジェクトディレクトリを VSCode で開いて、clj な拡張子をダブルクリックすると勝手に REPL を起動して接続する（左下に接続中とかのステータスがでる）

**コーディング**
編集作業。コード片をREPLに送るのが基本だが、`Ctrl+Shift+P`で出現するコマンドパレットにおいて、`Clojure: Eval and Show`というコマンドを入力すれば、評価される。お好みでショートカットキーに登録。直近の式だけを評価する方法がない気がする。


# 参考
というか私の勉強ソース

- 文法速習: https://learnxinyminutes.com/docs/clojure/
- チートシート: https://clojure.org/api/cheatsheet
- 無料のボリューミーな入門書: [CLOJURE for the BRAVE and TRUE](https://www.braveclojure.com/clojure-for-the-brave-and-true/)