ClojureでYAML入門

# はじめに

ClojureもYAMLもはじめての人向けです。
MacにClojureの環境を作りつつ、実際にYAMLをパースしながら基本的な構文を学びたくてまとめました。

# Clojureのインストール

事前にHomebrewとJava8をインストールしておく必要があります。
Clojureのインストールは下記のコマンド一発です.

```bash
$ brew install leiningen
```
ターミナルで```lein repl```を実行してプロンプトが起動すればインストール完了。

あとで使うので空のプロジェクトを作っておきます。

```bash
$ lein new yaml-test
```

<参考> Clojure環境を導入（mac）
https://qiita.com/FumiIwase/items/228a9c8dfdfbcde02d92

# Visual Studio Codeのインストール

ここ (https://qiita.com/akiko-pusu/items/185f4fd8484ecd3b3243) とか、
ここ (https://www.karelie.net/install-vscode-mac/) を見ながらインストールしました。

# Clojure開発環境のセットアップ

VSCodeでClojureアプリを開発するための環境をセットアップします。
まずは、Calvaをインストール

https://marketplace.visualstudio.com/items?itemName=cospaia.clojure4vscode
から[install]をクリック。

さらにVSCodeを開いて[install]をクリック。
簡単でした。

VSCodeのコマンドラインからreplを起動します。

```bash
$ lein repl
nREPL server started on port 50584 on host 127.0.0.1 - nrepl://127.0.0.1:50584
REPL-y 0.3.7, nREPL 0.2.12
Clojure 1.8.0
Java HotSpot(TM) 64-Bit Server VM 1.8.0_192-b12
    Docs: (doc function-name-here)
          (find-doc "part-of-name-here")
  Source: (source function-name-here)
 Javadoc: (javadoc java-object-or-class-here)
    Exit: Control+D or (exit) or (quit)
 Results: Stored in vars *1, *2, *3, an exception in *e

user=>
```

起動したら、```Ctrl+Alt+V C```で接続します。
replのポートが入っているのでそのまま[Return]でOK。

<img width="635" alt="Screen Shot 2018-10-30 at 11.01.34.png" src="https://qiita-image-store.s3.amazonaws.com/0/24592/45d14aa4-f967-16eb-e31b-457e805717b2.png">

```Ctrl+Alt+V C```で、もしコマンドが無いというエラーが出てきたら、Clojureのプロジェクトがちゃんとロードできていないみたいです。下記のようにVSCodeを開き直したらうまくいきました。

```bash
$ code project.clj .
```

左下にこんなのが出てたら成功です。

<img width="106" alt="Screen Shot 2018-10-30 at 11.13.27.png" src="https://qiita-image-store.s3.amazonaws.com/0/24592/454b1535-2437-cfa8-d0b5-e074a2ca3d1e.png">

試しに下記のようなコードを追加して

```clojure
(+ 1 3 )
```
コードを選択した状態で```ctrl+alt+v e```を押すと下記のようになります。
ちなみに、ファイルをセーブしないと出ませんでした（ちょっとはまりました）

<img width="141" alt="Screen Shot 2018-10-30 at 11.20.36.png" src="https://qiita-image-store.s3.amazonaws.com/0/24592/d2c29fd5-ef6d-ee95-60d5-7db47d98d944.png">

<参考>VSCodeの拡張：CalvaでClojureの開発環境を整える
https://qiita.com/frost_star/items/4475acaeff84badbf3f7

なお、VSCodeのClojure開発環境をググるとclojureVSCodeがヒットしたのでこれも試してみましたが、下記のエラーが出るのであきらめました。もしかしたら、VSCode開き直しで動いたのかも。

<img width="502" alt="Screen Shot 2018-10-30 at 10.22.39.png" src="https://qiita-image-store.s3.amazonaws.com/0/24592/f1224c62-9812-3215-3f9c-eb4677ba4cd0.png">

Clojure Development with Visual Studio Code
https://spin.atomicobject.com/2017/06/22/clojure-development-with-visual-studio-code/

clojureVSCode
https://marketplace.visualstudio.com/items?itemName=avli.clojure

# clj-yamlの導入

いよいよYAML Parserを使ってみます。
clj-yamlはMaven artifactとして使えるので、まずはproject.cljに依存ライブラリとして追加します。```[circleci/clj-yaml "0.5.6"]```の箇所です。
ついでに最終行の```:main yaml-test.core/-main```も追加しておきました。

```clojure:project.clj
(defproject yaml-test "0.1.0-SNAPSHOT"
  :description "FIXME: write description"
  :url "http://example.com/FIXME"
  :license {:name "Eclipse Public License"
            :url "http://www.eclipse.org/legal/epl-v10.html"}
  :dependencies [[org.clojure/clojure "1.8.0"]
                 [circleci/clj-yaml "0.5.6"]]
  :repl {:plugins [[cider/cider-nrepl "0.18.0"]]
          :dependencies [[nrepl "0.4.5"]]}
  :main yaml-test.core/-main)
```

ファイルを保存したあとターミナルから```lein deps```を実行しておきます。

```bash
$ lein deps
```

次にmain関数を作成します。```:require```でclj-yaml.coreを```yaml```で参照できるようにして、```yaml/generate-string```でYAMLフォーマットの文字列を生成してみます。

```clojure:core.clj
(ns yaml-test.core
  (:require [clj-yaml.core :as yaml] ))

(defn -main []
  (println
    (yaml/generate-string
     [{:name "John Smith", :age 33}
      {:name "Mary Smith", :age 27}])
  )
)
```

```lein run```で下記のように出力されたら成功です。

```bash
$ lein run
- {name: John Smith, age: 33}
- {name: Mary Smith, age: 27}
```

次は逆にYAMLをClojureアプリに取り込んでみます。

```clojure:core.clj
(ns yaml-test.core
  (:require [clj-yaml.core :as yaml] ))

(defn -main []
  (println
   (yaml/parse-string "
- {name: John Smith, age: 33}
- name: Mary Smith
  age: 27
  ")
  )
)
```

実行します。

```bash
$ lein run
(#ordered/map ([:name John Smith] [:age 33]) #ordered/map ([:name Mary Smith] [:age 27]))
```

# YAMLの動作確認

いろいろなYAMLをパースしてみました。

```clojure:core.clj
(ns yaml-test.core
  (:require [clj-yaml.core :as yaml] ))

(defn -main []
  (print "---\n【配列】\n")
  (println (pr-str (yaml/parse-string "
- aaa
- bbb
- ccc
  ")))

  (print "---\n【ハッシュ】\n")
  (println (pr-str (yaml/parse-string "
A: aaa
B: bbb
C: ccc
  ")))

  (print "---\n【ハッシュのネスト】\n")
  (println (pr-str (yaml/parse-string "
A: aaa
B: 
  B1: bbb1
  B1: bbb2
C: ccc
  ")))

  (print "---\n【フロースタイル】\n")
(println (pr-str (yaml/parse-string "
{ A: aaa, B: bbb, C: ccc }
  ")))

  (print "---\n【コメント】\n")
(println (pr-str (yaml/parse-string "
# コメント行
A: aaa
B: bbb
C: ccc
  ")))  

  (print "---\n【複数行の文字列】\n")
(println (pr-str (yaml/parse-string "
text: |-
  aaa
  bbb
  ccc
  
  
  ")))

  (print "---\n【アンカーとエイリアス】\n")
(println (pr-str (yaml/parse-string "
- &mark foo
- bar
- *mark
- *mark
  ")))
  
  (print "---\n【ハッシュのマージ】\n")
(println (pr-str (yaml/parse-string "
base: &base
  A: aaa
  B: bbb
Sample1:
  <<: *base
  C: ccc1
Sample2:
  <<: *base
  C: ccc2
  ")))

)
```

結果はこんな感じ

```bash
$lein run
---
【配列】
("aaa" "bbb" "ccc")
---
【ハッシュ】
#ordered/map ([:A "aaa"] [:B "bbb"] [:C "ccc"])
---
【ハッシュのネスト】
#ordered/map ([:A "aaa"] [:B #ordered/map ([:B1 "bbb2"])] [:C "ccc"])
---
【フロースタイル】
#ordered/map ([:A "aaa"] [:B "bbb"] [:C "ccc"])
---
【コメント】
#ordered/map ([:A "aaa"] [:B "bbb"] [:C "ccc"])
---
【複数行の文字列】
#ordered/map ([:text "aaa\nbbb\nccc"])
---
【アンカーとエイリアス】
("foo" "bar" "foo" "foo")
---
【ハッシュのマージ】
#ordered/map ([:base #ordered/map ([:A "aaa"] [:B "bbb"])] [:Sample1 #ordered/map ([:A "aaa"] [:B "bbb"] [:C "ccc1"])] [:Sample2 #ordered/map ([:A "aaa"] [:B "bbb"] [:C "ccc2"])])
```

アンカーとエイリアス、ハッシュのマージなんかはYAMLで設定ファイルを書くときに便利そうです。

<参考>
プログラマーのための YAML 入門 (初級編)
https://magazine.rubyist.net/articles/0009/0009-YAML.html

YAML 基本記法まとめ
https://qiita.com/tfrcm/items/5f8e4c5795ce41b214d1

# おわりに

YAMLの勉強のついでにClojureも勉強しようと思ってやってみましたが、Clojure面白いですね。
replを使えば簡単に実行できるし、関数型プログラミングを学ぶのに良い気がしてきました。
今度はClojureでWebアプリを作ってみたいです。