純粋関数型言語と参照透過性

# 登場人物
**ワイ**・・・ワイ。
**ハスケル子**・・・インターンの中学生。[**こちらの記事**](https://qiita.com/jzmstrjp/items/11dcd3ec26027ff30214)を参照。

# 素直になったワイ
ワイ「なぁ、ハスケル子ちゃん」
ワイ「ちょっと教えてほしいことがあるんやけど」

ハスケル子「なんですか」

ワイ「ハスケル子ちゃんの好きな**Haskell**っていうのは」
ワイ「**純粋関数型言語**ってやつやんな？」

ハスケル子「そうですね」

ワイ「なんというか、よう分からへんねんけど」
ワイ「**純粋関数型言語**を使うと**何が嬉しいんか**、ワイに教えてくれへん？」

ハスケル子「嬉しいというか」
ハスケル子「**参照透過性が担保されてる**のはいいと思います」

ワイ「**たんぽ**・・・？」
ワイ「ああ、ワイも**20代の頃はずっと**仕事で**お刺身の上に**乗せとったわ」
ハスケル子「それは多分**タンポポ**ですね」

社長「（あれは**タンポポ**ちゃう、**食用菊**やで・・・）」

# 参照透過性 is 何
ワイ「その**参照透過性**って言葉、たまに見かけるけどどういう意味なん？」

ハスケル子「**参照**について**透過的**な**性質**です」

ワイ「**うん、せやな**」
ワイ「**それが分からへん**いう話なんやけど」

ハスケル子「じゃあまず、**参照**っていう言葉は」
> **変数`x`**は**`3`**という値を**参照している**

ハスケル子「みたいに使うじゃないですか」

ワイ「せやな」
ワイ「**参照**は何となく分かるわ」

ハスケル子「じゃあ次は**透過的**って言葉ですけど」
ハスケル子「**透過しちゃう**わけなので」
ハスケル子「まるで**目に見えない**」
ハスケル子「つまり**存在を意識しない**って感じです」

ワイ「ふむふむ」

ハスケル子「だから」
ハスケル子「**参照のことを意識せずに扱える**」
ハスケル子「ってことです」

ワイ「なるほどな・・・」
ワイ「ほんで、それは」
ワイ「**どういう意味かいな？**」

ハスケル子「・・・**チッ**」

ワイ「（**舌打ち！？**）」

ハスケル子「ええと、コードで説明したほうが早いですね」
ハスケル子「例えば」

```javascript:keruko.js
let x = 3;
```

ハスケル子「っていうように」
ハスケル子「**`x`**という変数に**`3`**を代入したとして」
ハスケル子「それを**100行後**に」

```javascript:keruko.js
func(x);
```

ハスケル子「みたいに使うってなったら」
ハスケル子「どんなことを意識しますか？」

ワイ「ええと」
> ワイ「さっきは**`x`**は**`3`**やったけど」
> ワイ「**100行ほど**色々あったから」
> ワイ「**`x`**は今どんな値を**参照**してんのかいな？」

ワイ「って思うな」
ワイ「その間の処理を追っかけんとな」

ハスケル子「そうですよね」
ハスケル子「でも**純粋関数型言語**では」
ハスケル子「**再代入という概念がない**ので」
ハスケル子「一度定義した値は**不変**です」

ワイ「ほええ」

ハスケル子「つまり」
ハスケル子「一度定義したら、常に**`x === 3`**です」

ワイ「なるほどな」
ワイ「**再代入が可能な言語**の場合は」
> ワイ「この変数**`x`**は、コンピュータ上の何処かに保存されとる**`3`**という値を**今は**参照しとる・・・」
> ワイ「しかし次に使うときに何を参照しとるかは分からへん・・・」

ワイ「ってなるけど」
ワイ「**そうやない**っちゅうことやな」

ハスケル子「はい」
ハスケル子「**`x`**はどこかにある値を**参照している**、と考えなくても」
ハスケル子「単に**`3`がそこにある**かのように扱えるんです」

ワイ「ふむふむ」

ハスケル子「なので」
ハスケル子「**参照のことを意識せずに扱える**ってことですね」

ワイ「ほええ」

ハスケル子「変数の値が**不変**だと、色々と**心配事が減る**んです」

ワイ「なんとなく分かるで」

> ワイ「何かの関数の**副作用**で」
ワイ「**知らんうち**に**`x`**の値が変わっとった！」

ワイ「っちゅうことが**ない**ってことやな？」

ハスケル子「そうです」
ハスケル子「そして、変数の値が**不変**であることによって」
ハスケル子「**関数**の**参照透過性**が担保されます」

ワイ「**関数**の**参照透過性**・・・」

ハスケル子「つまり」
ハスケル子「**同じ引数**を渡せば、**常に同じ値を返してくれる**んです」

ワイ「なるほどな」
ワイ「**関数外の変数**とか**場面**とかによって戻り値が変わったりせぇへん、ということか」
ワイ「それは扱いやすいかもな」

ワイ「でも・・・」
ワイ「逆に**場面によって処理を変えたい**場合はどうすんの？」
ワイ「例えば・・・」

```javascript:yametaro.js
let scene = "朝";

function aisatsu () {
  switch (scene) {
    case "朝": return "おはよう";
    case "夜": return "こんばんは";
  }
}

alert(aisatsu());
```

ワイ「みたいに、」
ワイ「場面によって挨拶を**出し分けたい**ときとか」

ハスケル子「その場合は」

```javascript:keruko.js
function aisatsu (scene) {
  switch (scene) {
    case "朝": return "おはよう";
    case "夜": return "こんばんは";
  }
}

alert(aisatsu("朝"));
```

ハスケル子「こんな感じにしますかね」

ワイ「おお」
ワイ「つまり」

> ワイ「さあ、あいさつをせえ！」
> ワイ「（今は**朝**やから、**おはよう**で頼むで？）」

ワイ「て感じやなくて、」

> ワイ「**朝のあいさつ**をせえ！」

ワイ「って**明示的**に指示する感じやな」

ハスケル子「そんな感じです」
ハスケル子「もしこの関数をテストするときとかも」
ハスケル子「朝と夜に2回テストしないでも」
ハスケル子「`朝`と`夜`という2つの引数を与えてテストしてみればいいだけなので」
ハスケル子「テストがしやすいです」

ワイ「なるほどな」

## まとめ

- 純粋関数型言語には
  - **再代入という概念がない**
  - 変数の値は不変
  - 関数は、引数が同じであれば常に同じ値を返す（**参照透過性**）

ワイ「↑ってことやね！」

ハスケル子「はい」


## でもちょっと気になるワイ

ワイ「でもさ」
ワイ「さっきの変数に、引数として`昼`を与えたらどうなんの？」

ハスケル子「私なら型を自作して`朝`と`夜`以外はブロックします」
ハスケル子「素のJSでは出来ませんけど」

ワイ「なるほどな（**型を自作？**）」
ワイ「でもその・・・」
ワイ「今は**朝**やから**`朝`**っていう引数を与える、っていうのはどうやって判断すんの・・・？」
ワイ「結局はどこかに**現在の場面**や**状態**みたいなもんを保存しとかなあかんのとちゃうん・・・？」
ワイ「それともワイ、勉強しすぎて頭がおかしくなってしまったん・・・？」

ハスケル子「この先は、実際にやめ太郎さん自身がコードを書いてみたほうが分かりやすいと思います」
ハスケル子「Haskellと似た文法でコードを書いてHTMLやJavaScriptに変換できる、」
ハスケル子「**Elm**っていう純粋関数型言語があるので」
ハスケル子「それを勉強してみたら色々と実感を持って理解できると思いますよ」

ワイ「**Elm**ちゃんか」
ワイ「聞いたことあるわ」
ワイ「さっそく明日にでもやってみるわ」
ワイ「おおきにやで」

**〜「[ワイのElmデビュー【前編】](https://qiita.com/jzmstrjp/items/eb6fd45fe6324906a71a)」に続く〜**