ｱﾅﾌｫﾘｯｸなこふ語ｼﾞｪﾈﾚｰﾀっ

この記事は [こふ語 / ブチミリ Advent Calendar 2016](http://www.adventar.org/calendars/1478) の20日目の記事ですっ
ちなみにこふ語カレンダーは初投稿ですっ

# ｱﾅﾌｫﾘｯｸｯ

突然ですがっ **ｱﾅﾌｫﾘｯｸ** ないし **ｱﾅﾌｫﾗ** とは何でしょうかっ！！皆大好き weblio ｾﾝｾに聞いてみましょうっ

> 1. 【修辞】 首句反復 《連続した節や語句の初めに同じ語[表現]を反復すること》.
> 2. 【文法】 前方照応.
>
> [anaphoraの意味](http://ejje.weblio.jp/content/anaphora) - Weblio

2つの意味がありますがっ今回はコードを書くので意味的には前方照応ということになるでしょうかっ

> 〘言〙 〔anaphora〕 代名詞や冠詞が文中や文章中（発話中）の物事をさすこと。先に現れた物事なら前方照応，後に出てくる物事ならば後方照応という。
> [前方照応の意味](http://www.weblio.jp/content/%E7%85%A7%E5%BF%9C) - Weblio

## 仕組みっ

実際に書いてみましょうっ

```clj
(defmacro anakov
  [& body]
  `(let [~'ｱﾝｯ! "ｱﾝｯ!"])
    ~@body)

(println (anakov (take 4 (repeat ｱﾝｯ!)))) ; 実行すると…(ｱﾝｯ! ｱﾝｯ! ｱﾝｯ! ｱﾝｯ!)
```

どうして外側のスコープで `ｱﾝｯ!` が参照できているか説明していきますっ 実はマクロに body として渡したコードは展開時に `anakov` と同じスコープに入るのですがっ その時に body の展開と同時に let のベクタの中にある `~'ｱﾝｯ!` も unquote されて実行する段階で `ｱﾝｯ!` というシンボルが出来上がるのですっ なのでっ let のベクタの中の unquote と body に渡している `ｱﾝｯ!` の解決がマクロ展開時に行われっ 外側でそのシンボルを使っても問題なく振る舞われるということなのですっ 今回はっ この振る舞いを利用して簡単なこふ語ジェネレータっぽいマクロを組んでみようと思いますっ！！

## ﾚｯﾕﾄﾔｲｯ!!

```clj
(defmacro anakov
  [& body]
  `(let [~'ｱﾝｯ! "ｱﾝｯ!"
         ~'ｺﾞｸｯ! "ｺﾞｸｯ!"
         ~'ｼｭｯ! "ｼｭｯ!"
         ~'ｽﾞﾌﾞｯ! "ｽﾞﾌﾞｯ!"
         ~'ﾄﾞﾋﾟｭ "ﾄﾞﾋﾟｭ"
         ~'ﾙ "ﾙ"
         ~'ﾓｸﾞｯ! "ﾓｸﾞｯ"
         ~'ﾌﾞﾘｯ! "ﾌﾞﾘｯ!"]
    ~@body))

(println (anakov (take 4 (repeat ｱﾝｯ!)))) ; => (ｱﾝｯ! ｱﾝｯ! ｱﾝｯ! ｱﾝｯ!)
(println (anakov (take 4 (repeat ｺﾞｸｯ!)))) ; => (ｺﾞｸｯ! ｺﾞｸｯ! ｺﾞｸｯ! ｺﾞｸｯ!)
(println (anakov (take 4 (repeat ﾓｸﾞｯ!)))) ; => (ﾓｸﾞｯ! ﾓｸﾞｯ! ﾓｸﾞｯ! ﾓｸﾞｯ!)
(println (anakov (take 4 (repeat ﾌﾞﾘｯ!)))) ; => (ﾌﾞﾘｯ! ﾌﾞﾘｯ! ﾌﾞﾘｯ! ﾌﾞﾘｯ!)
(println (anakov (cons ﾄﾞﾋﾟｭｯ (take 10 (repeat ﾙ))))) ; => (ﾄﾞﾋﾟｭ ﾙ ﾙ ﾙ ﾙ ﾙ ﾙ ﾙ ﾙ ﾙ ﾙ)
```

一応動きますがっ `take` とか `repeat` とかを外側で何度も書く必要があって使いにくいですねっ ではっ これらをマクロに閉じ込めてしまいましょうっ

```clj
(defmacro anakov
  [& body]
  (let [f #(take (if (pos? %1) %1 4) (repeat %2))] ; 負数でシーケンスは作れないので念の為っ
    `(let [~'ｱﾝｯ! #(~f % "ｱﾝｯ!")
           ~'ｺﾞｸｯ! #(~f % "ｺﾞｸｯ!")
           ~'ｼｭｯ! #(~f % "ｼｭｯ!")
           ~'ｽﾞﾌﾞｯ! #(~f % "ｽﾞﾌﾞｯ!")
           ~'ﾄﾞﾋﾟｭ "ﾄﾞﾋﾟｭ"
           ~'ﾙ #(~f % "ﾙ")
           ~'ﾓｸﾞｯ! #(~f % "ﾓｸﾞｯ!")
           ~'ﾌﾞﾘｯ! #(~f % "ﾌﾞﾘｯ!")]
      ~@body)))

(println (anakov (ｱﾝｯ! 4))) ; => (ｱﾝｯ! ｱﾝｯ! ｱﾝｯ! ｱﾝｯ!)
(println (anakov (ｺﾞｸｯ! 4))) ; => (ｺﾞｸｯ! ｺﾞｸｯ! ｺﾞｸｯ! ｺﾞｸｯ!)
(println (anakov (ﾓｸﾞｯ! 4))) ; => (ﾓｸﾞｯ! ﾓｸﾞｯ! ﾓｸﾞｯ! ﾓｸﾞｯ!)
(println (anakov (ﾌﾞﾘｯ! 4))) ; => (ﾌﾞﾘｯ! ﾌﾞﾘｯ! ﾌﾞﾘｯ! ﾌﾞﾘｯ!)
(println (anakov (cons (ﾄﾞﾋﾟｭ 1) (ﾙ 10)))) ; => (ﾄﾞﾋﾟｭ ﾙ ﾙ ﾙ ﾙ ﾙ ﾙ ﾙ ﾙ ﾙ ﾙ)
```

おっ いい感じになってきましたっ 次は括弧を取ってちゃんと文字列にしてみましょうっ

```clj
(ns anakov.core
  (:require [clojure.string :refer [join]]))

(defmacro anakov
  [& body]
  (let [f #(take (if (pos? %1) %1 4) (repeat %2))] ; 負数でシーケンスは作れないので念の為っ
    `(let [~'ｱﾝｯ! #(~f % "ｱﾝｯ!")
           ~'ｺﾞｸｯ! #(~f % "ｺﾞｸｯ!")
           ~'ｼｭｯ! #(~f % "ｼｭｯ!")
           ~'ｽﾞﾌﾞｯ! #(~f % "ｽﾞﾌﾞｯ!")
           ~'ﾄﾞﾋﾟｭ "ﾄﾞﾋﾟｭ"
           ~'ﾙ #(~f % "ﾙ")
           ~'ﾓｸﾞｯ! #(~f % "ﾓｸﾞｯ!")
           ~'ﾌﾞﾘｯ! #(~f % "ﾌﾞﾘｯ!")]
      (join ~@body))))

(println (anakov (ｱﾝｯ! 4))) ; => ｱﾝｯ!ｱﾝｯ!ｱﾝｯ!ｱﾝｯ!
(println (anakov (ｺﾞｸｯ! 4))) ; => ｺﾞｸｯ!ｺﾞｸｯ!ｺﾞｸｯ!ｺﾞｸｯ!
(println (anakov (ﾓｸﾞｯ! 4))) ; => ﾓｸﾞｯ!ﾓｸﾞｯ!ﾓｸﾞｯ!ﾓｸﾞｯ!
(println (anakov (ﾌﾞﾘｯ! 4))) ; => ﾌﾞﾘｯ!ﾌﾞﾘｯ!ﾌﾞﾘｯ!ﾌﾞﾘｯ!
(println (str (anakov (cons ﾄﾞﾋﾟｭ (ﾙ 10))) "ｯ!")) ; => ﾄﾞﾋﾟｭﾙﾙﾙﾙﾙﾙﾙﾙﾙﾙｯ!
```

わおっ シンボル並べるだけでこふ語が作れてしまいましたっ

### でも気をつけてっ

一見便利だったり面白そうだったりするｱﾅﾌｫﾘｯｸﾏｸﾛですがっ let のスコープを用いるということはつまりっ より外側に同じ名前のシンボルがある場合はその参照を覆い隠してしまいますっ このことを**シャドウイング**と言いますっ 普通にコードを書く限りは意識もしない落とし穴ですがっ マクロを書く必要が出てきた時には気をつけてくださいっ(もちろん対処法はちゃんとあるのですがっ この記事では触れませんっ ｸﾞｸﾞｯﾃｯ!!)

以上になりますっ それではみなさんよいお年をっ