BackEnd

Rust入門してみた (基本構文編)

投稿日:

はじめに

最近、流行りのRustを勉強し始めました。学んだ中で、今回はRustの基本構文についてまとめました。

Rustとは?

Rustは、CやC++変わるものとして、実行時パフォーマンスはCと同程度を目指しつつむも、Cよりも楽にコーディングできることを目指している言語です。例えば、次のような特徴があります。

  • 静的型付け言語・型推論のサポート
  • コンパイル言語
  • traitを用いたポリモーフィズム
  • ジェネリクス
  • ガベージコレクションなしに確保されるメモリ安全性

最近では、Linuxカーネルの開発言語として採用されたり(長らくCが使用されていた)、最近ではJavaScriptランタイムのdenoがRustで実装されていたりしていて、話題になっていました。
また、私はPythonも書くのですが、使用しているライブラリ「cryptography」の実装がRustであるなど、ハイパフォーマンスが求められる場面で、Rustが使われることが増えてきていることを体感しています。

Rustの特徴的な基本構文

変数と定数

Rustの変数は、標準では不変であり、再代入することができません。そのため、変数に値を代入することを「値を束縛する」と言います。
let キーワードで変数を宣言できます。

また、変数を可変にするには、 mut キーワードを使用します。

Rustは静的型付け言語なので、宣言時と異なる型での再代入はできません。

mutを避ける方法として、シャドーイングがあります。
プログラムが長くなってくると、同じ変数名を使いたくなってくることがありますが、Rustでは同じ変数名で再宣言することができます。

この場合、新たな変数を宣言していることになるため、再代入とは異なり、別の型にすることもできます。

所有権

最近のプログラミング言語では、GCにより、参照されていないメモリ上の領域を開放する機能が備わっていると思います。RustにはGCは無く、代わりに所有権という概念により、適切にメモリ領域が破棄されます。
今回は、所有権を理解するところから始めます。
例えば、変数に値を束縛する例を見てみましょう。

前者のi32型はエラーとなりませんが、後者のString型はエラーとなります。その違いは、i32にはCopyトレイトが実装されていますが、Stringには実装されていないことにあります。
変数に値が束縛される際、Copyトレイトが実装された型である場合のみ値のCopyが行われ、そうでない場合はポインタのみがコピーされ、所有権が移ります。

それでは、なぜi32はコピートレイトが実装されているのでしょうか。その理由は、i32は固定長であり、値をコピーする際のコストが少ないからだそうです。
Copyトレイトが実装されている型は、基本的にはスカラー値のみで、それ以外の型はmoveが発生すると思っておくとよさそうです。
以下に、Bookからの引用で、Copyが行われるケースを例示します。

  • あらゆる整数型。 u32 など。
  • 論理値型である booltruefalse という値がある。
  • あらゆる浮動小数点型、 f64 など。
  • 文字型である char
  • タプル。ただ、 Copy の型だけを含む場合。例えば、 (i32, i32)Copy だが、 (i32, String) は違う。

次に、関数に引数を渡す例を見てみます。

関数の引数に変数を渡した場合も、所有権が移るため、元の変数を使用することはできません。
nameを引き続き使用したい場合には、greeting関数で引数の対をreturnして、所有権を返してもらう必要があります。ですが、毎回そのような実装をするのは面倒なので、そのようなケースでは所有権の借用をすることになります。

最終的に、所有権を持った変数は、スコープを抜けたタイミングでドロップされます。ドロップされると、メモリ上の領域から消去されます。
このように、所有権に反するコードがあると、コンパイルエラーとなるため、GCが無くても適切にメモリ上の領域が破棄されます。

所有権の借用

所有権をムーブすることなく、関数に変数の値を渡すためには、「参照渡し」をする必要があります。先ほどのコードを次のように修正すると、エラーが解消します。

値の参照を取得するには、 & を付けることで取得できます。また、参照で受ける場合には、型名にも&を付けます。
なお、参照を外すには * 演算子を使用します。

関数

既に何度も登場していますが、Rustの関数の基本形は次のようになります。

静的型付け言語を使っている人にとってはお馴染みだと思いますが、関数の仮引数には型指定が必要で、戻り値の型指定も必要です。
また、関数内で一番最後に実行される部分に「式」を書くことで、returnを省略することができます。
ちなみに、式は文末にセミコロンを書くと文として扱われてしまうため、注意が必要です。

