ユーニックス総合研究所

  • home
  • archives
  • rust-muzukashii

Rustは難しいけど楽しい言語です【本当?】

  • 作成日: 2023-05-23
  • 更新日: 2023-12-24
  • カテゴリ: Rust

Rustは難しいけど楽しい言語?

Rustは難しい。けど楽しい言語?
実際に使ってみると確かにRustの言語仕様は難しいところがあります。
しかし、慣れてくるとRustもなかなか楽しい言語と言えます。

この記事ではRustの難しさと楽しさを解説します。

関連記事
RustでJSONの読み書きを行う
RustでTCPクライアント/サーバーを作る【ソケット通信】
Rustでファイルサイズを取得する方法【std::fs::metadata】
RustのBoxの使い方【ヒープにメモリを確保!初心者向け】
RustのResultでエラーハンドリング処理を行う
RustのThread(スレッド)で並行処理をする方法
RustのVecの使い方【vec!, push, pop】
Rustのassert!の使い方【assert!, assert_eq!, assert_ne!】

Rustのどこが難しいか?

Rustって具体的にどこら辺が難しいのでしょうか?
これは以下の3つを挙げることができます。

  • ムーブセマンティクス
  • ポインタ
  • ライフタイム

ムーブセマンティクス

「ムーブセマンティクス」とは所有権の移動のことを言います。
Rustで「所有権」という概念があります。
これは変数のメモリをだれが所有しているか、という考えです。

Rustでは変数を別の変数に代入すると、デフォルトでムーブセマンティクスが働きます。

    let x = String::new();  
    let y = x;  
    println!("{}", x);  

上記のコードを実行するとエラーになります。
エラー内容は

println!("{}", x);  
              ^ value borrowed here after move  

というエラーです。これはxがムーブの後に参照されているというエラーです。
xの所有権はyに移動していますので、xはその段階で使えなくなります。

このムーブセマンティクスと言う概念は少なくともC言語時代からあった概念です。
構造体をコピーする関数で構造体内のポインタをすげ変えるという実装を行うことでコピーのコストを減らすというアプローチです。
Rustのムーブも基本的にはこの考え方と同じかと思われます。

ポインタ

Rustには「ポインタ」があります。

    let x = String::from("hello");  
    let y: *const String = &x;  
    unsafe {  
        println!("{}", *y);  
    }  

ポインタと言うのは変数のアドレスをポインタ変数と言う変数に保存したものを言います。
変数のアドレスとはメモリ上のアドレスのことで、パソコンは変数の値にアクセスするときにこのアドレスを見てアクセスします。
つまりかなり低レイヤーな機能で、Rustではこの機能をサポートしています。

これもC言語時代から存在する機能で、ポインタは数々の言語学習者を打ち破ってきました。
ポインタの前に敗れた学習者は数知れず、まさに死屍累々です。

Rustは低レイヤーなコードも書けるように設計されており、そのため低レイヤーな実装が必要な環境でも採用されている言語です。
このポインタの概念はお世辞にもわかりやすいとは言えず、言語学習者は苦労するかもしれません。

ライフタイム

Rustには「ライフタイム」があります。

ライフタイムとは変数を参照したときに、ダングリング参照を発生させないようにする仕組みです。
ダングリング参照とは、寿命が切れた変数の参照のことです。

    {  
        let r;  

        {  
            let x = 5;  
            r = &x;  
        }  

        println!("r: {}", r);  
    }  

上記のコードではxの寿命は内側のブロックで付きますが、その参照がrに保存されてしまっています。
rは寿命が切れたxの参照を持つことになり、これはアクセスした場合に困ったことになります。
このような状況を回避するための仕組みがライフタイムです。

ライフタイムはRustでは特別際立った機能です。
他の言語ではあまり見られません。
そのため理解するのが難しいと言えます。

Rustの難しさはどの程度のものか?

Rustの難しさはどの程度のものなのでしょうか?
他の言語と比較してどうでしょうか?
以下の言語と比較してみましょう。

  • C言語
  • C++

C言語との比較

C言語は言語機能がコンパクトでRustほど多機能ではありません。
そのため学習コストとしてはRustより低いと言えます。

しかし、C言語のエラー機構は現代的とは言えず、また不正なポインタを参照するとプログラムが落ちることがあるなど、詰まりやすいポイントも多いです。
Rustもunsafeなコードを書けばC言語と似たり寄ったりな感じになりますが、unsafeを使わなければ現代的なゆりかごに揺られて開発できます。

C言語は開発者の足を打ち抜くことがある言語ですが、Rustは開発者が望めば足を打ち抜くことがある言語と言えます。
そういう意味ではRustによる開発のほうがラクかもしれません。
言語機能はRustの方が多いですが、実行時エラーの難解さなどを比較した場合はRustのほうがデバッグが容易なことがあるかもしれません。
うーん、まさかのC言語のほうが難しい場合がある、という結果になりました。

C++との比較

