視野を広くしてくれたRustの世界

ど〜も、てるし〜です。Qiitaでは初登場です。

いつもはzennに登場していますが、なんとなくQiitaで書いてみようと思いました。

https://zenn.dev/terusi

# 背景

最近、Rustを勉強してます。
元々、JSやTSを書いている私でしたが、成長が止まったなと思ってRustを勉強し始めました。
勉強方法としては以下のドキュメントを読むことをしていました。

https://doc.rust-jp.rs/book-ja/ch01-03-hello-cargo.html

上記ドキュメントはプログラマーが「面白い！」と思うようなことがたくさん書いてあります。

私自身、まだ読み途中なのですが読むたびに「😁😁😁😁😁😁😁」って感じになります。

実際にプロジェクト等で使っているわけではないのですが、使えそうなところは考え方

その中でいくつか良いなと思ったこと、いくつかをTSに持ち込んだ話をします。

:::note alert
ぶっ叩くなら隠れて叩いてね😇
:::

# 1. 型

TSをやっていた私がRustをやって思ったことは**型がTSより明確だということ**です。

そもそも、JS/TSで`typeof a`とやった時に`a`の答えになり得る値は

- bigint
- boolean
- function
- object
- number
- string
- symbol
- undefined

だったと思います。
みなさんはこれを見て何か感じますか？？？？

ではRustの型ですが、整数型だけでなんと10種類あります。

https://doc.rust-jp.rs/book-ja/ch03-02-data-types.html#%E6%95%B4%E6%95%B0%E5%9E%8B

しかも、これは整数型でその他に数字だと小数系があります。

対してTSやJSは`number`でまとめられています。

出力結果を知っていて書いていればいいですが、想定外の結果が返ってくる時点でJSやTSの考えは良くないのではないかなと思っています。

# 2. 変数

**変数**という言葉を聞くとみなさんは何を思い浮かべますか？？？
Rustの変数の章を読んだ時、私は「😵😵😵😵😵😵😵😵😵😵😵😵😵」って感じになりました。
そもそも変数には**不変変数**と**可変変数**というものが存在しているのです！！

https://doc.rust-jp.rs/book-ja/ch03-01-variables-and-mutability.html

不変変数、可変変数はざっくりいうと再代入できるかできないかです。

Rustでは変数宣言をするときに`let`を使います。
```rs
let num_first=1;
```
この場合`let`のみを宣言すると再代入が不可能となるため不変変数という形になります。
可変にするには

```rs
let mut num_first=1;
num_first=2;
```
という形にします。

`mut`をつけないと再代入をする際にコンパイラに怒られます。
元々値が変わらないことを宣言しているのにも関わらず、値を変更しようとすると怒られるのです。
「これは再代入をしませんよ」ということをコード上で宣言できることはとても良いことだと思います！

さらに、**エラーを出してくれるということはとても幸せ**なことで**予期せぬバグを防いでくれる**ことにつながるのでとてもハッピーです！！


ここでみなさんは疑問に思いませんか？
じゃあ**定数**は？？？と。

Rustに定数というものはもちろん存在します。
Rustでの定数は
- 常に不変
- 必ず型を注釈しなければならない
- 定数式にしかセットできない

という特徴があります。

```rs
const MAX_NUM:u32=100000;
```
プログラムを実行中に全く値が変わらない値を定義するのにとても役に立ちます。

:::note info
よく、変わらない値をハードコードしている人がいると思いますが、定数を使って値を定義しておき条件式に利用することでコードの可読性やメンテナンスがしやすくなると思います。

これはどの言語においても言えることかと
:::

これを学んだ時私はとあることに気づきました。

**「JS/TSって定数って概念ねーじゃん。。。」**
MDNには一応定数ってことは書いてありますが、**オブジェクトの値を足したり消したり、リスト(一応配列って言っているらしいが)を伸び縮みさせたりとできるのでそれは定数ではなく不変変数ではないのか**と思っています。

そもそもJS/TSでは伸び縮みできる複数の値を入れることが可能なものを**配列**と呼んでいますが、実際の配列は**伸び縮みが不可能で同じ型を持つ値の集まり**だと思います。

プログラミングの一般的な考えとはなんか違うような気がしてます。。(あくまでも個人的な意見です)

# 3. 所有権

Rustのドキュメントで所有権に入った時私は1週間くらい「😇😇😇😇😇😇😇😇😇😇😇😇😇😇😇😇」って感じになってました。

https://doc.rust-jp.rs/book-ja/ch04-01-what-is-ownership.html

JSやTSを扱っているとメモリの意識はしないんじゃないですかね(私自身がそもそもあまり意識をしていなかったので)

