サクサク読めて、アプリ限定の機能も多数!
トップへ戻る
CES 2025
doc.rust-jp.rs
自動テストを書く 1972年のエッセイ「謙虚なプログラマ」でエドガー・W・ダイクストラは以下のように述べています。 「プログラムのテストは、バグの存在を示すには非常に効率的な手法であるが、 バグの不在を示すには望み薄く不適切である」と。これは、できるだけテストを試みるべきではないということではありません。 プログラムの正当性は、どこまで自分のコードが意図していることをしているかなのです。 Rustは、プログラムの正当性に重きを置いて設計されていますが、 正当性は複雑で、単純に証明することはありません。Rustの型システムは、 この重荷の多くの部分を肩代わりしてくれますが、型システムはあらゆる種類の不当性を捕捉してはくれません。 ゆえに、Rustでは、言語内で自動化されたソフトウェアテストを書くことをサポートしているのです。 例として、渡された何かの数値に2を足すadd_twoという関数を書
SyncとSendトレイトで拡張可能な並行性 面白いことに、Rust言語には、寡少な並行性機能があります。この章でここまでに語った並行性機能のほとんどは、 標準ライブラリの一部であり、言語ではありません。並行性を扱う選択肢は、言語や標準ライブラリに制限されません; 独自の並行性機能を書いたり、他人が書いたものを利用したりできるのです。 ですが、2つの並行性概念が言語に埋め込まれています: std::markerトレイトのSyncとSendです。 Sendでスレッド間の所有権の転送を許可する Sendマーカートレイトは、Sendを実装した型の所有権をスレッド間で転送できることを示唆します。 Rustのほとんどの型はSendですが、Rc<T>を含めて一部例外があります: この型は、Rc<T>の値をクローンし、 クローンしたものの所有権を別のスレッドに転送しようとしたら、両方のスレッドが同時に参
Hello, World! Rustをインストールしたので、最初のRustプログラムを書きましょう。新しい言語を学ぶ際に、 Hello, world!というテキストを画面に出力する小さなプログラムを書くことは伝統的なことなので、 ここでも同じようにしましょう! 注釈: この本は、コマンドラインに基礎的な馴染みがあることを前提にしています。Rustは、編集やツール、 どこにコードがあるかについて特定の要求をしないので、コマンドラインではなくIDEを使用することを好むのなら、 どうぞご自由にお気に入りのIDEを使用してください。今では、多くのIDEがなんらかの形でRustをサポートしています; 詳しくは、IDEのドキュメンテーションをご覧ください。最近、Rustチームは優れたIDEサポートを有効にすることに注力し、 その前線で急激に成果があがっています! プロジェクトのディレクトリを作成する
ハッシュ集合 値がなく、キーだけのHashMapを想像してみてください。これはハッシュ集合(HashSet)と呼ばれるものです。(HashSet<T>は、実際にはHashMap<T, ()>のラッパーです。) 「何の意味があるの?フツーにキーをVecに入れればいいじゃん」そう思いましたね? それは、HashSet独自の機能として、要素に重複がないということが保証されるためです。これは全ての集合(set)型がもつ機能です。HashSetはその実装の1つであり、他にはBTreeSet等があります。 HashSetに、すでに存在する値を加えようとすると、(すなわち、加えようとしている値のハッシュ値と、要素中のいずれかの値のハッシュ値が等しい場合、)新しい値によって古い値が上書きされます。 これは、同じ値を2つ以上欲しくない場合や、すでにある値を持っているか知りたい場合にとても有効です。 しかし、
状態共有並行性 メッセージ受け渡しは、並行性を扱う素晴らしい方法ですが、唯一の方法ではありません。 Go言語ドキュメンテーションのスローガンのこの部分を再び考えてください: 「メモリを共有することでやり取りする。」 メモリを共有することでやり取りするとはどんな感じなのでしょうか?さらに、 なぜメッセージ受け渡しに熱狂的な人は、それを使わず、代わりに全く反対のことをするのでしょうか? ある意味では、どんなプログラミング言語のチャンネルも単独の所有権に類似しています。 一旦チャンネルに値を転送したら、その値は最早使用することがないからです。 メモリ共有並行性は、複数の所有権に似ています: 複数のスレッドが同時に同じメモリ位置にアクセスできるのです。 第15章でスマートポインタが複数の所有権を可能にするのを目の当たりにしたように、 異なる所有者を管理する必要があるので、複数の所有権は複雑度を増さ
スレッドを使用してコードを同時に走らせる 多くの現代のOSでは、実行中のプログラムのコードはプロセスで走り、OSは同時に複数のプロセスを管理します。 自分のプログラム内で、独立した部分を同時に実行できます。これらの独立した部分を走らせる機能をスレッドと呼びます。 プログラム内の計算を複数のスレッドに分けると、パフォーマンスが改善します。プログラムが同時に複数の作業をするからですが、 複雑度も増します。スレッドは同時に走らせることができるので、異なるスレッドのコードが走る順番に関して、 本来的に保証はありません。これは例えば以下のような問題を招きます: スレッドがデータやリソースに矛盾した順番でアクセスする競合状態 2つのスレッドがお互いにもう一方が持っているリソースを使用し終わるのを待ち、両者が継続するのを防ぐデッドロック 特定の状況でのみ起き、確実な再現や修正が困難なバグ Rustは、ス
RefCell<T>と内部可変性パターン 内部可変性は、そのデータへの不変参照がある時でさえもデータを可変化できるRustでのデザインパターンです: 普通、この行動は借用規則により許可されません。データを可変化するために、このパターンは、データ構造内でunsafeコードを使用して、 可変性と借用を支配するRustの通常の規則を捻じ曲げています。まだ、unsafeコードについては講義していません; 第19章で行います。たとえ、コンパイラが保証できなくても、借用規則に実行時に従うことが保証できる時、 内部可変性パターンを使用した型を使用できます。関係するunsafeコードはそうしたら、安全なAPIにラップされ、 外側の型は、それでも不変です。 内部可変性パターンに従うRefCell<T>型を眺めてこの概念を探究しましょう。 RefCell<T>で実行時に借用規則を強制する Rc<T>と異なり、
Cargoのワークスペース 第12章で、バイナリクレートとライブラリクレートを含むパッケージを構築しました。プロジェクトの開発が進むにつれて、 ライブラリクレートの肥大化が続き、その上で複数のライブラリクレートにパッケージを分割したくなることでしょう。 この場面において、Cargoはワークスペースという協調して開発された関連のある複数のパッケージを管理するのに役立つ機能を提供しています。 ワークスペースを生成する ワークスペースは、同じCargo.lockと出力ディレクトリを共有する一連のパッケージです。 ワークスペースを使用したプロジェクトを作成し、ワークスペースの構造に集中できるよう、瑣末なコードを使用しましょう。 ワークスペースを構築する方法は複数ありますが、一般的な方法を提示しましょう。バイナリ1つとライブラリ2つを含むワークスペースを作ります。 バイナリは、主要な機能を提供します
所有権とは? Rustの中心的な機能は、所有権です。この機能は、説明するのは簡単なのですが、言語の残りの機能全てにかかるほど 深い裏の意味を含んでいるのです。 全てのプログラムは、実行中にコンピュータのメモリの使用方法を管理する必要があります。プログラムが動作するにつれて、 定期的に使用されていないメモリを検索するガベージコレクションを持つ言語もありますが、他の言語では、 プログラマが明示的にメモリを確保したり、解放したりしなければなりません。Rustでは第3の選択肢を取っています: メモリは、コンパイラがコンパイル時にチェックする一定の規則とともに所有権システムを通じて管理されています。 どの所有権機能も、実行中にプログラムの動作を遅くすることはありません。 所有権は多くのプログラマにとって新しい概念なので、慣れるまでに時間がかかります。 嬉しいことに、Rustと、所有権システムの規則の
メッセージ受け渡しを使ってスレッド間でデータを転送する 人気度を増してきている安全な並行性を保証する一つのアプローチがメッセージ受け渡しで、 スレッドやアクターがデータを含むメッセージを相互に送り合うことでやり取りします。 こちらが、Go言語のドキュメンテーションのスローガンにある考えです: 「メモリを共有することでやり取りするな; 代わりにやり取りすることでメモリを共有しろ」 メッセージ送信並行性を達成するためにRustに存在する一つの主な道具は、チャンネルで、 Rustの標準ライブラリが実装を提供しているプログラミング概念です。プログラミングのチャンネルは、 水の流れのように考えることができます。小川とか川ですね。アヒルのおもちゃやボートみたいなものを流れに置いたら、 水路の終端まで下流に流れていきます。 プログラミングにおけるチャンネルは、2分割できます: 転送機と受信機です。転送機
スマートポインタ ポインタは、メモリのアドレスを含む変数の一般的な概念です。このアドレスは、何らかの他のデータを参照、または「指します」。 Rustにおいて最もありふれた種類のポインタは参照です。参照については第4章で習いましたね。参照は&記号で示唆され、指している値を借用します。データを参照すること以外に特別な能力は何もありません。 また、オーバーヘッドもなく、ポインタの中では最も頻繁に使われます。 一方、スマートポインタは、ポインタのように振る舞うだけでなく、追加のメタデータと能力があるデータ構造です。 スマートポインタという概念は、Rustに特有のものではありません。スマートポインタは、C++に端を発し、 他の言語にも存在しています。Rustでは、標準ライブラリに定義された色々なスマートポインタが、 参照以上の機能を提供します。この章で探究する一つの例が、参照カウント方式のスマートポ
はじめに 注釈: この本のこの版は、本として利用可能なThe Rust Programming Languageと、 No Starch Pressのebook形式と同じです。 The Rust Programming Languageへようこそ。Rustに関する入門書です。 Rustプログラミング言語は、高速で信頼できるソフトウェアを書く手助けをしてくれます。 高レベルのエルゴノミクス(訳注: ergonomicsとは、人間工学的という意味。砕いて言えば、人間に優しいということ)と低レベルの制御は、 しばしばプログラミング言語の設計においてトレードオフの関係になります; Rustは、その衝突に挑戦しています。バランスのとれた強力な技術の許容量と素晴らしい開発者経験を通して、 Rustは伝統的にそれらの制御と紐付いていた困難全てなしに低レベルの詳細(メモリ使用など)を制御する選択肢を与えて
ライフタイムで参照を検証する 第4章の「参照と借用」節で議論しなかった詳細の一つに、Rustにおいて参照は全てライフタイムを保持するということがあります。 ライフタイムとは、その参照が有効になるスコープのことです。多くの場合、型が推論されるように、 大体の場合、ライフタイムも暗黙的に推論されます。複数の型の可能性があるときには、型を注釈しなければなりません。 同様に、参照のライフタイムがいくつか異なる方法で関係することがある場合には注釈しなければなりません。 コンパイラは、ジェネリックライフタイム引数を使用して関係を注釈し、実行時に実際の参照が確かに有効であることを保証することを要求するのです。 ライフタイムの概念は、他のプログラミング言語の道具とはどこか異なり、間違いなくRustで一番際立った機能になっています。 この章では、ライフタイムの全体を解説することはしませんが、 ライフタイム記
トレイト: 共通の振る舞いを定義する トレイトは、Rustコンパイラに、特定の型に存在し、他の型と共有できる機能について知らせます。 トレイトを使用すると、共通の振る舞いを抽象的に定義できます。トレイト境界を使用すると、 あるジェネリックが、特定の振る舞いをもつあらゆる型になり得ることを指定できます。 注釈: 違いはあるものの、トレイトは他の言語でよくインターフェイスと呼ばれる機能に類似しています。 トレイトを定義する 型の振る舞いは、その型に対して呼び出せるメソッドから構成されます。異なる型は、それらの型全てに対して同じメソッドを呼び出せるなら、 同じ振る舞いを共有することになります。トレイト定義は、メソッドシグニチャをあるグループにまとめ、なんらかの目的を達成するのに必要な一連の振る舞いを定義する手段です。 例えば、いろんな種類や量のテキストを保持する複数の構造体があるとしましょう:
まえがき すぐにはわかりにくいかもしれませんが、Rustプログラミング言語は、エンパワーメント(empowerment)を根本原理としています: どんな種類のコードを現在書いているにせよ、Rustは幅広い領域で以前よりも遠くへ到達し、 自信を持ってプログラムを組む力を与え(empower)ます。 一例を挙げると、メモリ管理やデータ表現、並行性などの低レベルな詳細を扱う「システムレベル」のプログラミングがあります。 伝統的にこの分野は難解で、年月をかけてやっかいな落とし穴を回避する術を習得した選ばれし者にだけ可能と見なされています。 そのように鍛錬を積んだ者でさえ注意が必要で、さもないと書いたコードがクラッキングの糸口になったりクラッシュやデータ破損を引き起こしかねないのです。 この難しさを取り除くために、Rustは、古い落とし穴を排除し、その過程で使いやすく役に立つ洗練された一連のツールを
クロージャ: 環境をキャプチャできる匿名関数 Rustのクロージャは、変数に保存したり、引数として他の関数に渡すことのできる匿名関数です。 ある場所でクロージャを生成し、それから別の文脈でクロージャを呼び出して評価することができます。 関数と異なり、呼び出されたスコープの値をクロージャは、キャプチャすることができます。 これらのクロージャの機能がコードの再利用や、動作のカスタマイズを行わせてくれる方法を模擬しましょう。 クロージャで動作の抽象化を行う クロージャを保存して後々使用できるようにするのが有用な場面の例に取り掛かりましょう。その過程で、 クロージャの記法、型推論、トレイトについて語ります。 以下のような架空の場面を考えてください: カスタマイズされたエクササイズのトレーニングプランを生成するアプリを作るスタートアップで働くことになりました。 バックエンドはRustで記述され、トレ
panic!すべきかするまいか では、panic!すべき時とResultを返すべき時はどう決定すればいいのでしょうか?コードがパニックしたら、 回復する手段はありません。回復する可能性のある手段の有る無しに関わらず、どんなエラー場面でもpanic!を呼ぶことはできますが、 そうすると、呼び出す側のコードの立場に立ってこの場面は回復不能だという決定を下すことになります。 Result値を返す決定をすると、決断を下すのではなく、呼び出し側に選択肢を与えることになります。 呼び出し側は、場面に合わせて回復を試みることを決定したり、この場合のErr値は回復不能と断定して、 panic!を呼び出し、回復可能だったエラーを回復不能に変換することもできます。故に、Resultを返却することは、 失敗する可能性のある関数を定義する際には、いい第一選択肢になります。 稀な場面では、Resultを返すよりもパ
Resultで回復可能なエラー 多くのエラーは、プログラムを完全にストップさせるほど深刻ではありません。時々、関数が失敗した時に、 容易に解釈し、対応できる理由によることがあります。例えば、ファイルを開こうとして、 ファイルが存在しないために処理が失敗したら、プロセスを停止するのではなく、ファイルを作成したいことがあります。 第2章の「Result型で失敗する可能性に対処する」でResult enumが以下のように、 OkとErrの2列挙子からなるよう定義されていることを思い出してください: #![allow(unused)] fn main() { enum Result<T, E> { Ok(T), Err(E), } } TとEは、ジェネリックな型引数です: ジェネリクスについて詳しくは、第10章で議論します。 たった今知っておく必要があることは、Tが成功した時にOk列挙子に含まれて
Hello, Cargo! CargoはRustのビルドシステム兼パッケージマネージャです。 ほとんどのRustaceanはこのツールを使ってRustプロジェクトを管理しています。 なぜなら、Cargoは多くの仕事、たとえばコードのビルド、コードが依存するライブラリのダウンロード、それらのライブラリのビルドなどを扱ってくれるからです。 (コードが必要とするライブラリのことを依存(dependencies)と呼びます) いままでに書いたようなごく単純なRustプログラムには依存がありません。 そのため「Hello, world!」プロジェクトをCargoでビルドしても、Cargoの中のコードをビルドする部分しか使わないでしょう。 より複雑なRustプログラムを書くようになると依存を追加することになりますが、Cargoを使ってプロジェクトを開始したなら、依存の追加もずっと簡単になります。 Ru
恐れるな!並行性 並行性を安全かつ効率的に扱うことは、Rustの別の主な目標です。並行プログラミングは、プログラムの異なる部分が独立して実行することであり、 並列プログラミングはプログラムの異なる部分が同時に実行することですが、多くのコンピュータが複数のプロセッサの利点を生かすようになるにつれ、 重要度を増しています。歴史的に、これらの文脈で行うプログラミングは困難で、エラーが起きやすいものでした: Rustはこれを変えると願っています。 当初、Rustチームは、メモリ安全性を保証することと、並行性問題を回避することは、 異なる方法で解決すべき別々の課題だと考えていました。時間とともに、チームは、所有権と型システムは、 メモリ安全性と並行性問題を管理する役に立つ一連の強力な道具であることを発見しました。 所有権と型チェックを活用することで、多くの並行性エラーは、実行時エラーではなくコンパイ
幽霊型パラメータ 幽霊型(Phantom Type)とは実行時には存在しないけれども、コンパイル時に静的に型チェックされるような型のことです。 構造体などのデータ型は、ジェネリック型パラメータを一つ余分に持ち、それをマーカーとして使ったりコンパイル時の型検査に使ったりすることができます。このマーカーは実際の値を何も持たず、したがって実行時の挙動そのものにはいかなる影響ももたらしません。 以下の例では、そのようなマーカーとして幽霊型(std::marker::PhantomData)を用い、それぞれ異なった型の値を持つタプルを作成します。 use std::marker::PhantomData; // A phantom tuple struct which is generic over `A` with hidden parameter `B`. // ジェネリックなタプル構造体。2つ
制御フロー 条件が真かどうかによってコードを走らせるかどうかを決定したり、 条件が真の間繰り返しコードを走らせるか決定したりすることは、多くのプログラミング言語において、基本的な構成ブロックです。 Rustコードの実行フローを制御する最も一般的な文法要素は、if式とループです。 if式 if式によって、条件に依存して枝分かれをさせることができます。条件を与え、以下のように宣言します。 「もし条件が合ったら、この一連のコードを実行しろ。条件に合わなければ、この一連のコードは実行するな」と。 projectsディレクトリにbranchesという名のプロジェクトを作ってif式について掘り下げていきましょう。 src/main.rsファイルに、以下のように入力してください: ファイル名: src/main.rs fn main() { let number = 3; if number < 5 {
では、どの整数型を使うべきかはどう把握すればいいのでしょうか?もし確信が持てないのならば、 Rustの基準型は一般的にいい選択肢になります。整数型の基準はi32型です: 64ビットシステム上でも、 この型が普通最速になります。isizeとusizeを使う主な状況は、何らかのコレクションにアクセスすることです。 浮動小数点型 Rustにはさらに、浮動小数点数に対しても、2種類の基本型があり、浮動小数点数とは数値に小数点がついたもののことです。 Rustの浮動小数点型は、f32とf64で、それぞれ32ビットと64ビットサイズです。基準型はf64です。 なぜなら、現代のCPUでは、f32とほぼ同スピードにもかかわらず、より精度が高くなるからです。 実際に動作している浮動小数点数の例をご覧ください: ファイル名: src/main.rs fn main() { let x = 2.0; // f6
数当てゲームのプログラミング ハンズオン形式のプロジェクトに一緒に取り組むことで、Rustの世界に飛び込んでみましょう! この章ではRustの一般的な概念を、実際のプログラムでの使い方を示しながら紹介します。 let、match、メソッド、関連関数、外部クレートの使いかたなどについて学びます! これらについての詳細は後続の章で取り上げますので、この章では基本的なところを練習します。 プログラミング初心者向けの定番問題である「数当てゲーム」を実装してみましょう。 これは次のように動作します。 プログラムは1から100までのランダムな整数を生成します。 そして、プレーヤーに予想(した数字)を入力するように促します。 予想が入力されると、プログラムはその予想が小さすぎるか大きすぎるかを表示します。 予想が当たっているなら、お祝いのメッセージを表示し、ゲームを終了します。 新規プロジェクトの立ち上
The Rust Programming Language 日本語版 著:Steve Klabnik、Carol Nichols、貢献:Rustコミュニティ このテキストのこの版ではRust 1.58(2022年1月13日リリース)かそれ以降が使われていることを前提にしています。 Rustをインストールしたりアップデートしたりするには第1章の「インストール」節を読んでください。 HTML版はhttps://doc.rust-lang.org/stable/book/で公開されています。 オフラインのときは、rustupでインストールしたRustを使ってrustup docs --bookで開けます。 訳注:日本語のHTML版はhttps://doc.rust-jp.rs/book-ja/で公開されています。 rustupを使ってオフラインで読むことはできません。 また、コミュニティによるい
Rust 裏本 高度で危険な Rust Programming のための闇の技法 NOTE: この文書はドラフトです。重大な間違いを含んでいるかもしれません。 私に与えられたのは、望んだようなプログラムではなく、身を震わせるような暗黒と言い表せないような孤独であった。そして私はついに、誰ひとり口にしようともしなかった恐ろしい真実、ささやくことすらできない神秘中の神秘を目にしたのだ。石のように硬く、耳障りな音をたてるこの言語は、ロンドンが古きロンドンではなく、パリが古きパリではないように、Rust の御代をとこしえにするものではなく、実はきわめて危険で、不完全に防腐処理された、だらしなく寝そべった死体だったのだ。そこにはコンパイル時に生まれた奇妙な生き物たちが所在なさげに蔓延っていた。 (訳注: H.P. ラヴクラフトの小説「あの男」のパロディのようです。) この本は、危険な Rust プロ
序文 Rust エディションガイドへようこそ! 「エディション」とは、Rust に後方互換性が保てなくなるようなアップデートを行うための方法です。 このガイドでは、下記の項目について説明します: エディションとは何か 各エディションの変更内容 コードをあるエディションから別のエディションへ移行する方法
次のページ
このページを最初にブックマークしてみませんか?
『Rustの日本語ドキュメント/Japanese Docs for Rust』の新着エントリーを見る
j次のブックマーク
k前のブックマーク
lあとで読む
eコメント一覧を開く
oページを開く