C++はどうでしょうか?
C++はC言語を拡張する目的で作られたマルチパラダイム言語です。

すでにC言語のほうがRustより難しい場合があるという結論が出ていますので、そういう意味ではC++のほうが難しいと言えます。
C++は言語機能がとにかく盛りだくさんで色々なところから吸収を続けている言語です。

またC++もC言語と同じで実行時エラーのデバッグが難解なので、そういう意味ではRustのほうがラクかもしれません。
もっとも、Rustのunsafeが解き放たれたとき、その順位は逆転する可能性もあります。

Rustは難しいから学習が大変?

Rustは難しいので学習が大変かもしれません。
初学者には向いている言語でしょうか?
この辺を見ていきましょう。

初学者か経験者かで変わる

Rustの学習難易度は学習者が初学者か経験者かで変わります。
まったくのプログラミング初心者がいきなりRustを学ぶというのはなかなか大変かと思われます。
先述の通りRustにはムーブセマンティクスやポインタ、ライフタイムなどの難しい概念が目白押しです。

C言語であれば難しいところはポインタぐらいですが、Rustになるとすそれは少なくとも3倍です。
しかしC言語などの経験がある開発者であればRustはそれほど難しくないかもしれません。
Rustのコンパイラは非常に親切で大抵のエラーは検索しなくても解決できるからです。

まったくの初学者がRustに挑むのはかなり大変

まったくの初学者がRustに挑んだ時の学習コストを想像してみましょう。
ムーブセマンティクスを知らない、参照・ポインタを知らない、ライフタイムを知らない、構造体、列挙体・・・。

うーん、やはり自分が初学者だと考えると、なかなか習得するのは大変かと想像できます。
逆に言えば初学者であってもRustを極めれば大抵の言語はそれほど難しさを感じなくなるかもしれません。
これはC++も同じでC++をやっている人は大抵の言語の習得をそれほど苦もなく行える可能性があります。

ある程度他の言語を知っていればラク

やはりある程度は他の言語で経験を積んでおいた方がいいかもしれません。
C言語から始めてC++, Rustというロードマップもありっちゃありです。
C言語は言語機能がコンパクトでC++はそれを拡張していますから、学習がスムーズに移行できます。
またC++で学んだことはRustにも応用が効きますので、そういう意味ではこのロードマップはある意味理想かもしれません。

問題は学習コストですよね。どれぐらい時間を使えば学習できるのか? という点が気になるところです。
このロードマップは学習時間がてんこ盛りです。

Rustを数年書いてきた開発者の感想

Rustを1~2年書いてきてその感想を述べたいと思います。
私はまだRust初学者ですが、Rustのフィーリングはなんとなくつかめています。

Rustは省略記法が多いがタイピング量は比較的に多くなる

Rustですがきっちりエラー処理をするとなるとやはりコード量はけっこう多いです。
しかしこれは他の言語でも同じことが言えてエラー処理をきっちりやるとコード量が増えるのは当然のことです。
Rustはfnpubなどタイピング量を減らす工夫がされていますが、この工夫があってもやはりコード量はそれなりに多くなるでしょう。

Rustのコンパイラは非常に優秀

Rustのコンパイラは非常に優秀です。
特にエラーについてはかなり親切に教えてくれます。
コンパイルエラーを見れば検索しなくてもエラーを解決できることが多いです。
この点は非常に助かります。

Rustのエコシステムも優秀

cargoなどを代表するRustのエコシステムは非常に便利です。
パッケージのインストールも簡単に行えて、それに加えてマルチプラットフォームで、C系列に慣れてきた開発者からするとかなりラクできます。
便利すぎてストレス耐性が無くなるんじゃないかと不安になるぐらいです。

Rustのどこが楽しいか?

Rustのどこら辺が楽しいでしょうか?
私が思うにRustで楽しいところは以下の通りです。

  • モダンなコードで低レイヤーな処理を書ける
  • コンパイラが親切に教えてくれる

モダンなコードで低レイヤーな処理を書ける

Rustは言語機能が豊富でかつ低レイヤーな処理が書けます。
いわゆるリッチなC言語ということができます。

リッチなC言語と言えばC++がそれの代表でしたが、これからの時代はRustも選択肢に入るということになるでしょう。
モダンな言語機能で低レイヤーな処理が書けるという体験はなかなか楽しいものです。

コンパイラが親切に教えてくれる

Rustはコンパイラが親切でエラーについても細かく教えてくれます。
ですので快適にプログラミングができます。
またエラーについてはコードの提案も行ってくれますので、その提案をコピペすれば解決することも多いです。

これからはAIの時代になってきますが、おそらくコンパイラにもAIによる提案機能が入ってくるんじゃないでしょうか。
そうなったらなおさらプログラミングが快適になるかと思われます。

おわりに

今回はRustの難しさと楽しさを解説しました。
Rustは比較的に難しい言語ですが楽しさもあります。
習得すれば大きな経験となるでしょう。
なにか参考になれば幸いです。