**所有権**について書いてある記事はたくさんあるのでここではあまり語りませんが、
C言語では速度は速いがメモリを手動で操作をするのでミスが起こりやすい、逆にJavaやpythonのようなガベージコレクションでメモリ操作を勝手にやってくれるが速度が遅いのと勝手に解放されるのでどのタイミングで解放されるのかがよくわからない(だったかな？)のでそれぞれう〜〜〜んと思うところが多いのに対し値を**所持する変数は必ず1つ**というRustの**所有権**のルールは私はとても感動しました。

**所有権**を学ぶことは**メモリ**がどうこうという話なので今まで意識していなかった部分を意識できるようになる良いきっかけになるのではないかなと思います。

個人的にはとても面白い！と思える内容でした。


# 4. `null`と`Option型`もしくは`Result型`

みなさんはプロジェクトで、`null`を使っていますか？？
私は堂々と使っていました。ですが、ハンドリング等を怠ってかなりバグを起こした痛い記憶があります。

Rustの`enum`の単元で面白い話が出てきました。

> Null References: The Billion Dollar Mistake"(Null参照: 10億ドルの間違い)

これの詳細はこのように書いてあります。

> nullの開発者であるトニー・ホーア(Tony Hoare)の2009年のプレゼンテーション、 "Null References: The Billion Dollar Mistake"(Null参照: 10億ドルの間違い)では、こんなことが語られています。 
>私はそれを10億ドルの失敗と呼んでいます。その頃、私は、オブジェクト指向言語の参照に対する、 最初のわかりやすい型システムを設計していました。私の目標は、 どんな参照の使用も全て完全に安全であるべきことを、コンパイラにそのチェックを自動で行ってもらって保証することだったのです。 しかし、null参照を入れるという誘惑に打ち勝つことができませんでした。それは、単純に実装が非常に容易だったからです。 これが無数のエラーや脆弱性、システムクラッシュにつながり、過去40年で10億ドルの苦痛や損害を引き起こしたであろうということなのです。

https://doc.rust-jp.rs/book-ja/ch06-01-defining-an-enum.html#option-enum%E3%81%A8null%E5%80%A4%E3%81%AB%E5%8B%9D%E3%82%8B%E5%88%A9%E7%82%B9

`null`は予期せぬバグ、下手すると脆弱性に繋がってしまうことがあります。

Javaなどの言語では`null`で犯したミスはエラーではなく実行時のバグとして起こってしまいます。
`null`は実装が楽なのかもしれませんが、しっかりハンドリングをしないと実行時に大変なことになってしまいます。
近年、開発されている言語では`null`がないものがほとんどだと思います。
Rustもその一つです。

Rustでは`Option`型や`Result`型など`null`の代わりにコンパイラが明確にわかる型設計が用意されています。
`Option`型には`some`と`none`があり`some`の中には存在する値が格納されています。

また、これらの型はハンドリングしないと明確な値が出てこないといったことからバグを未然に防げる安全なソースコードが生まれやすいともいえます。

この考えはJS/TSでも私は持ち込むようにしました。「`match`や`if let`がない」という意見はありますが、`if`や`switch`でハンドリングしてから次の処理に進むという意識付けができるようになり、**しょうもないバグが減るようになりました**。

少し前に書いた記事をここで記載しておきます。

https://zenn.dev/terusi/articles/abd692e1c2df69

TSでは`Result`型のライブラリがあるらしいですが、自分はよく簡単な`Option`型と`Result`型を作ります。

```ts
interface Some<T>{
    kind: "some",
    value:T
}

interface None{
    kind:"none"
}

type Option<T>=Some<T>|None
```

イメージだけを書きましたが`null`から`Option`に書き換えるだけで確実にハンドリングをしないといけない状況になるので個人的には導入してみても良いんじゃないかな？と思います。


# まとめ

いかがだったでしょうか？
Rustはとても個人的に良い言語だと思いますし、他の言語で行き詰まったり成長が止まったと感じた時に勉強すべき言語とも言えるのかもしれません。

Rustは安全なコードを書けるような設計をしているように感じられました。
特にコンパイラが細かくエラーを出してくれるのでそこがとても良いなと感じる瞬間でした。

今回4つのことについてを取り上げましたが他にもジェネリックなデータ型やエンコーディングについてなどRustを勉強することで今まで意識していなかったことが意識できるようになる可能性が高くなり、**直接的に使わなくてもより良いソースコードが書けるようになるのではないかな**と思います。

私自身もこれから読む章たちは楽しみです。

**どんな学びがあるのか、そしてどんな綺麗なソースコードが書けるようになるのか。**

私の冒険はまだまだ続きます。