Kotlinは何故便利なのか

## この投稿をした経緯

https://qiita.com/ngsmvn/items/b74328291d0b5342e407

長すぎ、読みたくないという人は、それぞれの節にまとめを付けているので、それだけでも趣旨は分かると思います。

## 何故Kotlinは便利なのか

何故Kotlinは便利なのかを一言でまとめると、**他の言語のいいとこどりをしているから**だと思います。

Kotlin in ActionというKotlinの開発者が書いた本にこうあります。

>We aren’t trying to advance the state of the art in programming language design and explore innovative ideas in computer science. Instead, whenever possible, we’re relying on features and solutions that have already appeared in other programming languages and have proven to be successful.

(拙訳)
>私たちは、プログラミング言語の技術水準をあげようとか、コンピューターサイエンスの革新的なアイディアについて探求しようとかしているわけではありません。その代わりに、他のプログラミング言語に既にあり、上手くいくことが分かっている機能や解決策に出来る限り頼っています。

実用的であること、既存のプログラミング言語の良い点を積極的に取り入れようとしていることがよく分かると思います。

## 具体的に便利な点

これ以外にも色々あると思いますが、以下の3点に絞ってまとめてみます。

1. 静的型付けなのに「柔軟」かつ「簡潔」
2. 関数型言語から取り入れた「参照透過性」
3. JVM(後述)で動くので「write once, run everywhere」

## 動的型付け言語の「簡潔さ」と「柔軟性」

この節のまとめ:静的型付け言語は、プログラムについての情報をたくさんコンピューターにあげるので、プログラムのミスが早く見つかる。その代わりに書くのがめんどくさい。Kotlinは静的型付け言語なのに簡潔かつ柔軟に書ける言語

JavaScriptやPHPで書いたプログラムが動かないと思ったら、タイプミスをしていただけだった、という経験はありませんか?単純なミスは、コンピューターが見つけてくれたら楽ですよね。

スペルミス・データの種類が違うなどのミスを、実行前に見つけてくれる言語を静的型付け言語と言います。逆にJavaScriptやPHPは動的型付け言語と呼ばれます。この二つは型(データの種類)がいつ決まるかが違います。

- 動的→プログラムを実行する時に決まる
    - データの矛盾を実行前に見つけられない
- 静的→プログラムを実行する前に決まる
    - データの矛盾を実行前に見つけられる

ミスを見つけてくれるんだったら、いつも静的型付け言語を使えばいいじゃんと思いますよね?ところがそうはいかないんです。文字列を出力するプログラムを比べてみます。

- JavaScript(動的型付け)

```JavaScript
alert("JavaScript");
```

- PHP(動的型付け)

```PHP
echo "PHP";
```

- Java(静的型付け)

```Java
public class Main {
    public static void main(String[] args){
        System.out.println("Java");
    }
}
```

単純に文字列を表示するだけなのに、これだけ書く必要があります。
静的型付け言語・動的型付け言語それぞれにメリットとデメリットがあります。

![コメント 2019-12-03 154004.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227939/6fdcebde-446b-f7c7-bc2c-2e5b0d6c540f.png)


簡潔かつ柔軟に書ける静的型付け言語があれば最強ですね。それはつまり、Kotlinが最強ということです。

```Kotlin
fun main() = println("Kotlin") //静的型付けなのに簡潔に書ける!!
```

他のプログラミング言語の失敗に学び、いい点に学んだ結果、既存の動的型付け言語に負けないくらい簡潔に書けるようになっています。

Kotlinには簡潔かつ柔軟に書くための機能がいっぱいあります。**紹介しきれないので、ググってください**

Qiitaにいい記事があります。(投げやり)

- 型推論
- 拡張関数
- ローカル関数
- スコープ関数
- 中置関数(infix)
- ローカルリターン
- デフォルト引数
- 名前付き引数
- データクラス
- リストに対する処理(sumBy, groupBy, fold, first, drop...)
- 高階関数

## 関数型言語の「参照透過性」

この節のまとめ:色々値が変わると、考えることが増えて大変。関数型言語やその仕組みを真似しているKotlinは値をあえて書き換えられない書き方ができる

参照透過性とは、入力が同じなら、関数の実行結果が同じになるという性質です。当たり前のことだと思いましたか?では、以下の例を考えてみてください。

