Rust
私がRustを選んだ理由
久しぶりにgolangに行ったら、新しい1.6が来てたので入れた。順調に進化してるな。また触ってみるか。血圧管理アプリもgo製だしね。
ネットをうろうろしてたら、
実装言語を「Go」から「Rust」に変更、ゲーマー向けチャットアプリ「Discord」の課題とは
こんな記事に行き当たった。Goが採用してるGCが足枷になってるとな。Lispに源にするGCは、javaだとかrubyとかにも採用され、ユーザーをメモリー管理から解放してくれる希望の星とばかり思っていた。
けど、場合によっては邪魔になるとな。そう言えばjavaなんかは、並々ならぬ苦労をしてGCの挙動を隠すようにしてたね。この事情はrubyも同じだ。
大体、GoとRustはよきライバル関係にあるのだな。そう思って、もう少しggしてみると、
Rust,Go,Elixir,Kotlin次世代言語の魅力をCTOが語る
どこかの社長さんが21世紀言語を語っていた。そして、こんな記事もあったぞ。
幸いオイラーは、Rustなんて触った事が無い、原人。OpenBSDに来てたら触ってみるか、と言う他人まかせな賭けに出て見る。無いならスルーします。
って、有ったから、この記事を書いているんでしょ。
Install Rust
畳上の水練にならないように、処理システムを入れるのが最初の一歩です。
at OpenBSD
パッケージは4つに分解されてました。rustって奴が一番大きいから本体だろう。rust-gdbなんてのは、gdbのサポートなんだな。後の2つは何よ? portsの説明を参照。
DESCR-clippy A bunch of lints to catch common mistakes and improve your Rust code. DESCR-rustfmt A tool for formatting Rust code according to style guidelines.
これを見ると、迷わず入れておkって類ですね。
それからemacsのサポートはどうか?ggると、色々な設定を施している方が多いけど、最初はそこまで凝らずに、basicなrust-modeだけを入れた。 第二歩目は、あれだ。
ob$ cat hoge.rs fn main() { println!("Hello, world!"); } ob$ rustc hoge.rs ob$ ./hoge Hello, world!
あれ? C語で必要だった、#include が不要になってるね。
ob$ ldd ./hoge | cut -b 50- GrpRef Name 0 ./hoge 0 /usr/lib/libpthread.so.26.1 0 /usr/lib/libc++abi.so.3.0 0 /usr/lib/libc.so.96.0 0 /usr/libexec/ld.so ob$ file hoge hoge: ELF 64-bit LSB shared object, x86-64, version 1 ob$ ls -l hoge -rwxr-xr-x 1 sakae wheel 324832 Mar 9 08:03 hoge*
at debian
OpenBSDへのカウンターとしてリナ系にも入れるのが、オイラーの流儀。一穴はまずいですからね。
Webでアクセスしてインストールを選べば、rustupってコマンドで簡単に、開発環境をインストール出来る。このアプリが、アップデートにも対応してる。
Other installation methods こんな案内も有った。
debian:~$ du -sh .cargo/ 144M .cargo/ debian:~$ du -sh .rustup/ 1.1G .rustup/
普段使いのコマンド類は、.cargo/bin/に収まっている。が、それを下支えするライブラリィー類は、.rustupの中に格納されている。この.rustupは、見なかった事にしておくのが吉。 それから、これらが全て$home下に置いてある事に注目。全てユーザーの裁量でなんとか出来る。これは、派遣先とかで、こっそりと内職をやる時等、便利だぞ。敷居を下げて、拡散希望って、切なる願いがこもっております。
debian:z$ time rustc hoge.rs real 0m12.282s user 0m0.502s sys 0m0.181s debian:z$ ./hoge Hello, world! debian:z$ rm hoge debian:z$ time rustc hoge.rs real 0m0.604s user 0m0.514s sys 0m0.086s
お約束で初回は色々な準備が有る為、随分待たされる。2回目からは、許容範囲のコンパイル時間に落ち着く。そなら、mainは特別扱いか、調べてみる。
debian:z$ rustc hoge.rs error[E0601]: `main` function not found in crate `hoge` --> hoge.rs:1:1 | 1 | / fn foo() { 2 | | println!("Hello, world!"); 3 | | } | |_^ consider adding a `main` function to `hoge.rs` error: aborting due to previous error For more information about this error, try `rustc --explain E0601`.
やはり特別扱い。C語の遺伝子を継承してるな。ここ見ろワンワンが示された。
debian:z$ rustc --explain E0601 No `main` function was found in a binary crate. To fix this error, add a `main` function: ``` fn main() { // Your program will start here. println!("Hello world!"); } ``` If you don't know the basics of Rust, you can look at the [Rust Book][rust-book] to get started. [rust-book]: https://doc.rust-lang.org/book/
本嫁、本読めと言ってきたな。
debian:z$ ls -lh hoge -rwxr-xr-x 1 sakae sakae 3.1M Mar 10 07:14 hoge* debian:z$ ldd hoge linux-gate.so.1 (0xb7efc000) libgcc_s.so.1 => /lib/i386-linux-gnu/libgcc_s.so.1 (0xb7e5d000) librt.so.1 => /lib/i386-linux-gnu/librt.so.1 (0xb7e52000) libpthread.so.0 => /lib/i386-linux-gnu/libpthread.so.0 (0xb7e31000) libdl.so.2 => /lib/i386-linux-gnu/libdl.so.2 (0xb7e2b000) libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb7c4d000) /lib/ld-linux.so.2 (0xb7efe000)
OpenBSDのrustが作ったバイナリーに比べて10倍も肥大化してる。
from source
バイナリーインストールは気味が悪いので、一応ソースに当たっておく。
ninja って言う新種のbuildシステムが必要とか。
Ninja is yet another build system. It takes as input the interdependencies of files (typically source code and output executables) and orchestrates building them, quickly. Ninja joins a sea of other build systems. Its distinguishing goal is to be fast. It is born from my work on the Chromium browser project, which has over 30,000 source files and whose other build systems (including one built from custom non-recursive Makefiles) can take ten seconds to start building after changing one file. Ninja is under a second. WWW: https://ninja-build.org/
取り合えずソースをお取り寄せ。
debian:src$ du -sh rust/ 5.0G rust/
ぐちゃぐちゃやってると思ったら、こんなに肥大化してた。自前でコンパイルしたら、とんでもない時間がかかりそう。潔く諦めた。
book
rustは難しいので、資料はbookと言う名前で公開されてるっぽい。
プログラミング言語Rustのススメ これがエッセンスだな。
Rust入門 全体を俯瞰するのに便利
お気楽 Rust プログラミング超入門 こちらもお勧め
The Rust Programming Language日本語版 本家の資料が日本語化されてる
Rustの日本語ドキュメント/Japanese Docs for Rust 日本語資料の基点
Rustの本家 日本語がサポートされてるって、めちゃ感激。
この本家では、スペイン語やフランス語やロシア語等も有るけど、何故かドイツ語は無い。昔ドイツの人と交流した事が有るけど、皆英語は普通に使ってた。田舎のホテル兼居酒屋で、おばちゃんからも英語で話かけられたし。
ドイツ国内を旅行した時、やはり居酒屋で、よいぼれ爺さんにビールを奢ってもらった。 お前はヤーパンか、今度イタ公抜きで、もう一度戦争しようなんて、悪い冗談を言われた。
こう考えるとRustは、言語障害をかかえる国の人(正しく、オイラーみたいな奴)にも、手厚いサポートをしてファンを増やそうと言う心意気を感じるぞ。
compile ang go
goもそうであったように、プロジェクトを作って、そこでごにょごにょやるのが、現代風らしい。その為にはcargoって言うコマンドを使うとな。
ob$ cargo new hoge Created binary (application) `hoge` package ob$ cd hoge/ ob$ tree . |-- Cargo.toml `-- src `-- main.rs 1 directory, 2 files ob$ time cargo r Compiling hoge v0.1.0 (/tmp/hoge) Finished dev [unoptimized + debuginfo] target(s) in 4.93s Running `target/debug/hoge` Hello, world! 0m04.95s real 0m00.21s user 0m03.45s system
newするとたたき台が出来る。r(un)すると、コンパイルされて、出来上がったバイナリーが実行される。初回は、やはり時間がかかる。
ob$ time cargo r Compiling hoge v0.1.0 (/tmp/hoge) Finished dev [unoptimized + debuginfo] target(s) in 0.56s Running `target/debug/hoge` Hello, Rust 0m00.58s real 0m00.18s user 0m00.59s system
ソースを変更してから、再実行。今度はすんなりだ。target/debug/hogeにバイナリーが出来上がるのだけど、サイズはリナのそれと比べて1/10のサイズだ。その違いは、/usr/lib/libc++abi.so.3.0が外のやつを使っている為と思われる。
crate
木箱って意味らしい。クレートと発音するそうな。箱だから何かが入っている。その何かは、好き者が開発したライブラリィー類。コンパイルする時の単位になる。ライブラリィーで機能豊富な場合、ファイルを分割する事がある。でも、そんな場合、ファイル単独のコンパイルでは意味をなさない。分割した物を全てコンパイルして(リンクして)、意味があるものになる。
The Rust community’s crate registry crate.io て所で、検索出来る。
ob$ cargo search rand Updating crates.io index Fetch [==============> ] 27.42%
手元に持ってきて、検索するのが楽。indexは、$home/.cargo/registry/ 以下に置かれる。 何もかも .git に頼っていて、単一故障点だな。大丈夫か、おい。
ob$ cargo search rand rand = "0.8.3" # Random number generators and other randomness functionality. : rand_mt = "4.0.1" # Reference Mersenne Twister random number generators. ... and 491 crates more (use --limit N to see more)
for emacs
rust-lang / rust-mode これが標準設定?
;; rust-mode (require 'rust-mode) (add-hook 'rust-mode-hook (lambda () (setq indent-tabs-mode nil))) (setq rust-format-on-save t) (define-key rust-mode-map (kbd "C-c C-c") 'rust-run)
シンプルにrust-modeだけの仕様。requireは入れておかないと、シンボルが解決出来んと言うエラーになる(普通は、要らないんだけど、今回は特殊か)。
ob$ emacs src/main.rs : ソースが見えたら、C-c C-c すると、画面が割れて、cargo runしてくれる。楽ちん。 -*- mode: compilation; default-directory: "/tmp/fuga/" -*- Compilation started at Thu Mar 11 15:35:21 cargo run Compiling fuga v0.1.0 (/tmp/fuga) Finished dev [unoptimized + debuginfo] target(s) in 0.44s Running `target/debug/fuga` Hello, Emacs! Compilation finished at Thu Mar 11 15:35:21
Rustの環境構築(Emacs) 凝った設定で、使いこなすの難しそう。
sample
実習
上で挙げた、時間計測ってのを、オイラーもやってみる。まず適当なプロジェクトを作るんだな。
ob$ cargo new zz Created binary (application) `zz` package ob$ cd zz ob$ emacs src/main.rs
main.rsを開いてから、取り合えずソースをコピペ。走らせてみると
cargo run Compiling zz v0.1.0 (/tmp/zz) error[E0432]: unresolved import `quanta` --> src/main.rs:1:5 | 1 | use quanta::Clock; | ^^^^^^ use of undeclared type or module `quanta` error: aborting due to previous error
初っ端からエラーの返礼。良くみると、該当するクレートが無いと言ってる。
ob$ cargo search quanta quanta = "0.7.2" # high-speed timing facility :
この案内を、Cargo.tomlに書いておくんだな。
[dependencies] quanta = "0.7.2"
これで走らせてみる。
ob$ cargo r Updating crates.io index Compiling bitflags v1.2.1 Compiling libc v0.2.88 Compiling atomic-shim v0.1.0 Compiling once_cell v1.7.2 Compiling raw-cpuid v9.0.0 Compiling quanta v0.7.2 Compiling zz v0.1.0 (/tmp/zz) warning: variable does not need to be mutable --> src/main.rs:5:9 | 5 | let mut clock = Clock::new(); | ----^^^^^ | | | help: remove this `mut` | = note: `#[warn(unused_mut)]` on by default warning: 1 warning emitted Finished dev [unoptimized + debuginfo] target(s) in 9.65s Running `target/debug/zz` std::time:Instant::now() overhead = 1.718695873s quanta::clock::now() overhead = 178.454077ms
quantaってのは、色々なモジュールに依存してる。勿論本体は陽にquantaに依存してる。それを解決(コンパイル)して、最後の2行が、実行結果。このソースの場合、mutは必要無いと、ご丁寧な提案が有った。
本体に依存したライブラリィーは、$home/.cargoの中に蓄えられるのね。 この実習で、大体の仕組みが分かったよ。
このソースでも使われているんだけど、printlnマクロのブレースフォルダーの指定が分からなかったので、先人の調べを借用した。
{Rust} 文字列のフォーマット指定(println! / format!)