JavaScriptとElmを比べてみた〜前編〜

**Elm**は、JavaScriptにコンパイルできる言語、いわゆる**altJS**です。


## 変数宣言（のようなもの）
### JavaScriptの場合
```javascript
const a = 1;
let b = 1;
var c = 1;
```

ワイ「`const`は**定数**いうて**再代入できひん**やつやな」

### Elmの場合
```elm
a = 1
```

ワイ「`const`も`let`も`var`も無いねんな」

ハスケル子「はい」
ハスケル子「デフォルトで**再代入不可**です」
ハスケル子「つまり**不変**なので、**変数**ですらなくて」
ハスケル子「ただ値に**命名**している、値を**定義**しているって感じですね」
ハスケル子「あとセミコロンも要りません」

ワイ「再代入はできなくても、JSのconstみたいに」
ワイ「**オブジェクトのプロパティ**を一部変更することはできんねやろ？」

ハスケル子「いえ、オブジェクトのプロパティ・・・」
ハスケル子「というかElmでは**レコード**の**フィールド**ですね」
ハスケル子「フィールドも**上書きできません**[^1]」
ハスケル子「**全ての値が不変です**」

ワイ「へぇぇ・・・」

## 関数の定義

### JavaScriptの場合
```javascript
function add (a, b) {
  return a + b;
}
```

または

```javascript
const add = function (a, b) {
  return a + b;
}
```

アロー関数式で書くと↓

```javascript
const add = (a, b) => a + b;
```

### Elmの場合

```elm
add a b =
    a + b
```

ワイ「**Elm**では**カッコもカンマも無い**んやな」
ワイ「さらに**returnも書かへん**ねやな」

ハスケル子「はい」
ハスケル子「関数の**最後に評価された値**が自動的に戻り値になります」

ワイ「そもそも`function`とかいうのも無いんやな」
ワイ「**変数とほぼおんなじ**やん」

ハスケル子「そうですね」
ハスケル子「**引数があれば関数**って感じです」

## 関数の実行（適用）

### JavaScriptの場合
```javascript
const result = add(3, 5);
```

### Elmの場合
```elm
result = add 3 5
```

ワイ「関数を適用するにも**カッコもカンマも無し**なんや」

ハスケル子「はい」
ハスケル子「ただ、`add`関数の結果を**更に別の関数に渡したい**ときなんかは───」

```elm
result = anotherFunc add 3 5
```

ハスケル子「───と書くと」
ハスケル子「`anotherFunc`関数に対して、`add`と`3`と`5`という」
ハスケル子「3つの引数を渡してる感じになっちゃうので」

```elm
result = anotherFunc (add 3 5)
```

ハスケル子「↑こうすると、カッコで囲まれた部分が先に実行されます」

ワイ「なるほどな」
ワイ「`add 3 5`の計算結果、つまり`8`が」
ワイ「`anotherFunc`関数の引数として渡される感じか」

ハスケル子「はい」
ハスケル子「または───」

```elm
result = anotherFunc <| add 3 5
```

ハスケル子「───こう書いても同じです」

ワイ「あー、**パイプライン**いうやつやね」
ワイ「これ読みやすくて好きやわ」

## 書く順序による影響

### JavaScriptの場合

```javascript
const a = 3;
const b = 5;
const c = a + b;
```

ワイ「基本、上から順に実行って感じよな」

ハスケル子「はい」
ハスケル子「なので例えば───」

```javascript
const c = a + b;
const a = 3;
const b = 5;
```

ハスケル子「───こんな感じで」
ハスケル子「`a`や`b`に値を代入するより上の行で」
ハスケル子「`a`や`b`を使った計算などをしようとすると」
ハスケル子「エラーになっちゃいますよね」

ワイ「なるほどな」
ワイ「でもまあ、それは普通そうやろ」

ハスケル子「それが**Elmの場合は違う**んですよ」

### Elmの場合
```elm
c = a + b
a = 3
b = 5
```

ハスケル子「↑これも**普通にOKです**」

ワイ「ええ・・・」
ワイ「`a`や`b`を**定義するより上の行**で」
ワイ「`a`や`b`を計算に使ってるやん・・・」

ハスケル子「はい」
ハスケル子「**関数と同じ感じ**なんですよ」

ワイ「ああ・・・」
ワイ「JSでも関数はそうやもんな」
ワイ「下の方で宣言した関数、上の方で使えるもんな」

ハスケル子「はい」
ハスケル子「Elmでは**全ての値が不変**なので、それが可能なんです」

ワイ「全ての値が不変・・・つまり**再代入という概念が存在しない**ということやろ？」
ワイ「それやと順番が関係なくなるの？」
ワイ「なんで・・・？」

![haskellko2.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295452/9d459448-b6c0-b947-a018-bd34aea4e003.jpeg)

ハスケル子「JSの場合は───」

```javascript
let a = 3;
console.log(a);
// 3 と表示。

a = 5;
console.log(a);
// 5 と表示。
```

ハスケル子「`let a = 3;`って書いて」
ハスケル子「そのすぐ下の行で`a`を呼び出したら、`a`の値は`3`だけど」
ハスケル子「その後、`a = 5;`って再代入して」
ハスケル子「その下の行で`a`を呼び出したら、`a`の値は`5`」

ワイ「それは分かるわ」
ワイ「**当然の時間の流れ**や」

ハスケル子「でも再代入という概念がないとしたらどうですか？」

ワイ「ああ・・・」
ワイ「再代入できひんなら、`a`はいつでも`3`や」
ワイ「`a`の**状態が変わることが無い**から」
ワイ「`a`を`5`に変えた**後に**呼び出したらどうこう・・・」
ワイ「みたいな話がそもそも**あり得へん**わけやな」

ハスケル子「そうです」
ハスケル子「全ての値が不変で」
ハスケル子「**時間が止まってる**ようなものなので」
ハスケル子「コードの中に**前とか後とか無い**イメージです」

ワイ「なるほどなー」
ワイ「時が止まってるような」
ワイ「1フレームの中で全てが実行されているような」
ワイ「不思議な感じやな」
ワイ「**スタープラチナ・ザ・ワールド**みたいやな」

ハスケル子「**オラオラオラオラ！**って感じです」

ワイ「**痛い！痛い！**」
ワイ「やめてぇや」

ワイ「ええと、つまり」
ワイ「時間が止まっとるようなもんやから」
ワイ「値の定義より上の行で、その値を使っても」
ワイ「問題ないんやな」

ハスケル子「そんな感じです」

ワイ「でも、なんの値も変えられなくて」
ワイ「この言語、何ができるの・・・？」

ハスケル子「普通に**シングルページアプリケーション**とか」
ハスケル子「**[動きのあるゲーム](https://ellie-app.com/5RRP5mfVr8Ha1)**だって作れますよ」

ワイ「**えぇ・・・！？**」
ワイ「全て不変のはずやのに**ボール動いてますやん・・・！**」
ワイ「言うてることちゃいますやん・・・！」

ハスケル子「気になるなら**[Elm Guide](https://guide.elm-lang.jp/)**読んでみてください」

ハスケル子「じゃあ」
ハスケル子「次は**オブジェクト**とか**イベントハンドラ**について比べてみましょう」

**〜後編に続く〜**

## 後編も書いたで！
### → [JavaScriptとElmを比べてみた〜後編・Vue.jsとも比べてみた〜](https://qiita.com/Yametaro/items/005a854a2e86e22bb036)

[^1]: 詳しくは後編にて。