自動販売機に1000円札を入れて、100円のコーヒーのボタンを押したとします。出てくる商品とおつりは、いつも同じですか?
![自販機](https://3.bp.blogspot.com/-CGjU9gYp1LY/V3o2fXLCuzI/AAAAAAAA8HE/SovGs2dke-EWICh2sX--HlBRkyMbhryAACLcB/s400/machine_jidouhanbaiki.png)

売り切れていたらコーヒーは出てきませんし、おつりも500円玉と100円玉だったり、全部100円玉だったりしますよね。この例をプログラムに置き換えると

- 1000円札を入れる→入力
- ボタンを押す→関数呼び出し
- 出てくるおつりと商品→出力
- **自販機に入っている商品と小銭→状態**

この例で伝えたかったのは、**状態が変わると、出力が変わってしまう**ということです。いちいち状態のことを考えながらプログラミングするのはめんどくさいです。そもそも、状態が変わらなければこんなことを考える必要はありません。

なので、純粋な関数型言語では、オブジェクトの状態を書き換えないことで参照透過性を実現しています。

例えばHaskellだとこんなことはできません。(疑似コードなので、ちゃんとしたHaskellではないです。)

```Haskell
--使えるプログラミング言語のリスト
let skillSet = ["JavaScript", "PHP"]
--勉強会に参加したので、Kotlinが使えるようになった
skillSet push "Kotlin" --←リストへの追加はできない
for (let i = 0; i < skillSet size; i++){ --←ループ変数を1ずつ増やすこともできない
    --使えるプログラミング言語の自慢をする
    putStrLn skillSet !! i ++ "が使えるよ!!"
}
--しばらくコードを書かなかったので、全部忘れた
skillSet = [] --←再代入もできない。というか、代入と呼ばずに束縛と呼ぶ
--
```

Kotlinはこの考え方を部分的に取り入れて、書き換えができるオブジェクト(mutable object)とできないオブジェクト(immutable object)を区別しています。

- 動く

```Kotlin
//使えるプログラミング言語のリスト
var skillSet = mutableListOf("JavaScript", "PHP") //mutableなリストを、再代入ができる変数に代入
//勉強会に参加したので、Kotlinが使えるようになった
skillSet.add("Kotlin")
for (i in 0 until skillSet.size){
    //使えるプログラミング言語の自慢をする
    println("${skillSet[i]}が使えるよ")
}
//しばらくコードを書かなかったので、全部忘れた
skillSet = mutableListOf()
```

- 動かない

```Kotlin
//使えるプログラミング言語のリスト
val skillSet = listOf("JavaScript", "PHP") //immutableなリストを、再代入ができない変数に代入
//勉強会に参加したので、Kotlinが使えるようになった
skillSet.add("Kotlin") //←これはできない
for (i in 0 until skillSet.size){
    //使えるプログラミング言語の自慢をする
    println("${skillSet[i]}が使えるよ")
}
//しばらくコードを書かなかったので、全部忘れた
skillSet = listOf() //←これもできない
```

参照透過性以外にも、高階関数やリストに対する操作などで関数型言語の影響を受けているようです。

## Javaの「write once, run everywhere(一度書いたら、どこでも動く)」

この節のまとめ:JavaはOSを選ばずに実行できるし、Javaの仕組みを真似しているKotlinも同じ。

### コンパイラ言語とインタプレタ言語

KotlinはJavaという言語に強く影響を受けています。どうしてKotlinがすごいのかを説明するためには、Javaがどうしてすごいのかを説明する必要があります。ちょっと遠回りをしますが、最後にはKotlinの話につながるので、ついてきてください。

プログラミング言語には大きく分けて2種類あります。コンパイラ言語とインタプレタ言語です。

どこで聞いた比喩なのか覚えていないのですが、プログラマはコンピューターにお手紙を書くのがお仕事みたいなものです。

![](http://4.bp.blogspot.com/-piPWJlRYOIo/UUhH7Pfy1rI/AAAAAAAAO5k/4JfvOTxND24/s180-c/mail.png)

「Webページを見せてください」「データベースの値を見せてください」「メールをあの人に送ってください」色々なお願い事があると思いますが、そのお願いを手紙に書いてコンピューターに送ります。その手紙がプログラムで、プログラムを書くのに使う言葉がプログラミング言語です。

コンピューターはプログラミング言語が分かりません。コンピューターが分かるのは、電流のON/OFFだけです。ON/OFFを数字の0と1で表した、コンピューターに分かる言葉を機械語と言います。

コンピューターにお手紙を読んでもらう(=プログラムを実行してもらう)には、大きく二つ方法があります。

1. 前もってお手紙を全部機械語に翻訳してから送る
2. コンピューターが読む隣で、一行ずつ意味を説明してあげる


前者でお手紙を書くのがコンパイラ言語、後者がインタプレタ言語です。

コンパイラ言語は実行速度が速い、お手紙を他の人に真似される心配が少ない(人間は機械語が分からないので)などのメリットがありますが、困ったことがあります。

### お手紙がOSに依存してしまう

Java以前のコンパイラ言語では、プログラムがOSに依存してしまっていました。OSに依存というのは、OS毎に開発・テストをする必要があったということです。そもそもOSは何のためにあるのでしょうか

コンピューターが処理を行うには、(当然ですが)自分自身のハードを使う必要があります。「ディスクのこの位置に保存しておいたファイルを表示して」みたいに、ハードについて細かくプログラムに書く必要があるとします。コンピューターを買い換えたり、自分のプログラムを友達のコンピューターで実行したりしたいときにどうなるでしょうか。

当然、コンピューターの設計も部品も違うので、プログラムを書き直しです。めんどくさいですよね。

直接プログラマが触る必要がないように、コンピューターのハードへのアクセスを代行してくれるのがOSです。OSがあるおかげでハードに対して直接プログラムする必要がありません。

ソフトが「OS君、ハードに良い感じにアクセスしてよ」というお願いをする窓口をAPIと言います。OS毎にAPIが違うので、OSが違うとプログラムも変わってしまいます。ハードに直接アクセスするよりは楽ですが、OS間の違いに対応するめんどくささは残っています。

そのめんどくささを解決したのがJavaの仮想マシン(JVM)です。

### JVM

JVMとは、Java仮想マシンです。Javaの実行環境として動く仮想マシンです。仮想マシンとは、本物のコンピューターのハードを使ってコンピューターの振りをするソフトです。JVM以外にもいろんな種類があります。

JVMはJavaプログラムにAPIを提供しています。このAPIはあえて各種OSに共通する機能のみに絞ってあります。

前述のお手紙の例えでいうと、Javaでお手紙を書くと機械語ではなく中間言語というJVMが分かる言語に置き換わります。JVMが搭載されているOSに応じて良い感じに機械語に直してくれます。

ソフトが直接ハードに触るのではなく、OSを経由することでハードの違いを吸収することができました。それと同じように、直接OSにアクセスするのではなくJVMを経由することで、OSの違いを吸収することができます。

これがJavaを作ったSun Microsystemsが提唱していた「write once, run everywhere(一度書いたらどこでも動く)」です。一度書いたら、OSの違いを意識する必要なしでプログラムを使えます。これでもう、めんどくさくないですね...とはなりませんでした。

実行環境としてのJavaは優れていますが、プログラミング言語としてのJavaは長ったらしい構文でとてもめんどくさいものでした。

「こんなんでIDE作れるか!」と嫌になったチェコにある会社がJVMで動く近代的なプログラミング言語を作りました。それがKotlinです。「write once, run everywhere」を実現するJVMのいいとこどりをしたわけです。

---

以上!Kotlinが何故便利なのか自分なりの言葉でまとめてみました。

## 参考資料
[Kotlin In Action](https://www.manning.com/books/kotlin-in-action)
[Javaでなぜつくるのか](https://www.amazon.co.jp/Java%E3%81%A7%E3%81%AA%E3%81%9C%E3%81%A4%E3%81%8F%E3%82%8B%E3%81%AE%E3%81%8B-%E7%9F%A5%E3%81%A3%E3%81%A6%E3%81%8A%E3%81%8D%E3%81%9F%E3%81%84Java%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E3%81%AE%E5%9F%BA%E7%A4%8E%E7%9F%A5%E8%AD%98-%E7%B1%B3%E6%8C%81-%E5%B9%B8%E5%AF%BF/dp/4822281965)