エラーハンドリング

Rustでのエラーハンドリングは大きく分けて2つあります。

回復不能なエラー(panic!)

panic!()を使用すると、その時点でプログラムは終了します。panic!は回復不能なエラーであるため、よほどの場合でない限り、使用することはないと思います。

回復可能なエラー(Result)

RustにはJavaやPythonなどのように、例外を投げるという機能はありません。代わりに、回復可能なエラーとしてResultをReturnする方法があります。実際のところ、Resultは次のようなEnumです。

扱いはEnumと同じなので、Resultをmatch式で受け、エラーハンドリングすることができます。

上記のコードにはまだ問題があります。それは、せっかくエラーハンドリングしているのに、panic!を起こしてしまっている点です。それでは、エラーが発生した場合に、呼び元にエラーを返す(移譲する)ようにしたいと思います。

まず、main関数でエラーハンドリングが行われるようになったため、read_file()関数の結果をmatch式で評価するようになりました。
また、read_fileの返り値の型が Result<String, io::Error> となりました。これは、read_fileで使用している関数のResult型が返すエラーがio::Error型であるためです。

そして、read_file()関数の中身がかなりスッキリしました。文末に ? 演算子が付いています。これは、Result型を返す関数に対してのみ使える書き方で、エラーが返ってきた場合に、呼び出し元にそのままエラーをreturnすることができる書き方です。
?を付けた場合、返り値の型はResultのT型となるため、続けて関数を呼び出すこともできます。

さいごに

Rustで一番初めに躓きそうなポイントを紹介できたと思います。今後は、さらに深掘りしたいと思います!

おすすめ書籍

Webアプリ開発で学ぶ Rust言語入門 パーフェクトRust プログラミングRust 第2版

blog-page_footer_336




blog-page_footer_336




-BackEnd
-

執筆者:

免責事項

このブログは、記事上部に記載のある投稿日時点の一般的な情報を提供するものであり、投資等の勧誘・法的・税務上の助言を提供するものではありません。仮想通貨の投資・損益計算は複雑であり、個々の取引状況や法律の変更によって異なる可能性があります。ブログに記載された情報は参考程度のものであり、特定の状況に基づいた行動の決定には専門家の助言を求めることをお勧めします。当ブログの情報に基づいた行動に関連して生じた損失やリスクについて、筆者は責任を負いかねます。最新の法律や税務情報を確認し、必要に応じて専門家に相談することをお勧めします。


comment

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA


関連記事

Go言語

go:embedとGo 1.16、1.17での変更点まとめ

1 はじめに1.1 変更点一覧2 go:embedとは3 go:embedの使い方3.1 基本的な使い方3.2 複数のファイルを埋め込む3.3 異なるディレクトリのファイルを埋め込む3.4 ディレクト ...

laravel logo

[Laravel]データベースの暗号化について考えてみる

1 はじめに2 環境3 Laravelでの暗号化4 暗号化されたカラムは、そのままではLIKE検索ができない4.1 問題点4.2 解決案1:全件取得してPHP側でがんばって検索する4.3 解決案2:暗 ...

Go言語

Go言語で使えるmigrationライブラリ

1 はじめに2 migrationライブラリ2.1 goose2.2 sql-migrate2.3 migu2.4 pop2.5 sqldef3 sqldefを使ってみる3.1 導入3.2 テーブルを ...

laravel logo

Laravel Authのパスワードリセット機能をカスタマイズする

1 はじめに2 準備2.1 Auth2.2 mailhog3 ユーザー登録とログイン4 パスワードリセットのカスタマイズ4.1 ルーティング確認4.2 view編集4.3 認証処理の編集5 リセット画 ...

laravel logo

LaravelのFacade(ファサード)とは? 何気なく使用していた裏側の仕組みを解説!

1 はじめに1.1 Facadeを使用しているクラス2 Facadeの仕組み3 Facadeの作成3.1 サンプルコードに必要な実装3.2 Serviceの作成3.3 Facadeクラスの作成3.4 ...

フォロー

blog-page_side_responsive

2023年3月
 1234
567891011
12131415161718
19202122232425
262728293031  

アプリ情報

私たちは無料アプリもリリースしています、ぜひご覧ください。 下記のアイコンから無料でダウンロードできます。