こんにちは〜〜〜〜🎸
この記事はNE Advent Calendar 2022のカレンダー1枚目11日目の記事です
Rustにふれました。すごかったです。
ツールの使い心地の感動と実際理解を深めようとしたときの奥の深さに頭を抱えました。
どこかの誰かのちょっとしたきっかけぐらいになってくれたら幸いです。
はじめに
Rustについて触ってみようと思ったのは WEB+DBvol.131の「Rust入門」 を読んだのがきっかけです。
個人的にはとっかかり的にはめちゃくちゃvol.131の説明がわかりやすかったのでおすすめです。
なので、今回の記事はWEB+DBvol.131と公式サイトのチュートリアルで学んでこととをもとに書いていこうと思います
Rustの世界に触れてみる
Rust製のコマンドラインがこの世には色々あるようで、今回がRust製grep(rg)コマンドで体感してみる。(インストール手順は割愛)
実際このなかにはたくさんの「aaaa」って文字がはいってるの
だけど、1個だけ「test」って文字が入っちゃってて何行目にあるのかを知りたいよね
標準のgrepとRust製のgrepで比較してみよう!
1GBのデータから値を抜き出す速度の比較
結果
- grep → 7.14s
- rg → 0.06s
めちゃくちゃ早〜〜〜〜〜〜い!!!!!これがRustか!!!!!!!
ってことでモチベが上がったところで、詳しく知っていく👇👇👇
Rustってなぁに?
- Rustはね、コンパイル型言語っていう処理速度の速さに定評がある種類の1つでね。おんなじお友達にはC言語やJavaもいるんだよ。(参考記事がめちゃくちゃ分かりやすかったです)
参考:https://qiita.com/tomokichi_ruby/items/73b0e7924a9f83fe45c6 - Rustはね、所有権っていう特有のメモリ管理の方法が特徴なんだよ。所有権があることは所有者もあってそれはいわゆる変数なんだ。ざっくり説明すると、所有権は常に誰か一人が持っていて、所有者(変数)のスコープから外れたら値が削除されるんだ。イメージ的にはリレーのバトン(所有権)を人(変数)が受け渡して処理が進んでいく感じ
- Rustはね、Nullの概念は存在しないのだ。例えば他言語だと、変数の値をdumpしてみて「あ、ここの値NULLなんだ〜」って確認することあるとおもうけど、コンパイルのタイミングでNULLが入る余地がある箇所が見つかったタイミングでエラーになるのよ
- Rustはね、コンパイルタイミングでめちゃくちゃエラーメッセージでるんだ。でも焦らないで、めちゃくちゃ出る分どこでどういう原因でエラーになったかを親切に押してくれるから。(僕は英語弱々だったから無事頭を抱えました)
参考:https://doc.rust-jp.rs/book-ja/title-page.html
Rustで遊びながら学んでみる
ここからはあかちゃん置いてけぼりにして、いろいろ試した結果とまとめていきます
環境構築をせずともブラウザ上で色々試せれるのでおすすめです!
https://play.rust-lang.org/
パターン①
fn main() {
let a = String::from("hoge");
let b = a;
println!("{}",a);
println!("{}",b);
}
error[E0382]: borrow of moved value: `a`
--> src/main.rs:4:19
これはエラーになって
let a = "hoge";
let b = a;
println!("{}",a);
println!("{}",b);
}
hoge
hoge
これはエラーにならない!!!!なんで!!!!!!
調べたら、
文字列を扱う場合 String,&str2種類あり
ざっくりいうと&strは固定値、Stringは可変値として扱うことができて、値の保持される場所(スタック,ヒープ)違うらしい。
参考:https://doc.rust-jp.rs/rust-by-example-ja/std/str.html
可変値を所有する変数は自分の役割を終えると値が削除されるので、すでに削除された値の変数を呼ぶとエラーとなる。
逆に下のパターンは、暗黙的に&strの固定値として扱われていて、この場合はデータの保管場所が異なるため削除されずにエラーにならない。
で、borrow of moved valueを解決するのは借用という仕組みを使うことで解決できた
let a = String::from("hoge");
let b = &a;←上で指定した変数に&をつける
パターン2
fn main() {
let a = "hoge";
let b = a + "fuga";
println!("{}",a);
println!("{}",b);
}
cannot add `&str` to `&str`
これはエラーになって
fn main() {
let a = 50;
let b = a + 100;
println!("{}",a);
println!("{}",b);
}
50
150
これはエラーにならない!!!!なんで!!!!!
型の扱いが原因で
そもそも、文字の固定値と固定値をそのまま結合できない。
もし行いたい場合、上の公式の説明にもあった 「&strはいつでもStringに変換することができる」 ので、結合先で可変値として扱うように明示しないといけないのでこういう記述にすれば解決された。
fn main() {
let a = "hoge";
let b = String::new() + a + "fuga";
println!("{}",a);
println!("{}",b);
}
hoge
hogefuga
ってことで、メモリについてやら型について、いろいろ試したんですが今回はここまで
まとめ
Rustについてはまだまだ勉強途中なので今後も継続してやっていこうと思います。
メモリ管理やスタックとかヒープあたりの概念に触れたことがなかったので「あれもしらない!待ってこれも知らない!!」が多すぎて、今までなんとなくエンジニアしてた部分をより深く知るきっかけになったので個人的にはよかったです。
とても、導入も簡単だったので何も試したことないよって人は一緒にRustに触れれたらいいなと思います🎸
ではまた〜〜〜〜