From 499278e793f936e956a85fd59eef3a542cbefc89 Mon Sep 17 00:00:00 2001 From: shinmili Date: Sun, 26 May 2024 12:58:01 +0900 Subject: [PATCH 01/10] =?UTF-8?q?ch00=20=E3=81=AF=E3=81=98=E3=82=81?= =?UTF-8?q?=E3=81=AB=E3=81=AE=E5=92=8C=E8=A8=B3=E3=82=92=E6=9C=80=E6=96=B0?= =?UTF-8?q?=E7=89=88=E3=81=AB=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit rust-lang/book@19c40bfd2d57641d962f3119a1c343355f1b3c5e --- src/ch00-00-introduction.md | 98 +++++++++++++++++++------------------ 1 file changed, 50 insertions(+), 48 deletions(-) diff --git a/src/ch00-00-introduction.md b/src/ch00-00-introduction.md index 327055d08..f690afb48 100644 --- a/src/ch00-00-introduction.md +++ b/src/ch00-00-introduction.md @@ -13,7 +13,7 @@ > 注釈: この本のこの版は、本として利用可能な[The Rust Programming Language][nsprust]と、 > [No Starch Press][nsp]のebook形式と同じです。 -[nsprust]: https://nostarch.com/rust +[nsprust]: https://nostarch.com/rust-programming-language-2nd-edition [nsp]: https://nostarch.com/ * Cargoは、付属の依存関係管理ツール兼ビルドツールで、依存関係の追加、コンパイル、管理を容易にし、Rustのエコシステム全体で一貫性を持たせます。 -* Rustfmtは開発者の間で一貫したコーディングスタイルを保証します。 +* Rustfmtフォーマットツールは開発者の間で一貫したコーディングスタイルを保証します。 * Rust言語サーバーは、IDE(統合開発環境)との統合により、コード補完やインラインエラーメッセージに対応しています。 @@ -161,17 +162,17 @@ Rustは、Rustプログラミング言語やコミュニティ、開発者ツー Rustは、スピードと安定性を言語に渇望する方向けです。ここでいうスピードとは、 -Rustで作れるプログラムのスピードとソースコードを書くスピードのことです。Rustコンパイラのチェックにより、 +Rustコードの実行速度とプログラムを書くスピードのことです。Rustコンパイラのチェックにより、 機能の追加とリファクタリングを通して安定性を保証してくれます。これはこのようなチェックがない言語の脆いレガシーコードとは対照的で、 その場合開発者はしばしば、変更するのを恐れてしまいます。ゼロコスト抽象化を志向し、 手で書いたコードと同等の速度を誇る低レベルコードにコンパイルされる高レベル機能により、 @@ -218,12 +219,12 @@ reading a book that specifically provides an introduction to programming. 一般的に、この本は、順番に読み進めていくことを前提にしています。後の章は、前の章の概念の上に成り立ち、 -前の章では、ある話題にさほど深入りしない可能性があります; 典型的に後ほどの章で同じ話題を再度しています。 +前の章では、特定の話題にさほど深入りしない可能性がありますが、後ほどの章で同じ話題を再検討するでしょう。 第1章はRustのインストール方法、“Hello, world!”プログラムの書き方、Rustのパッケージマネージャ兼、 -ビルドツールのCargoの使用方法を説明します。第2章は、Rust言語への実践的な導入です。ここでは概念をざっくりと講義し、後ほどの章で追加の詳細を提供します。 -今すぐRustの世界に飛び込みたいなら、第2章こそがそのためのものです。第3章は他のプログラミング言語の機能に似たRustの機能を講義していますが、 -最初その3章すら飛ばして、まっすぐに第4章に向かい、Rustの所有権システムについて学びたくなる可能性があります。 -しかしながら、あなたが次に進む前に全ての詳細を学ぶことを好む特別に几帳面な学習者なら、 +ビルドツールのCargoの使用方法を説明します。第2章は、数当てゲームを作りながら、実際にRustでのプログラミングをやってもらう導入です。 +ここでは概念をざっくりと講義し、後ほどの章で追加の詳細を提供します。 +今すぐRustの世界に飛び込みたいなら、第2章こそがそのためのものです。第3章は他のプログラミング言語の機能に似たRustの機能を講義し、 +第4章ではRustの所有権システムについて学びます。 +あなたが次に進む前に全ての詳細を学ぶことを好む特別に几帳面な学習者なら、 第2章を飛ばして真っ先に第3章に行き、学んだ詳細を適用するプロジェクトに取り組みたくなった時に第2章に戻りたくなる可能性があります。 最後に、言語についての有用な情報をよりリファレンスのような形式で含む付録があります。 付録AはRustのキーワードを講義し、付録Bは、Rustの演算子と記号、付録Cは、 標準ライブラリが提供する導出可能なトレイト、付録Dはいくつか便利な開発ツールを講義し、 -付録EではRustのエディションについて説明します。 - +付録EではRustのエディションについて説明します。付録Fではこの本の翻訳を見つけることができ、 +付録GではRustの作られ方、そしてnightly Rustとは何かについて講義します。 -| Ferris | Meaning | -|------------------------------------------------------------------------|--------------------------------------------------| -| | このコードはコンパイルできません! | -| | このコードはパニックします! | -| | このコードはアンセーフなコードを含みます。 | -| | このコードは求められている振る舞いをしません。 | +| Ferris | Meaning | +|------------------------------------------------------------------------------------------------------------------|--------------------------------------------------| +| Ferris with a question mark | このコードはコンパイルできません! | +| Ferris throwing up their hands | このコードはパニックします! | +| Ferris with one claw up, shrugging | このコードは求められている振る舞いをしません。 | -> 注釈: なんらかの理由で`rustup`を使用したくない場合、[Rustインストールページ][rust-installation-page]で、 +> 注釈: なんらかの理由で`rustup`を使用したくない場合、[Other Rust Installation Methods ページ][otherinstall]で、 > 他の選択肢をご覧になってください。 -> 訳注:日本語版のRustインストールページは[こちら][rust-installation-page-ja]です。 - -[rust-installation-page]: https://www.rust-lang.org/tools/install/ -[rust-installation-page-ja]: https://www.rust-lang.org/ja/tools/install/ - 以下の手順で最新の安定版のRustコンパイラをインストールします。 @@ -45,16 +40,17 @@ Rustは安定性 (stability) を保証しているので、現在この本の例 > > In this chapter and throughout the book, we’ll show some commands used in the > terminal. Lines that you should enter in a terminal all start with `$`. You -> don’t need to type in the `$` character; it indicates the start of each -> command. Lines that don’t start with `$` typically show the output of the -> previous command. Additionally, PowerShell-specific examples will use `>` -> rather than `$`. +> don’t need to type the `$` character; it’s the command line prompt shown to +> indicate the start of each command. Lines that don’t start with `$` typically +> show the output of the previous command. Additionally, PowerShell-specific +> examples will use `>` rather than `$`. --> > ### コマンドラインの記法 > > この章及び、本を通して、端末で使用するなんらかのコマンドを示すことがあります。読者が入力するべき行は、 -> 全て`$`で始まります。ただし、読者が`$`文字を入力する必要はありません; これは各コマンドの開始を示しているだけです。 +> 全て`$`で始まります。ただし、読者が`$`文字を入力する必要はありません; +> これは各コマンドの開始を示すために表示しているコマンドラインプロンプトです。 > `$`で始まらない行は、典型的には直前のコマンドの出力を示します。また、PowerShell限定の例には、 > `$`ではなく、`>`を使用します。 @@ -88,22 +84,37 @@ Rust is installed now. Great! ``` + +*リンカ*も必要になるでしょう。 +リンカは、コンパイルされた出力をひとつのファイルに合体させるためにRustが使用するプログラムです。 +リンカが既にインストールされている可能性は高いでしょう。 +リンカエラーが発生したときは、Cコンパイラは典型的にリンカを含んでいるでしょうから、Cコンパイラをインストールすべきです。 +一般的なRustパッケージの中には、Cコードに依存し、Cコンパイラが必要になるものもあるので、この理由からもCコンパイラは有用です。 + + + +macOSでは、以下を実行することでCコンパイラが手に入ります: + +```console +$ xcode-select --install +``` + + -これに加えて、なんらかのリンカが必要になるでしょう。既にインストールされている可能性は高いものの、 -Rustプログラムをコンパイルしようとした時、リンカが実行できないというエラーが出たら、 -システムにリンカがインストールされていないということなので、手動でインストールする必要があるでしょう。 -Cコンパイラは通常正しいリンカとセットになっています。 -自分のプラットフォームのドキュメンテーションを見てCコンパイラのインストール方法を確認してください。 -一般的なRustパッケージの中には、Cコードに依存し、Cコンパイラが必要になるものもあります。 -ですので、Cコンパイラは今のうちにインストールしておく価値があるかもしれません。 +Linuxユーザは、通常はディストリビューションのドキュメントに従って、GCCまたはClangをインストールするべきです。 +例えばUbuntuを使用している場合は、`build-essential`パッケージをインストールすれば大丈夫です。 Windowsでは、[https://www.rust-lang.org/tools/install][install]に行き、手順に従ってRustをインストールしてください。 -インストールの途中で、Visual Studio 2013以降用のC++ビルドツールも必要になるという旨のメッセージが出るでしょう。 -ビルドツールを取得する最も簡単な方法は、[Visual Studio 2019用のビルドツール][visualstudio]をインストールすることです。 -どのワークロード (workloads) をインストールするかと質問されたときは、"C++ build tools"が選択されており、Windows 10 SDKと英語の言語パック (English language pack) が含まれていることを確かめてください。 +インストールの途中で、Visual Studio 2013以降用のMSVCビルドツールも必要になるという旨のメッセージが出るでしょう。 -> 訳注:Windowsの言語を日本語にしている場合は言語パックのところで「日本語」が選択されており、そのままの設定でインストールしても基本的に問題ないはずです。しかし、サードパーティーのツールやライブラリの中には英語の言語パックを必要とするものがあるため、「日本語」に加えて「英語」も選択することをお勧めします。 + -[install]: https://www.rust-lang.org/tools/install -[visualstudio]: https://visualstudio.microsoft.com/visual-cpp-build-tools/ +ビルドツールを取得するには、[Visual Studio 2022][visualstudio]をインストールする必要があるでしょう。 +どのワークロード (workloads) をインストールするかと質問されたときは、以下を含めてください: + + + +* 「C++によるデスクトップ開発」(“Desktop Development with C++”) +* Windows 10または11のSDK +* 英語の言語パック (English language pack) コンポーネント (お好みで他の任意の言語パックも) + +> 訳注:Windowsの言語を日本語にしている場合は言語パックのところで「日本語」が選択されており、そのままの設定でインストールしても基本的に問題ないはずです。しかし、サードパーティーのツールやライブラリの中には英語の言語パックを必要とするものがあるため、「日本語」に加えて「英語」も選択することをお勧めします。 -### 更新及びアンインストール +### トラブルシューティング -`rustup`経由でRustをインストールしたなら、最新版へ更新するのは簡単です。 -シェルから以下の更新スクリプトを実行してください: +Rustが正常にインストールされているか確かめるには、シェルを開いて以下の行を入力してください: ```console -$ rustup update +$ rustc --version ``` -Rustと`rustup`をアンインストールするには、シェルから以下のアンインストールスクリプトを実行してください: +バージョンナンバー、コミットハッシュ、最新の安定版がリリースされたコミット日時が以下のフォーマットで表示されるのを目撃するはずです。 -```console -$ rustup self uninstall +```text +rustc x.y.z (abcabcabc yyyy-mm-dd) ``` -### トラブルシューティング +この情報が見られたなら、Rustのインストールに成功しています! +この情報が出ない場合は、次のようにしてRustが`%PATH%`システム環境変数にあることを確認してください。 -Rustが正常にインストールされているか確かめるには、シェルを開いて以下の行を入力してください: +Windows CMDでは: ```console -$ rustc --version +> echo %PATH% ``` -バージョンナンバー、コミットハッシュ、最新の安定版がリリースされたコミット日時が以下のフォーマットで表示されるのを目撃するはずです。 +PowerShellでは: -```text -rustc x.y.z (abcabcabc yyyy-mm-dd) +```powershell +> echo $env:Path ``` -この情報が見られたなら、Rustのインストールに成功しています!この情報が出ず、Windowsを使っているなら、 -Rustが`%PATH%`システム環境変数にあることを確認してください。これらが全て正常であるのに、それでもRustがうまく動かないなら、 -助力を得られる場所はたくさんあります。最も簡単なのが[Rustの公式Discord][discord]の#beginnersチャンネルです。そのアドレスで、助けてくれる他のRustacean (Rustユーザが自分たちのことを呼ぶ、冗談めいたニックネーム) たちとチャットできます。 -他にも、素晴らしいリソースとして[ユーザ・フォーラム][users]と[Stack Overflow][stackoverflow]が挙げられます。 +LinuxおよびmacOSでは: + +```console +$ echo $PATH +``` + + + +これらが全て正常であるのに、それでもRustがうまく動かないなら、助力を得られる場所はたくさんあります。 +他のRustacean(Rustユーザが自分たちのことを呼ぶ、冗談めいたニックネーム)たちと交流する方法を[コミュニティページ][community]で探してください。 > 訳注1:Rustaceanについて、いらないかもしれない補足です。[公式Twitter曰く、Rustaceanはcrustaceans(甲殻類)から来ている][twitter]そうです。 > そのため、Rustのマスコットは(非公式らしいですが)[カニ][mascott]。上の会話でCの欠点を削ぎ落としているからcを省いてるの?みたいなことを聞いていますが、 > 違うそうです。検索したら、堅牢性が高いから甲殻類という意見もありますが、真偽は不明です。 > 明日使えるかもしれないトリビアでした。 -> 訳注2:上にある公式Discordは英語話者のコミュニティです。日本語話者のためのコミュニティが[Zulip rust-lang-jpにあり][zulip_jp]、こちらでもRustaceanたちが活発に議論をしています。 +> 訳注2:上にあるコミュニティページはどれも英語話者のコミュニティへのリンク集です。日本語話者のためのコミュニティが[Zulip rust-lang-jpにあり][zulip_jp]、こちらでもRustaceanたちが活発に議論をしています。 > 公式Discord同様、初心者向けの#beginnersチャンネルが存在するので、気軽に質問してみてください。 -[discord]: https://discord.gg/rust-lang -[users]: https://users.rust-lang.org/ -[stackoverflow]: https://stackoverflow.com/questions/tagged/rust [twitter]: https://mobile.twitter.com/rustlang/status/916284650674323457 [mascott]: https://www.slideshare.net/wolf-dog/ss-64026540 [zulip_jp]: https://rust-lang-jp.zulipchat.com + + +### 更新及びアンインストール + + + +`rustup`経由でRustがインストールされたなら、新しくリリースされた版へ更新するのは簡単です。 +シェルから以下の更新スクリプトを実行してください: + +```console +$ rustup update +``` + + + +Rustと`rustup`をアンインストールするには、シェルから以下のアンインストールスクリプトを実行してください: + +```console +$ rustup self uninstall +``` + @@ -234,12 +286,12 @@ Rustが`%PATH%`システム環境変数にあることを確認してくださ ### ローカルのドキュメンテーション -インストールされたRustには、ローカルに複製されたドキュメンテーションのコピーが含まれているので、これをオフラインで閲覧することができます。 +インストールされたRustには、オフラインでドキュメンテーションを閲覧できるように、ドキュメンテーションのローカルコピーが含まれています。 ブラウザでローカルのドキュメンテーションを開くには、`rustup doc`を実行してください。 標準ライブラリにより提供される型や関数がなんなのかや、それをどう使えば良いのかがよくわからないときは、いつでもAPIのドキュメンテーションを検索してみてください! + + +[otherinstall]: https://forge.rust-lang.org/infra/other-installation-methods.html +[install]: https://www.rust-lang.org/tools/install +[visualstudio]: https://visualstudio.microsoft.com/downloads/ +[community]: https://www.rust-lang.org/community diff --git a/src/ch01-02-hello-world.md b/src/ch01-02-hello-world.md index d517eef33..686cbfdb5 100644 --- a/src/ch01-02-hello-world.md +++ b/src/ch01-02-hello-world.md @@ -5,9 +5,9 @@ ## Hello, World! Rustをインストールしたので、最初のRustプログラムを書きましょう。新しい言語を学ぶ際に、 @@ -19,16 +19,17 @@ Rustをインストールしたので、最初のRustプログラムを書きま > no specific demands about your editing or tooling or where your code lives, so > if you prefer to use an integrated development environment (IDE) instead of > the command line, feel free to use your favorite IDE. Many IDEs now have some -> degree of Rust support; check the IDE’s documentation for details. Recently, -> the Rust team has been focusing on enabling great IDE support, and progress -> has been made rapidly on that front! +> degree of Rust support; check the IDE’s documentation for details. The Rust +> team has been focusing on enabling great IDE support via `rust-analyzer`. See +> [Appendix D][devtools] for more details. --> > 注釈: この本は、コマンドラインに基礎的な馴染みがあることを前提にしています。Rustは、編集やツール、 > どこにコードがあるかについて特定の要求をしないので、コマンドラインではなくIDEを使用することを好むのなら、 > どうぞご自由にお気に入りのIDEを使用してください。今では、多くのIDEがなんらかの形でRustをサポートしています; -> 詳しくは、IDEのドキュメンテーションをご覧ください。最近、Rustチームは優れたIDEサポートを有効にすることに注力し、 -> その前線で急激に成果があがっています! +> 詳しくは、IDEのドキュメンテーションをご覧ください。 +> Rustチームは`rust-analyzer`を介して優れたIDEサポートを可能にすることに注力しています。 +> 詳しくは[付録D][devtools]をご覧ください。 端末を開いて以下のコマンドを入力し、*projects*ディレクトリと、 -*projects*ディレクトリ内にHello, world!プロジェクトのディレクトリを作成してください。 +*projects*ディレクトリ内に「Hello, world!」プロジェクトのディレクトリを作成してください。 -LinuxとmacOSなら、こう入力してください: +Linux、macOS、そしてWindows上のPowerShellなら、こう入力してください: -```text +```console $ mkdir ~/projects $ cd ~/projects $ mkdir hello_world @@ -80,19 +81,6 @@ Windowsのcmdなら、こう: > cd hello_world ``` - - -WindowsのPowerShellなら、こう: - -```powershell -> mkdir $env:USERPROFILE\projects -> cd $env:USERPROFILE\projects -> mkdir hello_world -> cd hello_world -``` - @@ -101,13 +89,13 @@ WindowsのPowerShellなら、こう: 次にソースファイルを作り、*main.rs*というファイル名にしてください。Rustのファイルは常に *.rs*という拡張子で終わります。 -ファイル名に2単語以上使っているなら、アンダースコアで区切ってください。例えば、*helloworld.rs*ではなく、 +ファイル名に2単語以上使っているなら、アンダースコアで区切るのが規約です。例えば、*helloworld.rs*ではなく、 *hello_world.rs*を使用してください。 -ファイルを保存し、端末ウィンドウに戻ってください。LinuxかmacOSなら、以下のコマンドを打ってファイルをコンパイルし、 -実行してください: +ファイルを保存し、*~/projects/hello_world*ディレクトリの端末ウィンドウに戻ってください。 +LinuxかmacOSなら、以下のコマンドを打ってファイルをコンパイルし、実行してください: -```text +```console $ rustc main.rs $ ./main Hello, world! @@ -163,16 +152,17 @@ Hello, world! OSに関わらず、`Hello, world!`という文字列が端末に出力されるはずです。この出力が見れないなら、 -「トラブルシューティング」節に立ち戻って、助けを得る方法を参照してください。 +インストールの節の[「トラブルシューティング」][troubleshooting]の部分に立ち戻って、助けを得る方法を参照してください。 `Hello, world!`が確かに出力されたら、おめでとうございます!正式にRustプログラムを書きました。 @@ -185,11 +175,11 @@ Rustプログラマになったのです!ようこそ! ### Rustプログラムの解剖 -Hello, world!プログラムでいま何が起こったのか詳しく確認しましょう。 +この「Hello, world!」プログラムを詳しく再確認しましょう。 こちらがパズルの最初のピースです: ```rust @@ -199,42 +189,41 @@ fn main() { ``` -これらの行でRustで関数を定義しています。`main`関数は特別です: 常に全ての実行可能なRustプログラムで走る最初のコードになります。 -1行目は、引数がなく、何も返さない`main`という関数を宣言しています。引数があるなら、かっこ(`()`)の内部に入ります。 +これらの行は`main`という名前の関数を定義しています。`main`関数は特別です: 常に全ての実行可能なRustプログラムで走る最初のコードになります。 +ここで、1行目は、引数がなく何も返さない`main`という関数を宣言しています。引数があるなら、かっこ(`()`)の内部に入ります。 -また、関数の本体が波括弧(`{}`)に包まれていることにも注目してください。Rustでは、全ての関数本体の周りにこれらが必要になります。 +関数の本体は`{}`に包まれます。Rustでは、全ての関数本体の周りに波括弧が必要になります。 スペースを1つあけて、開き波括弧を関数宣言と同じ行に配置するのがいいスタイルです。 -複数のRustプロジェクトに渡って標準的なスタイルにこだわりたいなら、`rustfmt`を使うことでコードを決まったスタイルに整形できるでしょう。 -Rustチームは、`rustc`のように標準的なRustの配布にこのツールを含んでいるため、既にコンピューターにインストールされているはずです! -詳細は、オンラインのドキュメンテーションを確認してください。 +> 注釈: 複数のRustプロジェクトに渡って標準的なスタイルにこだわりたいなら、`rustfmt`を使うことでコードを決まったスタイルに整形できるでしょう(`rustfmt`の詳細は[付録D][devtools]で)。 +> Rustチームは、`rustc`のように標準的なRustの配布にこのツールを含んでいるため、既にコンピューターにインストールされているはずです! -`main`関数内には、こんなコードがあります: +`main`関数の本体は、こんなコードを抱えています: ```rust println!("Hello, world!"); @@ -242,23 +231,29 @@ Inside the `main` function is the following code: この行が、この小さなプログラムの全作業をしています: テキストを画面に出力するのです。 -ここで気付くべき重要な詳細が4つあります。まず、Rustのスタイルは、タブではなく、4スペースでインデントするということです。 +ここで気付くべき重要な詳細が4つあります。 + +まず、Rustのスタイルは、タブではなく、4スペースでインデントするということです。 + + 2番目に`println!`はRustのマクロを呼び出すということです。代わりに関数を呼んでいたら、 `println`(`!`なし)と入力されているでしょう。Rustのマクロについて詳しくは、第19章で議論します。 -とりあえず、`!`を使用すると、普通の関数ではなくマクロを呼んでいるのだということを知っておくだけでいいでしょう。 +とりあえず、`!`を使用すると、普通の関数ではなくマクロを呼んでいるのだということと、マクロは関数と同じルールには必ずしも従わないということを知っておくだけでいいでしょう。 -Linux、macOS、WindowsのPowerShellなら、シェルで以下のように`ls`コマンドを入力することで実行可能ファイルを見られます: +Linux、macOS、WindowsのPowerShellなら、シェルで`ls`コマンドを入力することで実行可能ファイルを見られます: -```text +```console $ ls main main.rs ``` +LinuxとmacOSでは、2つのファイルが見えるでしょう。 +WindowsのPowerShellでは、CMDを使ったときに見ることになるのと同じ3つのファイルが見えるでしょう。 WindowsのCMDなら、以下のように入力するでしょう: ```cmd @@ -340,29 +339,25 @@ main.rs これは、*.rs*拡張子のソースコードファイル、実行可能ファイル(Windowsなら*main.exe*、他のプラットフォームでは、*main*)、 -そして、CMDを使用しているなら、*.pdb*拡張子のデバッグ情報を含むファイルを表示します。ここから、 +そして、Windowsを使用しているなら、*.pdb*拡張子のデバッグ情報を含むファイルを表示します。ここから、 *main*か*main.exe*を走らせます。このように: -```text +```console $ ./main # or .\main.exe on Windows # または、Widnowsなら.\main.exe ``` -*main.rs*がHello, world!プログラムなら、この行は`Hello, world!`と端末に出力するでしょう。 - - +*main.rs*がHello, world!プログラムなら、この行は`Hello, world!`と端末に出力します。 + +[troubleshooting]: ch01-01-installation.html#トラブルシューティング +[devtools]: appendix-04-useful-development-tools.html diff --git a/src/ch01-03-hello-cargo.md b/src/ch01-03-hello-cargo.md index 8b4284a65..6a9fe8884 100644 --- a/src/ch01-03-hello-cargo.md +++ b/src/ch01-03-hello-cargo.md @@ -19,14 +19,14 @@ CargoはRustのビルドシステム兼パッケージマネージャです。 いままでに書いたようなごく単純なRustプログラムには依存がありません。 -そのため「Hello, world!」プロジェクトをCargoでビルドしても、Cargoの中のコードをビルドする部分しか使わないでしょう。 +「Hello, world!」プロジェクトをCargoでビルドしても、Cargoの中のコードをビルドする部分しか使わないでしょう。 より複雑なRustプログラムを書くようになると依存を追加することになりますが、Cargoを使ってプロジェクトを開始したなら、依存の追加もずっと簡単になります。 Rustプロジェクトの大多数がCargoを使用しているので、これ以降、この本では、あなたもCargoを使用していると想定します。 @@ -63,9 +63,9 @@ determine how to install Cargo separately. Cargoを使って新しいプロジェクトを作成し、元の「Hello, world!」プロジェクトとの違いを見ていきましょう。 @@ -78,12 +78,12 @@ $ cd hello_cargo ``` -最初のコマンドは*hello_cargo*という名の新しいディレクトリを作成します。 +最初のコマンドは*hello_cargo*という名の新しいディレクトリとプロジェクトを作成します。 プロジェクトを*hello_cargo*と名付けたので、Cargoはそれに関連するいくつかのファイルを同名のディレクトリに作成します。 -このファイルは[TOML](https://toml.io)(*Tom's Obvious, Minimal Language*、トムの明確な最小限の言語)形式で、Cargoの設定フォーマットです。 +このファイルは[*TOML*][toml](*Tom's Obvious, Minimal Language*、トムの明確な最小限の言語)形式で、Cargoの設定フォーマットです。 Cargoはリスト1-1で書いたような「Hello, world!」プログラムを生成してくれています。 -これまでのところ、以前のプロジェクトとCargoが生成したプロジェクトの違いは、Cargoがコードを*src*ディレクトリに配置したことと、 +これまでのところ、私たちのプロジェクトとCargoが生成したプロジェクトの違いは、Cargoがコードを*src*ディレクトリに配置したことと、 最上位のディレクトリに*Cargo.toml*設定ファイルがあることです。 このコマンドは実行ファイルを現在のディレクトリではなく、*target/debug/hello_cargo*(Windowsでは*target/debug/hello_cargo.exe*)に作成します。 +デフォルトのビルドはデバッグビルドなので、Cargoはバイナリを*debug*という名前のディレクトリの中に入れます。 以下のコマンドで実行ファイルを実行できます。 ```console $ ./target/debug/hello_cargo # or .\target\debug\hello_cargo.exe on Windows -$ # Windowsでは .\target\debug\hello_cargo.exe + # Windowsでは .\target\debug\hello_cargo.exe Hello, world! ``` @@ -290,7 +294,7 @@ Cargoがその内容を管理してくれます。 先ほどは`cargo build`でプロジェクトをビルドし、`./target/debug/hello_cargo`で実行しました。 @@ -303,15 +307,25 @@ $ cargo run Hello, world! ``` + + +`cargo run`を使ったほうが、`cargo build`を忘れずに実行した後バイナリへのパス全体を使わないといけないのと比較して便利なので、 +ほとんどの開発者は`cargo run`を使います。 + 今回はCargoが`hello_cargo`をコンパイルしていることを示す出力がないことに注目してください。 -Cargoはファイルが変更されていないことに気づいたので、単にバイナリを実行したのです。 +Cargoはファイルが変更されていないことに気づいたので、再ビルドせずに単にバイナリを実行したのです。 もしソースコードを変更していたら、Cargoは実行前にプロジェクトを再ビルドし、以下のような出力が表示されたことでしょう。 ```console @@ -338,16 +352,17 @@ $ cargo check なぜ実行可能ファイルが欲しくないのでしょうか? `cargo check`は実行ファイルを生成するステップを省くことができるので、多くの場合、`cargo build`よりもずっと高速です。 -もし、あなたがコードを書きながら継続的にチェックするのなら、`cargo check`を使えば、そのプロセスを高速化できます! +もし、あなたがコードを書きながら継続的にチェックするのなら、`cargo check`を使えば、プロジェクトのコンパイルがまだ通るか教えてくれるプロセスを高速化できます! そのため多くのRustaceanはプログラムを書きながら定期的に`cargo check`を実行し、コンパイルできるか確かめます。 そして、実行ファイルを使う準備ができたときに`cargo build`を走らせるのです。 @@ -418,13 +433,14 @@ the executable in *target/release*. 単純なプロジェクトでは、Cargoは単に`rustc`を使うことに対してあまり多くの価値を生みません。 しかし、プログラムが複雑になるにつれて、その価値を証明することになるでしょう。 -複数のクレートからなる複雑なプロジェクトでは、Cargoにビルドを調整させるほうがずっと簡単です。 +プログラムが複数のファイルに分かれるほど大きくなったり、依存が必要になってくると、 +Cargoにビルドを調整させるほうがずっと簡単です。 -Cargoの詳細については、[ドキュメント]を参照してください。 - -[ドキュメント]: https://doc.rust-lang.org/cargo/ +Cargoの詳細については、[ドキュメント][cargo]を参照してください。 [installation]: ch01-01-installation.html#インストール +[toml]: https://toml.io [appendix-e]: appendix-05-editions.html +[cargo]: https://doc.rust-lang.org/cargo/ From cc34c09dc4170731771a3b3ccf5d2ed922ec3ce5 Mon Sep 17 00:00:00 2001 From: shinmili Date: Sun, 26 May 2024 12:58:01 +0900 Subject: [PATCH 03/10] =?UTF-8?q?ch02=20=E6=95=B0=E5=BD=93=E3=81=A6?= =?UTF-8?q?=E3=82=B2=E3=83=BC=E3=83=A0=E3=81=AE=E3=83=97=E3=83=AD=E3=82=B0?= =?UTF-8?q?=E3=83=A9=E3=83=9F=E3=83=B3=E3=82=B0=E3=81=AE=E5=92=8C=E8=A8=B3?= =?UTF-8?q?=E3=82=92=E6=9C=80=E6=96=B0=E7=89=88=E3=81=AB=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit rust-lang/book@19c40bfd2d57641d962f3119a1c343355f1b3c5e --- .../listing-02-01/src/main.rs | 2 +- .../listing-02-02/Cargo.lock | 40 +- .../listing-02-02/Cargo.toml | 2 +- .../listing-02-02/src/main.rs | 2 +- .../listing-02-03/Cargo.lock | 16 +- .../listing-02-03/Cargo.toml | 2 +- .../listing-02-03/src/main.rs | 6 +- .../listing-02-04/Cargo.lock | 16 +- .../listing-02-04/Cargo.toml | 2 +- .../listing-02-04/output.txt | 40 +- .../listing-02-04/src/main.rs | 6 +- .../listing-02-05/Cargo.lock | 16 +- .../listing-02-05/Cargo.toml | 2 +- .../listing-02-05/src/main.rs | 6 +- .../listing-02-06/Cargo.lock | 16 +- .../listing-02-06/Cargo.toml | 2 +- .../listing-02-06/src/main.rs | 4 +- .../no-listing-01-cargo-new/Cargo.lock | 3 +- .../no-listing-02-without-expect/output.txt | 11 +- .../no-listing-02-without-expect/src/main.rs | 2 +- .../Cargo.lock | 16 +- .../Cargo.toml | 2 +- .../src/main.rs | 9 +- .../no-listing-04-looping/Cargo.lock | 16 +- .../no-listing-04-looping/Cargo.toml | 2 +- .../no-listing-04-looping/src/main.rs | 6 +- .../no-listing-05-quitting/Cargo.lock | 16 +- .../no-listing-05-quitting/Cargo.toml | 2 +- .../no-listing-05-quitting/src/main.rs | 6 +- src/ch02-00-guessing-game-tutorial.md | 553 ++++++++++-------- src/ch09-02-recoverable-errors-with-result.md | 2 +- 31 files changed, 402 insertions(+), 424 deletions(-) diff --git a/listings/ch02-guessing-game-tutorial/listing-02-01/src/main.rs b/listings/ch02-guessing-game-tutorial/listing-02-01/src/main.rs index 9f38aa25c..453ce8506 100644 --- a/listings/ch02-guessing-game-tutorial/listing-02-01/src/main.rs +++ b/listings/ch02-guessing-game-tutorial/listing-02-01/src/main.rs @@ -25,7 +25,7 @@ fn main() { // ANCHOR_END: expect // ANCHOR: print_guess - println!("You guessed: {}", guess); // 次のように予想しました: {} + println!("You guessed: {guess}"); // 次のように予想しました: {guess} // ANCHOR_END: print_guess } // ANCHOR: all diff --git a/listings/ch02-guessing-game-tutorial/listing-02-02/Cargo.lock b/listings/ch02-guessing-game-tutorial/listing-02-02/Cargo.lock index 0a2f222c2..0fb52b33c 100644 --- a/listings/ch02-guessing-game-tutorial/listing-02-02/Cargo.lock +++ b/listings/ch02-guessing-game-tutorial/listing-02-02/Cargo.lock @@ -1,5 +1,7 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] name = "cfg-if" version = "1.0.0" @@ -8,9 +10,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "getrandom" -version = "0.2.2" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8" +checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" dependencies = [ "cfg-if", "libc", @@ -26,33 +28,32 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.86" +version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7282d924be3275cec7f6756ff4121987bc6481325397dde6ba3e7802b1a8b1c" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" [[package]] name = "ppv-lite86" -version = "0.2.10" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "rand" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", "rand_chacha", "rand_core", - "rand_hc", ] [[package]] name = "rand_chacha" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e12735cf05c9e10bf21534da50a147b924d555dc7a547c42e6bb2d5b6017ae0d" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", "rand_core", @@ -60,24 +61,15 @@ dependencies = [ [[package]] name = "rand_core" -version = "0.6.2" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34cf66eb183df1c5876e2dcf6b13d57340741e8dc255b48e40a26de954d06ae7" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ "getrandom", ] -[[package]] -name = "rand_hc" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73" -dependencies = [ - "rand_core", -] - [[package]] name = "wasi" -version = "0.10.2+wasi-snapshot-preview1" +version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" diff --git a/listings/ch02-guessing-game-tutorial/listing-02-02/Cargo.toml b/listings/ch02-guessing-game-tutorial/listing-02-02/Cargo.toml index cc63f6f02..7eda67aea 100644 --- a/listings/ch02-guessing-game-tutorial/listing-02-02/Cargo.toml +++ b/listings/ch02-guessing-game-tutorial/listing-02-02/Cargo.toml @@ -6,4 +6,4 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -rand = "0.8.3" +rand = "0.8.5" diff --git a/listings/ch02-guessing-game-tutorial/listing-02-02/src/main.rs b/listings/ch02-guessing-game-tutorial/listing-02-02/src/main.rs index 60fb2a8e5..b35ed0f2f 100644 --- a/listings/ch02-guessing-game-tutorial/listing-02-02/src/main.rs +++ b/listings/ch02-guessing-game-tutorial/listing-02-02/src/main.rs @@ -11,5 +11,5 @@ fn main() { .read_line(&mut guess) .expect("Failed to read line"); - println!("You guessed: {}", guess); + println!("You guessed: {guess}"); } diff --git a/listings/ch02-guessing-game-tutorial/listing-02-03/Cargo.lock b/listings/ch02-guessing-game-tutorial/listing-02-03/Cargo.lock index 0a2f222c2..2ae9e459e 100644 --- a/listings/ch02-guessing-game-tutorial/listing-02-03/Cargo.lock +++ b/listings/ch02-guessing-game-tutorial/listing-02-03/Cargo.lock @@ -1,5 +1,7 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] name = "cfg-if" version = "1.0.0" @@ -38,14 +40,13 @@ checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" [[package]] name = "rand" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", "rand_chacha", "rand_core", - "rand_hc", ] [[package]] @@ -67,15 +68,6 @@ dependencies = [ "getrandom", ] -[[package]] -name = "rand_hc" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73" -dependencies = [ - "rand_core", -] - [[package]] name = "wasi" version = "0.10.2+wasi-snapshot-preview1" diff --git a/listings/ch02-guessing-game-tutorial/listing-02-03/Cargo.toml b/listings/ch02-guessing-game-tutorial/listing-02-03/Cargo.toml index cc63f6f02..7eda67aea 100644 --- a/listings/ch02-guessing-game-tutorial/listing-02-03/Cargo.toml +++ b/listings/ch02-guessing-game-tutorial/listing-02-03/Cargo.toml @@ -6,4 +6,4 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -rand = "0.8.3" +rand = "0.8.5" diff --git a/listings/ch02-guessing-game-tutorial/listing-02-03/src/main.rs b/listings/ch02-guessing-game-tutorial/listing-02-03/src/main.rs index 164bd46e8..bdacf04b5 100644 --- a/listings/ch02-guessing-game-tutorial/listing-02-03/src/main.rs +++ b/listings/ch02-guessing-game-tutorial/listing-02-03/src/main.rs @@ -8,10 +8,10 @@ fn main() { println!("Guess the number!"); // ANCHOR: ch07-04 - let secret_number = rand::thread_rng().gen_range(1..101); + let secret_number = rand::thread_rng().gen_range(1..=100); // ANCHOR_END: ch07-04 - println!("The secret number is: {}", secret_number); //秘密の数字は次の通り: {} + println!("The secret number is: {secret_number}"); //秘密の数字は次の通り: {secret_number} println!("Please input your guess."); @@ -21,7 +21,7 @@ fn main() { .read_line(&mut guess) .expect("Failed to read line"); - println!("You guessed: {}", guess); + println!("You guessed: {guess}"); // ANCHOR: ch07-04 } // ANCHOR_END: ch07-04 diff --git a/listings/ch02-guessing-game-tutorial/listing-02-04/Cargo.lock b/listings/ch02-guessing-game-tutorial/listing-02-04/Cargo.lock index 0a2f222c2..2ae9e459e 100644 --- a/listings/ch02-guessing-game-tutorial/listing-02-04/Cargo.lock +++ b/listings/ch02-guessing-game-tutorial/listing-02-04/Cargo.lock @@ -1,5 +1,7 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] name = "cfg-if" version = "1.0.0" @@ -38,14 +40,13 @@ checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" [[package]] name = "rand" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", "rand_chacha", "rand_core", - "rand_hc", ] [[package]] @@ -67,15 +68,6 @@ dependencies = [ "getrandom", ] -[[package]] -name = "rand_hc" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73" -dependencies = [ - "rand_core", -] - [[package]] name = "wasi" version = "0.10.2+wasi-snapshot-preview1" diff --git a/listings/ch02-guessing-game-tutorial/listing-02-04/Cargo.toml b/listings/ch02-guessing-game-tutorial/listing-02-04/Cargo.toml index cc63f6f02..7eda67aea 100644 --- a/listings/ch02-guessing-game-tutorial/listing-02-04/Cargo.toml +++ b/listings/ch02-guessing-game-tutorial/listing-02-04/Cargo.toml @@ -6,4 +6,4 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -rand = "0.8.3" +rand = "0.8.5" diff --git a/listings/ch02-guessing-game-tutorial/listing-02-04/output.txt b/listings/ch02-guessing-game-tutorial/listing-02-04/output.txt index 0c4b6f929..91598470c 100644 --- a/listings/ch02-guessing-game-tutorial/listing-02-04/output.txt +++ b/listings/ch02-guessing-game-tutorial/listing-02-04/output.txt @@ -5,42 +5,22 @@ $ cargo build Compiling ppv-lite86 v0.2.10 Compiling rand_core v0.6.2 Compiling rand_chacha v0.3.0 - Compiling rand v0.8.3 + Compiling rand v0.8.5 Compiling guessing_game v0.1.0 (file:///projects/guessing_game) error[E0308]: mismatched types (型が合いません) --> src/main.rs:22:21 | 22 | match guess.cmp(&secret_number) { - | ^^^^^^^^^^^^^^ expected struct `String`, found integer - | (構造体`std::string::String`を予期したけど、整数型変数が見つかりました) + | --- ^^^^^^^^^^^^^^ expected `&String`, found `&{integer}` + | | (`&String`を予期したけど、`&{integer}`が見つかりました) + | | + | arguments to this method are incorrect + | (このメソッドへの引数が正しくありません) | = note: expected reference `&String` found reference `&{integer}` +note: method defined here + --> /rustc/07dca489ac2d933c78d3c5158e3f43beefeb02ce/library/core/src/cmp.rs:814:8 -error[E0283]: type annotations needed for `{integer}` - --> src/main.rs:8:44 - | -8 | let secret_number = rand::thread_rng().gen_range(1..101); - | ------------- ^^^^^^^^^ cannot infer type for type `{integer}` - | | - | consider giving `secret_number` a type - | - = note: multiple `impl`s satisfying `{integer}: SampleUniform` found in the `rand` crate: - - impl SampleUniform for i128; - - impl SampleUniform for i16; - - impl SampleUniform for i32; - - impl SampleUniform for i64; - and 8 more -note: required by a bound in `gen_range` - --> /Users/carolnichols/.cargo/registry/src/github.com-1ecc6299db9ec823/rand-0.8.3/src/rng.rs:129:12 - | -129 | T: SampleUniform, - | ^^^^^^^^^^^^^ required by this bound in `gen_range` -help: consider specifying the type arguments in the function call - | -8 | let secret_number = rand::thread_rng().gen_range::(1..101); - | ++++++++ - -Some errors have detailed explanations: E0283, E0308. -For more information about an error, try `rustc --explain E0283`. -error: could not compile `guessing_game` due to 2 previous errors (先の2つのエラーのため、`guessing_game`をコンパイルできませんでした) +For more information about this error, try `rustc --explain E0308`. +error: could not compile `guessing_game` (bin "guessing_game") due to 1 previous error (先の1つのエラーのため、`guessing_game` (bin "guessing_game") をコンパイルできませんでした) diff --git a/listings/ch02-guessing-game-tutorial/listing-02-04/src/main.rs b/listings/ch02-guessing-game-tutorial/listing-02-04/src/main.rs index d22864972..eadbaf9f2 100644 --- a/listings/ch02-guessing-game-tutorial/listing-02-04/src/main.rs +++ b/listings/ch02-guessing-game-tutorial/listing-02-04/src/main.rs @@ -8,9 +8,9 @@ fn main() { // ANCHOR_END: here println!("Guess the number!"); - let secret_number = rand::thread_rng().gen_range(1..101); + let secret_number = rand::thread_rng().gen_range(1..=100); - println!("The secret number is: {}", secret_number); + println!("The secret number is: {secret_number}"); println!("Please input your guess."); @@ -21,7 +21,7 @@ fn main() { .expect("Failed to read line"); // ANCHOR: here - println!("You guessed: {}", guess); + println!("You guessed: {guess}"); match guess.cmp(&secret_number) { Ordering::Less => println!("Too small!"), //小さすぎ! diff --git a/listings/ch02-guessing-game-tutorial/listing-02-05/Cargo.lock b/listings/ch02-guessing-game-tutorial/listing-02-05/Cargo.lock index 0a2f222c2..2ae9e459e 100644 --- a/listings/ch02-guessing-game-tutorial/listing-02-05/Cargo.lock +++ b/listings/ch02-guessing-game-tutorial/listing-02-05/Cargo.lock @@ -1,5 +1,7 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] name = "cfg-if" version = "1.0.0" @@ -38,14 +40,13 @@ checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" [[package]] name = "rand" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", "rand_chacha", "rand_core", - "rand_hc", ] [[package]] @@ -67,15 +68,6 @@ dependencies = [ "getrandom", ] -[[package]] -name = "rand_hc" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73" -dependencies = [ - "rand_core", -] - [[package]] name = "wasi" version = "0.10.2+wasi-snapshot-preview1" diff --git a/listings/ch02-guessing-game-tutorial/listing-02-05/Cargo.toml b/listings/ch02-guessing-game-tutorial/listing-02-05/Cargo.toml index cc63f6f02..7eda67aea 100644 --- a/listings/ch02-guessing-game-tutorial/listing-02-05/Cargo.toml +++ b/listings/ch02-guessing-game-tutorial/listing-02-05/Cargo.toml @@ -6,4 +6,4 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -rand = "0.8.3" +rand = "0.8.5" diff --git a/listings/ch02-guessing-game-tutorial/listing-02-05/src/main.rs b/listings/ch02-guessing-game-tutorial/listing-02-05/src/main.rs index 41a4cdd14..12f497e18 100644 --- a/listings/ch02-guessing-game-tutorial/listing-02-05/src/main.rs +++ b/listings/ch02-guessing-game-tutorial/listing-02-05/src/main.rs @@ -5,9 +5,9 @@ use std::io; fn main() { println!("Guess the number!"); - let secret_number = rand::thread_rng().gen_range(1..101); + let secret_number = rand::thread_rng().gen_range(1..=100); - println!("The secret number is: {}", secret_number); + println!("The secret number is: {secret_number}"); loop { println!("Please input your guess."); @@ -28,7 +28,7 @@ fn main() { }; // ANCHOR_END: ch19 - println!("You guessed: {}", guess); + println!("You guessed: {guess}"); // --snip-- // ANCHOR_END: here diff --git a/listings/ch02-guessing-game-tutorial/listing-02-06/Cargo.lock b/listings/ch02-guessing-game-tutorial/listing-02-06/Cargo.lock index 0a2f222c2..2ae9e459e 100644 --- a/listings/ch02-guessing-game-tutorial/listing-02-06/Cargo.lock +++ b/listings/ch02-guessing-game-tutorial/listing-02-06/Cargo.lock @@ -1,5 +1,7 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] name = "cfg-if" version = "1.0.0" @@ -38,14 +40,13 @@ checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" [[package]] name = "rand" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", "rand_chacha", "rand_core", - "rand_hc", ] [[package]] @@ -67,15 +68,6 @@ dependencies = [ "getrandom", ] -[[package]] -name = "rand_hc" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73" -dependencies = [ - "rand_core", -] - [[package]] name = "wasi" version = "0.10.2+wasi-snapshot-preview1" diff --git a/listings/ch02-guessing-game-tutorial/listing-02-06/Cargo.toml b/listings/ch02-guessing-game-tutorial/listing-02-06/Cargo.toml index cc63f6f02..7eda67aea 100644 --- a/listings/ch02-guessing-game-tutorial/listing-02-06/Cargo.toml +++ b/listings/ch02-guessing-game-tutorial/listing-02-06/Cargo.toml @@ -6,4 +6,4 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -rand = "0.8.3" +rand = "0.8.5" diff --git a/listings/ch02-guessing-game-tutorial/listing-02-06/src/main.rs b/listings/ch02-guessing-game-tutorial/listing-02-06/src/main.rs index 30859c70e..7fcbb99fb 100644 --- a/listings/ch02-guessing-game-tutorial/listing-02-06/src/main.rs +++ b/listings/ch02-guessing-game-tutorial/listing-02-06/src/main.rs @@ -5,7 +5,7 @@ use std::io; fn main() { println!("Guess the number!"); - let secret_number = rand::thread_rng().gen_range(1..101); + let secret_number = rand::thread_rng().gen_range(1..=100); loop { println!("Please input your guess."); @@ -21,7 +21,7 @@ fn main() { Err(_) => continue, }; - println!("You guessed: {}", guess); + println!("You guessed: {guess}"); match guess.cmp(&secret_number) { Ordering::Less => println!("Too small!"), diff --git a/listings/ch02-guessing-game-tutorial/no-listing-01-cargo-new/Cargo.lock b/listings/ch02-guessing-game-tutorial/no-listing-01-cargo-new/Cargo.lock index 5802b7dc9..ee5d79095 100644 --- a/listings/ch02-guessing-game-tutorial/no-listing-01-cargo-new/Cargo.lock +++ b/listings/ch02-guessing-game-tutorial/no-listing-01-cargo-new/Cargo.lock @@ -1,6 +1,7 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] name = "guessing_game" version = "0.1.0" - diff --git a/listings/ch02-guessing-game-tutorial/no-listing-02-without-expect/output.txt b/listings/ch02-guessing-game-tutorial/no-listing-02-without-expect/output.txt index 0c102c8c7..0905fd9d1 100644 --- a/listings/ch02-guessing-game-tutorial/no-listing-02-without-expect/output.txt +++ b/listings/ch02-guessing-game-tutorial/no-listing-02-without-expect/output.txt @@ -1,14 +1,19 @@ $ cargo build Compiling guessing_game v0.1.0 (file:///projects/guessing_game) warning: unused `Result` that must be used -(警告: 使用されなければならない`std::result::Result`が使用されていません) +(警告: 使用されなければならない`Result`が使用されていません) --> src/main.rs:10:5 | 10 | io::stdin().read_line(&mut guess); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `#[warn(unused_must_use)]` on by default = note: this `Result` may be an `Err` variant, which should be handled + = note: `#[warn(unused_must_use)]` on by default +help: use `let _ = ...` to ignore the resulting value +(ヘルプ: 結果の値を無視するには `let _ = ...` を使用してください) + | +10 | let _ = io::stdin().read_line(&mut guess); + | +++++++ warning: `guessing_game` (bin "guessing_game") generated 1 warning Finished dev [unoptimized + debuginfo] target(s) in 0.59s diff --git a/listings/ch02-guessing-game-tutorial/no-listing-02-without-expect/src/main.rs b/listings/ch02-guessing-game-tutorial/no-listing-02-without-expect/src/main.rs index aaf90bd65..51046016f 100644 --- a/listings/ch02-guessing-game-tutorial/no-listing-02-without-expect/src/main.rs +++ b/listings/ch02-guessing-game-tutorial/no-listing-02-without-expect/src/main.rs @@ -9,5 +9,5 @@ fn main() { io::stdin().read_line(&mut guess); - println!("You guessed: {}", guess); + println!("You guessed: {guess}"); } diff --git a/listings/ch02-guessing-game-tutorial/no-listing-03-convert-string-to-number/Cargo.lock b/listings/ch02-guessing-game-tutorial/no-listing-03-convert-string-to-number/Cargo.lock index 0a2f222c2..2ae9e459e 100644 --- a/listings/ch02-guessing-game-tutorial/no-listing-03-convert-string-to-number/Cargo.lock +++ b/listings/ch02-guessing-game-tutorial/no-listing-03-convert-string-to-number/Cargo.lock @@ -1,5 +1,7 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] name = "cfg-if" version = "1.0.0" @@ -38,14 +40,13 @@ checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" [[package]] name = "rand" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", "rand_chacha", "rand_core", - "rand_hc", ] [[package]] @@ -67,15 +68,6 @@ dependencies = [ "getrandom", ] -[[package]] -name = "rand_hc" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73" -dependencies = [ - "rand_core", -] - [[package]] name = "wasi" version = "0.10.2+wasi-snapshot-preview1" diff --git a/listings/ch02-guessing-game-tutorial/no-listing-03-convert-string-to-number/Cargo.toml b/listings/ch02-guessing-game-tutorial/no-listing-03-convert-string-to-number/Cargo.toml index cc63f6f02..7eda67aea 100644 --- a/listings/ch02-guessing-game-tutorial/no-listing-03-convert-string-to-number/Cargo.toml +++ b/listings/ch02-guessing-game-tutorial/no-listing-03-convert-string-to-number/Cargo.toml @@ -6,4 +6,4 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -rand = "0.8.3" +rand = "0.8.5" diff --git a/listings/ch02-guessing-game-tutorial/no-listing-03-convert-string-to-number/src/main.rs b/listings/ch02-guessing-game-tutorial/no-listing-03-convert-string-to-number/src/main.rs index cd0962ce9..a4af2240f 100644 --- a/listings/ch02-guessing-game-tutorial/no-listing-03-convert-string-to-number/src/main.rs +++ b/listings/ch02-guessing-game-tutorial/no-listing-03-convert-string-to-number/src/main.rs @@ -5,9 +5,9 @@ use std::io; fn main() { println!("Guess the number!"); - let secret_number = rand::thread_rng().gen_range(1..101); + let secret_number = rand::thread_rng().gen_range(1..=100); - println!("The secret number is: {}", secret_number); + println!("The secret number is: {secret_number}"); println!("Please input your guess."); @@ -20,10 +20,9 @@ fn main() { .read_line(&mut guess) .expect("Failed to read line"); - let guess: u32 = guess.trim().parse() - .expect("Please type a number!"); //数値を入力してください! + let guess: u32 = guess.trim().parse().expect("Please type a number!"); //数値を入力してください! - println!("You guessed: {}", guess); + println!("You guessed: {guess}"); match guess.cmp(&secret_number) { Ordering::Less => println!("Too small!"), diff --git a/listings/ch02-guessing-game-tutorial/no-listing-04-looping/Cargo.lock b/listings/ch02-guessing-game-tutorial/no-listing-04-looping/Cargo.lock index 0a2f222c2..2ae9e459e 100644 --- a/listings/ch02-guessing-game-tutorial/no-listing-04-looping/Cargo.lock +++ b/listings/ch02-guessing-game-tutorial/no-listing-04-looping/Cargo.lock @@ -1,5 +1,7 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] name = "cfg-if" version = "1.0.0" @@ -38,14 +40,13 @@ checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" [[package]] name = "rand" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", "rand_chacha", "rand_core", - "rand_hc", ] [[package]] @@ -67,15 +68,6 @@ dependencies = [ "getrandom", ] -[[package]] -name = "rand_hc" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73" -dependencies = [ - "rand_core", -] - [[package]] name = "wasi" version = "0.10.2+wasi-snapshot-preview1" diff --git a/listings/ch02-guessing-game-tutorial/no-listing-04-looping/Cargo.toml b/listings/ch02-guessing-game-tutorial/no-listing-04-looping/Cargo.toml index cc63f6f02..7eda67aea 100644 --- a/listings/ch02-guessing-game-tutorial/no-listing-04-looping/Cargo.toml +++ b/listings/ch02-guessing-game-tutorial/no-listing-04-looping/Cargo.toml @@ -6,4 +6,4 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -rand = "0.8.3" +rand = "0.8.5" diff --git a/listings/ch02-guessing-game-tutorial/no-listing-04-looping/src/main.rs b/listings/ch02-guessing-game-tutorial/no-listing-04-looping/src/main.rs index 61a5dc018..f97d1c58c 100644 --- a/listings/ch02-guessing-game-tutorial/no-listing-04-looping/src/main.rs +++ b/listings/ch02-guessing-game-tutorial/no-listing-04-looping/src/main.rs @@ -5,12 +5,12 @@ use std::io; fn main() { println!("Guess the number!"); - let secret_number = rand::thread_rng().gen_range(1..101); + let secret_number = rand::thread_rng().gen_range(1..=100); // ANCHOR: here // --snip-- - println!("The secret number is: {}", secret_number); + println!("The secret number is: {secret_number}"); loop { println!("Please input your guess."); @@ -27,7 +27,7 @@ fn main() { let guess: u32 = guess.trim().parse().expect("Please type a number!"); - println!("You guessed: {}", guess); + println!("You guessed: {guess}"); // ANCHOR: here match guess.cmp(&secret_number) { diff --git a/listings/ch02-guessing-game-tutorial/no-listing-05-quitting/Cargo.lock b/listings/ch02-guessing-game-tutorial/no-listing-05-quitting/Cargo.lock index 0a2f222c2..2ae9e459e 100644 --- a/listings/ch02-guessing-game-tutorial/no-listing-05-quitting/Cargo.lock +++ b/listings/ch02-guessing-game-tutorial/no-listing-05-quitting/Cargo.lock @@ -1,5 +1,7 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] name = "cfg-if" version = "1.0.0" @@ -38,14 +40,13 @@ checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" [[package]] name = "rand" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", "rand_chacha", "rand_core", - "rand_hc", ] [[package]] @@ -67,15 +68,6 @@ dependencies = [ "getrandom", ] -[[package]] -name = "rand_hc" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73" -dependencies = [ - "rand_core", -] - [[package]] name = "wasi" version = "0.10.2+wasi-snapshot-preview1" diff --git a/listings/ch02-guessing-game-tutorial/no-listing-05-quitting/Cargo.toml b/listings/ch02-guessing-game-tutorial/no-listing-05-quitting/Cargo.toml index cc63f6f02..7eda67aea 100644 --- a/listings/ch02-guessing-game-tutorial/no-listing-05-quitting/Cargo.toml +++ b/listings/ch02-guessing-game-tutorial/no-listing-05-quitting/Cargo.toml @@ -6,4 +6,4 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -rand = "0.8.3" +rand = "0.8.5" diff --git a/listings/ch02-guessing-game-tutorial/no-listing-05-quitting/src/main.rs b/listings/ch02-guessing-game-tutorial/no-listing-05-quitting/src/main.rs index 3f8e8b771..def0a0e7e 100644 --- a/listings/ch02-guessing-game-tutorial/no-listing-05-quitting/src/main.rs +++ b/listings/ch02-guessing-game-tutorial/no-listing-05-quitting/src/main.rs @@ -5,9 +5,9 @@ use std::io; fn main() { println!("Guess the number!"); - let secret_number = rand::thread_rng().gen_range(1..101); + let secret_number = rand::thread_rng().gen_range(1..=100); - println!("The secret number is: {}", secret_number); + println!("The secret number is: {secret_number}"); loop { println!("Please input your guess."); @@ -20,7 +20,7 @@ fn main() { let guess: u32 = guess.trim().parse().expect("Please type a number!"); - println!("You guessed: {}", guess); + println!("You guessed: {guess}"); // ANCHOR: here // --snip-- diff --git a/src/ch02-00-guessing-game-tutorial.md b/src/ch02-00-guessing-game-tutorial.md index b90da438d..ed1a080f9 100644 --- a/src/ch02-00-guessing-game-tutorial.md +++ b/src/ch02-00-guessing-game-tutorial.md @@ -8,15 +8,15 @@ Let’s jump into Rust by working through a hands-on project together! This chapter introduces you to a few common Rust concepts by showing you how to use them in a real program. You’ll learn about `let`, `match`, methods, associated -functions, using external crates, and more! In the following chapters, we’ll -explore these ideas in more detail. In this chapter, you’ll practice the +functions, external crates, and more! In the following chapters, we’ll explore +these ideas in more detail. In this chapter, you’ll just practice the fundamentals. --> ハンズオン形式のプロジェクトに一緒に取り組むことで、Rustの世界に飛び込んでみましょう!  この章ではRustの一般的な概念を、実際のプログラムでの使い方を示しながら紹介します。 -`let`、`match`、メソッド、関連関数、外部クレートの使いかたなどについて学びます!  -これらについての詳細は後続の章で取り上げますので、この章では基本的なところを練習します。 +`let`、`match`、メソッド、関連関数、外部クレートなどについて学びます!  +これらについての詳細は後続の章で取り上げますので、この章では基本的なところだけを練習します。 + @@ -166,8 +175,8 @@ prints it このコードには多くの情報が詰め込まれています。 @@ -180,9 +189,9 @@ standard library, known as `std`: ``` Rustはデフォルトで、標準ライブラリで定義されているアイテムの中のいくつかを、すべてのプログラムのスコープに取り込みます。 @@ -198,8 +207,6 @@ user input. 使いたい型がpreludeにない場合は、その型を`use`文で明示的にスコープに入れる必要があります。 `std::io`ライブラリを`use`すると、ユーザ入力を受け付ける機能など(入出力に関する)多くの便利な機能が利用できるようになります。 -[prelude]: https://doc.rust-lang.org/std/prelude/index.html - `fn`構文は関数を新しく宣言し、かっこの`()`は引数がないことを示し、波括弧の`{`は関数の本体を開始します。 @@ -270,13 +277,15 @@ let apples = 5; この行では`apples`という名前の新しい変数を作成し`5`という値に束縛しています。 -Rustでは変数はデフォルトで不変(immutable)になります。 +Rustでは変数はデフォルトで不変(immutable)で、これは一度変数に値を与えたらその値は変わらないという意味です。 この概念については第3章の[「変数と可変性」][variables-and-mutability]の節で詳しく説明します。 変数を可変(mutable)にするには、変数名の前に`mut`をつけます。 @@ -299,7 +308,7 @@ let mut bananas = 5; // mutable @@ -359,20 +366,19 @@ input: ``` -もし、プログラムの最初に`use std::io`と書いて`io`ライブラリをインポートしていなかったとしても、`std::io::stdin`のように呼び出せば、この関数を利用できます。 +もし、プログラムの最初に`use std::io;`と書いて`io`ライブラリをインポートしていなかったとしても、`std::io::stdin`のように呼び出せば、この関数を利用できます。 `stdin`関数はターミナルの標準入力へのハンドルを表す型である[`std::io::Stdin`][iostdin]のインスタンスを返します。 -[iostdin]: https://doc.rust-lang.org/std/io/struct.Stdin.html - + + + この`&`は、この引数が*参照*であることを示し、これによりコードの複数の部分が同じデータにアクセスしても、そのデータを何度もメモリにコピーしなくて済みます。 参照は複雑な機能(訳注:一部のプログラム言語では正しく使うのが難しい機能)ですが、Rustの大きな利点の一つは参照を安全かつ簡単に使用できることです。 このプログラムを完成させるのに、そのような詳細を知る必要はないでしょう。 @@ -408,15 +417,15 @@ thoroughly.) (参照については第4章でより詳しく説明します) -### `Result`型で失敗の可能性を扱う +### `Result`で失敗の可能性を扱う まだ、このコードの行は終わってません。 @@ -450,44 +459,30 @@ discuss what this line does. -前述したように、`read_line`メソッドは渡された文字列にユーザが入力したものを入れます。 -しかし、同時に値(この場合は[`io::Result`][ioresult])も返します。 -Rustの標準ライブラリには`Result`という名前の型がいくつかあります。 -汎用の[`Result`][result]と、`io::Result`といったサブモジュール用の特殊な型などです。 -これらの`Result`型は[*列挙型*][enums]になります。 -列挙型は*enum*とも呼ばれ、取りうる値として決まった数の*列挙子*(variant)を持ちます。 -列挙型はよく`match`と一緒に使われます。 -これは条件式の一種で、評価時に、列挙型の値がどの列挙子であるかに基づいて異なるコードを実行できるという便利なものです。 - -[ioresult]: https://doc.rust-lang.org/std/io/type.Result.html -[result]: https://doc.rust-lang.org/std/result/enum.Result.html +前述したように、`read_line`メソッドは渡された文字列にユーザが入力したものを入れますが、同時に`Result`値も返します。 +`Result`は[*列挙型*][enums]、または*enum*ともよく呼ばれるもののひとつです。 +列挙型は、複数の取りうる状態の中からどれか一つになることができる型です。 +私たちはこのそれぞれの取りうる状態のことを*列挙子* (variant) と呼びます。 -enumについては第6章で詳しく説明します。 +enumについては[第6章][enums]で詳しく説明します。 これらの`Result`型の目的は、エラー処理に関わる情報を符号化(エンコード)することです。 -[enums]: ch06-00-enums.html - `Result`の列挙子は`Ok`か`Err`です。 @@ -496,25 +491,24 @@ why the operation failed. `Result`型の値にも、他の型と同様にメソッドが定義されています。 -`io::Result`のインスタンスには[`expect`メソッド][expect]がありますので、これを呼び出せます。 -この`io::Result`インスタンスが`Err`の値の場合、`expect`メソッドはプログラムをクラッシュさせ、引数として渡されたメッセージを表示します。 +`Result`のインスタンスには[`expect`メソッド][expect]がありますので、これを呼び出せます。 +この`Result`インスタンスが`Err`の値の場合、`expect`メソッドはプログラムをクラッシュさせ、引数として渡されたメッセージを表示します。 `read_line`メソッドが`Err`を返したら、それはおそらく基礎となるオペレーティング・システムに起因するものでしょう。 -もしこの`io::Result`オブジェクトが`Ok`値の場合、`expect`メソッドは`Ok`列挙子が保持する戻り値を取り出して、その値だけを返してくれます。 +もしこの`Result`オブジェクトが`Ok`値の場合、`expect`メソッドは`Ok`列挙子が保持する戻り値を取り出して、その値だけを返してくれます。 こうして私たちはその値を使うことができるわけです。 今回の場合、その値はユーザ入力のバイト数になります。 -[expect]: https://doc.rust-lang.org/std/result/enum.Result.html#method.expect - @@ -533,13 +527,13 @@ indicating that the program hasn’t handled a possible error. Rustは私たちが`read_line`から返された`Result`値を使用していないことを警告し、これはプログラムがエラーの可能性に対処していないことを示します。 -警告を抑制する正しい方法は実際にエラー処理を書くことです。 +警告を抑制する正しい方法は実際にエラー処理コードを書くことです。 しかし、現時点では問題が起きたときにこのプログラムをクラッシュさせたいだけなので、`expect`が使えるわけです。 エラーからの回復については第9章で学びます。 @@ -563,31 +557,33 @@ the code so far: この行はユーザの入力を現在保持している文字列を表示します。 一組の波括弧の`{}`はプレースホルダーです。 `{}`は値を所定の場所に保持する小さなカニのはさみだと考えてください。 -波括弧をいくつか使えば複数の値を表示できます。 -最初の波括弧の組はフォーマット文字列のあとに並んだ最初の値に対応し、2組目は2番目の値、というように続いていきます。 -一回の`println!`の呼び出しで複数の値を表示するなら次のようになります。 +変数の値を表示するときは、変数名を波括弧の中に入れればよいです。 +式の評価結果を表示するときは、フォーマット文字列の中に空の波括弧を置き、それぞれの空の波括弧プレースホルダに表示する式を同じ順で、カンマ区切りリストにして続けてください。 +一回の`println!`の呼び出しで変数と式の結果を表示するなら次のようになります。 ```rust let x = 5; let y = 10; -println!("x = {} and y = {}", x, y); +println!("x = {x} and y + 2 = {}", y + 2); ``` -このコードは`x = 5 and y = 10`と表示するでしょう。 +このコードは`x = 5 and y + 2 = 12`と表示するでしょう。 ```console $ cargo run @@ -642,8 +643,6 @@ said functionality. Rustの標準ライブラリには、まだ乱数の機能は含まれていません。 ですが、Rustの開発チームがこの機能を持つ[`rand`クレート][randcrate]を提供してくれています。 -[randcrate]: https://crates.io/crates/rand - @@ -653,8 +652,8 @@ Rustの標準ライブラリには、まだ乱数の機能は含まれていま クレートはRustソースコードを集めたものであることを思い出してください。 @@ -666,17 +665,22 @@ programs, and can’t be executed on its own. Cargo’s coordination of external crates is where Cargo really shines. Before we can write code that uses `rand`, we need to modify the *Cargo.toml* file to include the `rand` crate as a dependency. Open that file now and add the -following line to the bottom beneath the `[dependencies]` section header that +following line to the bottom, beneath the `[dependencies]` section header that Cargo created for you. Be sure to specify `rand` exactly as we have here, with -this version number, or the code examples in this tutorial may not work. +this version number, or the code examples in this tutorial may not work: --> Cargoがその力を発揮するのは外部クレートと連携するときです。 `rand`を使ったコードを書く前に、*Cargo.toml*ファイルを編集して`rand`クレートを依存関係に含める必要があります。 そのファイルを開いて、Cargoが作ってくれた`[dependencies]`セクションヘッダの下に次の行を追加してください。 バージョンナンバーを含め、ここに書かれている通り正確に`rand`を指定してください。 -そうしないと、このチュートリアルのコード例が動作しないかもしれません。 +そうしないと、このチュートリアルのコード例が動作しないかもしれません: + *Cargo.toml*ファイルでは、ヘッダに続くものはすべて、他のセクションが始まるまで続くセクションの一部になります。 (訳注:Cargo.tomlファイル内には複数のセクションがあり、各セクションは`[ ]`で囲まれたヘッダ行から始まります) `[dependecies]`はプロジェクトが依存する外部クレートと必要とするバージョンをCargoに伝えます。 -今回は`rand`クレートを`0.8.3`というセマンティックバージョン指定子で指定します。 +今回は`rand`クレートを`0.8.5`というセマンティックバージョン指定子で指定します。 Cargoは[セマンティックバージョニング][semver](*SemVer*と呼ばれることもあります)を理解しており、これはバージョンナンバーを記述するための標準です。 -`0.8.3`という数字は実際には`^0.8.3`の省略記法で、`0.8.3`以上`0.9.0`未満の任意のバージョンを意味します。 -Cargoはこれらのバージョンを、バージョン`0.8.3`と互換性のある公開APIを持つものとみなします。 +`0.8.5`という指定子は実際には`^0.8.5`の省略記法で、0.8.5以上0.9.0未満の任意のバージョンを意味します。 + + + +Cargoはこれらのバージョンを、バージョン0.8.5と互換性のある公開APIを持つものとみなします。 この仕様により、この章のコードが引き続きコンパイルできるようにしつつ、最新のパッチリリースを取得できるようになります。 0.9.0以降のバージョンは、以下の例で使用しているものと同じAPIを持つことを保証しません。 -[semver]: http://semver.org - + ```console $ cargo build Updating crates.io index (crates.ioインデックスを更新しています) - Downloaded rand v0.8.3 - (rand v0.8.3をダウンロードしています) - Downloaded libc v0.2.86 - Downloaded getrandom v0.2.2 + Downloaded rand v0.8.5 + (rand v0.8.5をダウンロードしています) + Downloaded libc v0.2.127 + Downloaded getrandom v0.2.7 Downloaded cfg-if v1.0.0 - Downloaded ppv-lite86 v0.2.10 - Downloaded rand_chacha v0.3.0 - Downloaded rand_core v0.6.2 - Compiling rand_core v0.6.2 - (rand_core v0.6.2をコンパイルしています) - Compiling libc v0.2.86 - Compiling getrandom v0.2.2 + Downloaded ppv-lite86 v0.2.16 + Downloaded rand_chacha v0.3.1 + Downloaded rand_core v0.6.3 + Compiling libc v0.2.127 + (libc v0.2.127をコンパイルしています) + Compiling getrandom v0.2.7 Compiling cfg-if v1.0.0 - Compiling ppv-lite86 v0.2.10 - Compiling rand_chacha v0.3.0 - Compiling rand v0.8.3 + Compiling ppv-lite86 v0.2.16 + Compiling rand_core v0.6.3 + Compiling rand_chacha v0.3.1 + Compiling rand v0.8.5 Compiling guessing_game v0.1.0 (file:///projects/guessing_game) (guessing_game v0.1.0をコンパイルしています) Finished dev [unoptimized + debuginfo] target(s) in 2.53s @@ -758,8 +770,8 @@ adding the rand crate as a dependency もしかしたら異なるバージョンナンバー(とはいえ、SemVerのおかげですべてのコードに互換性があります)や、 @@ -777,8 +789,6 @@ post their open source Rust projects for others to use. レジストリとは[Crates.io][cratesio]のデータのコピーです。 Crates.ioは、Rustのエコシステムにいる人たちがオープンソースのRustプロジェクトを投稿し、他の人が使えるようにする場所です。 -[cratesio]: https://crates.io - *src/main.rs*ファイルを開いて些細な変更を加え、それを保存して再度ビルドすると2行しか表示されません。 + + ```console $ cargo build Compiling guessing_game v0.1.0 (file:///projects/guessing_game) @@ -819,7 +834,7 @@ $ cargo build ``` @@ -837,7 +852,7 @@ reuse what it has already downloaded and compiled for those. Cargo has a mechanism that ensures you can rebuild the same artifact every time you or anyone else builds your code: Cargo will use only the versions of the dependencies you specified until you indicate otherwise. For example, say that -next week version 0.8.4 of the `rand` crate comes out, and that version +next week version 0.8.6 of the `rand` crate comes out, and that version contains an important bug fix, but it also contains a regression that will break your code. To handle this, Rust creates the *Cargo.lock* file the first time you run `cargo build`, so we now have this in the *guessing_game* @@ -846,25 +861,27 @@ directory. Cargoはあなたや他の人があなたのコードをビルドするたびに、同じ生成物をリビルドできるようにするしくみを備えています。 Cargoは何も指示されない限り、指定したバージョンの依存のみを使用します。 -たとえば来週`rand`クレートのバージョン0.8.4が出て、そのバージョンには重要なバグ修正が含まれていますが、同時にあなたのコードを破壊するリグレッションも含まれているとします。 +たとえば来週`rand`クレートのバージョン0.8.6が出て、そのバージョンには重要なバグ修正が含まれていますが、同時にあなたのコードを破壊するリグレッションも含まれているとします。 これに対応するため、Rustは`cargo build`を最初に実行したときに*Cargo.lock*ファイルを作成します。 (いまの*guessing_game*ディレクトリにもあるはずです) プロジェクトを初めてビルドするとき、Cargoは条件に合うすべての依存関係のバージョンを計算し*Cargo.lock*ファイルに書き込みます。 -次にプロジェクトをビルドすると、Cargoは*Cargo.lock*ファイルが存在することを確認し、バージョンを把握するすべての作業を再び行う代わりに、そこで指定されているバージョンを使います。 +次にプロジェクトをビルドすると、Cargoは*Cargo.lock*ファイルが存在することを確認し、バージョンを把握するすべての作業を再び行う代わりに、そこで指定されているバージョンを使うでしょう。 これにより再現性のあるビルドを自動的に行えます。 -言い換えれば、*Cargo.lock*ファイルのおかげで、あなたが明示的にアップグレードするまで、プロジェクトは`0.8.3`を使い続けます。 +言い換えれば、*Cargo.lock*ファイルのおかげで、あなたが明示的にアップグレードするまで、プロジェクトは0.8.5を使い続けます。 +*Cargo.lock*ファイルは再現性のあるビルドのために重要なので、プロジェクトの残りのコードとともにソース管理にチェックインされることが多いです。 クレートを*本当に*アップグレードしたくなったときのために、Cargoは`update`コマンドを提供します。 このコマンドは*Cargo.lock*ファイルを無視して、*Cargo.toml*ファイル内の全ての指定に適合する最新バージョンを算出します。 成功したらCargoはそれらのバージョンを*Cargo.lock*ファイルに記録します。 -ただし、デフォルトでCargoは`0.8.3`以上、`0.9.0`未満のバージョンのみを検索します。 -もし`rand`クレートの新しいバージョンとして`0.8.4`と`0.9.0`の二つがリリースされていたなら、`cargo update`を実行したときに以下のようなメッセージが表示されるでしょう。 +ただし、デフォルトでCargoは0.8.5以上、0.9.0未満のバージョンのみを検索します。 +もし`rand`クレートの新しいバージョンとして0.8.6と0.9.0の二つがリリースされていたなら、`cargo update`を実行したときに以下のようなメッセージが表示されるでしょう。 + + ```console $ cargo update Updating crates.io index (crates.ioインデックスを更新しています) - Updating rand v0.8.3 -> v0.8.4 - (randクレートをv0.8.3 -> v0.8.4に更新しています) + Updating rand v0.8.5 -> v0.8.6 + (randクレートをv0.8.5 -> v0.8.6に更新しています) ``` -Cargoは`0.9.0`リリースを無視します。 -またそのとき、*Cargo.lock*ファイルが変更され、`rand`クレートの現在使用中のバージョンが`0.8.4`になったことにも気づくでしょう。 -そうではなく、`rand`のバージョン`0.9.0`か、`0.9.x`系のどれかを使用するには、*Cargo.toml*ファイルを以下のように変更する必要があります。 +Cargoは0.9.0リリースを無視します。 +またそのとき、*Cargo.lock*ファイルが変更され、`rand`クレートの現在使用中のバージョンが0.8.6になったことにも気づくでしょう。 +そうではなく、`rand`のバージョン0.9.0か、0.9.*x*系のどれかを使用するには、*Cargo.toml*ファイルを以下のように変更する必要があります。 ```toml [dependencies] - rand = "0.9.0" ``` @@ -934,9 +955,6 @@ from a number of packages. いまのところは、これだけ知っていれば十分です。 Cargoはライブラリの再利用をとても簡単にしてくれるので、Rustaceanが数多くのパッケージから構成された小さなプロジェクトを書くことが可能になっています。 -[doccargo]: http://doc.crates.io -[doccratesio]: http://doc.crates.io/crates-io.html - @@ -969,44 +987,42 @@ number リスト2-3:乱数を生成するコードの追加 -まず`use rand::Rng`という行を追加します。 +まず`use rand::Rng;`という行を追加します。 `Rng`トレイトは乱数生成器が実装すべきメソッドを定義しており、それらのメソッドを使用するには、このトレイトがスコープ内になければなりません。 トレイトについて詳しくは第10章で解説します。 次に、途中に2行を追加しています。 最初の行では`rand::thread_rng`関数を呼び出して、これから使う、ある特定の乱数生成器を取得しています。 なお、この乱数生成器は現在のスレッドに固有で、オペレーティングシステムからシード値を得ています。 そして、この乱数生成器の`gen_range`メソッドを呼び出しています。 -このメソッドは`use rand::Rng`文でスコープに導入した`Rng`トレイトで定義されています。 +このメソッドは`use rand::Rng;`文でスコープに導入した`Rng`トレイトで定義されています。 `gen_range`メソッドは範囲式を引数にとり、その範囲内の乱数を生成してくれます。 -ここで使っている範囲式の種類は`開始..終了`という形式で、下限値は含みますが上限値は含みません。 +ここで使っている範囲式の種類は`開始..=終了`という形式で、下限値と上限値をともに含みます。 そのため、1から100までの数をリクエストするには`1..101`と指定する必要があります。 -あるいは、これと同等の`1..=100`という範囲を渡すこともできます。 + ```console $ cargo run Compiling guessing_game v0.1.0 (file:///projects/guessing_game) @@ -1070,8 +1094,8 @@ You should get different random numbers, and they should all be numbers between さて、ユーザ入力と乱数が揃ったので両者を比較してみましょう。 @@ -1106,19 +1130,11 @@ the three outcomes that are possible when you compare two values. `Ordering`もenumの一つで`Less`、`Greater`、`Equal`という列挙子を持っています。 これらは二つの値を比較したときに得られる3種類の結果です。 -```rust,ignore -match guess.cmp(&secret_number) { - Ordering::Less => println!("Too small!"), - Ordering::Greater => println!("Too big!"), - Ordering::Equal => println!("You win!"), -} -``` - `match`式は複数の*アーム*(腕)で構成されます。 各アームはマッチさせる*パターン*と、`match`に与えられた値がそのアームのパターンにマッチしたときに実行されるコードで構成されます。 Rustは`match`に与えられた値を受け取って、各アームのパターンを順に照合していきます。 -パターンと`match`式はRustの強力な機能で、コードか遭遇する可能性のあるさまざまな状況を表現し、それらすべてを確実に処理できるようにします。 +パターンと`match`式はRustの強力な機能です: コードか遭遇する可能性のあるさまざまな状況を表現し、それらすべてを確実に処理できるようにします。 これらの機能については、それぞれ第6章と第18章で詳しく説明します。 + +ここで使われている`match`式に対して、例を通して順に見ていきましょう。 +たとえばユーザが50と予想し、今回ランダムに生成された秘密の数字は38だったとしましょう。 + + -ここで使われている`match`式に対して、例を通して順に見ていきましょう。 -たとえばユーザが50と予想し、今回ランダムに生成された秘密の数字は38だったとしましょう。 コードが50と38を比較すると、50は38よりも大きいので`cmp`メソッドは`Ordering::Greater`を返します。 `match`式は`Ordering::Greater`の値を取得し、各アームのパターンを吟味し始めます。 まず最初のアームのパターンである`Ordering::Less`を見て、`Ordering::Greater`の値と`Ordering::Less`がマッチしないことがわかります。 そのため、このアームのコードは無視して、次のアームに移ります。 次のアームのパターンは`Ordering::Greater`で、これは`Ordering::Greater`と*マッチ*します!  このアームに関連するコードが実行され、画面に`Too big!`と表示されます。 -このシナリオでは最後のアームと照合する必要がないため`match`式(の評価)は終了します。 +このシナリオでは最初に成功したマッチで`match`式(の評価)は終了し、最後のアームとは照合されません。 + ```console {{#include ../listings/ch02-guessing-game-tutorial/listing-02-04/output.txt}} ``` @@ -1207,8 +1232,8 @@ Rustのデフォルトは`i32`型で、型情報をどこかに追加してRust 最終的にはプログラムが入力として読み込んだ`String`を実数型に変換し、秘密の数字と数値として比較できるようにしたいわけです。 @@ -1236,19 +1261,19 @@ let guess: u32 = guess.trim().parse().expect("Please type a number!"); `guess`という名前の変数を作成しています。 しかし待ってください、このプログラムには既に`guess`という名前の変数がありませんでしたか?  -たしかにありますが、Rustでは`guess`の前の値を新しい値で*覆い隠す*(shadowする)ことが許されているのです。 -シャドーイング(shadowing)は、`guess_str`と`guess`のような重複しない変数を二つ作る代わりに、`guess`という変数名を再利用させてくれるのです。 -これについては第3章で詳しく説明しますが、今のところ、この機能はある型から別の型に値を変換するときによく使われることを知っておいてください。 +たしかにありますが、Rustでは`guess`の前の値を新しい値で覆い隠す(shadowする)ことが許されているのです。 +*シャドーイング*(shadowing)は、`guess_str`と`guess`のような重複しない変数を二つ作る代わりに、`guess`という変数名を再利用させてくれるのです。 +これについては[第3章][shadowing]で詳しく説明しますが、今のところ、この機能はある型から別の型に値を変換するときによく使われることを知っておいてください。 この新しい変数を`guess.trim().parse()`という式に束縛しています。 @@ -1271,60 +1296,71 @@ class="keystroke">enter results in a carriage return and a newline, これは数値データのみを表現できる`u32`型とこの文字列を比較するために(準備として)行う必要があります。 ユーザは予想を入力したあと`read_line`の処理を終えるためにEnterキーを押す必要がありますが、これにより文字列に改行文字が追加されます。 たとえばユーザが5と入力してEnterキーを押すと、`guess`は`5\n`になります。 -この`\n`は「改行」を表しています。(WindowsではEnterキーを押すとキャリッジリターンと改行が入り`\r\n`となります) +この`\n`は「改行」を表しています。(WindowsではEnterキーを押すとキャリッジリターンと改行が入り`\r\n`となります。) `trim`メソッドは`\n`や`\r\n`を削除するので、その結果`5`だけになります。 -[文字列の`parse`メソッド][parse]は文字列をパース(解析)して何らかの数値にします。 -このメソッドは(文字列を)さまざまな数値型へとパースできるので、`let guess: u32`としてRustに正確な数値型を伝える必要があります。 +[文字列の`parse`メソッド][parse]は文字列を別の型に変換します。 +ここでは、私たちは文字列を数値に変換するために使います。 +`let guess: u32`として、Rustに欲しい数値の正確な型を伝える必要があります。 `guess`の後にコロン(`:`)を付けることで変数の型に注釈をつけることをRustに伝えています。 Rustには組み込みの数値型がいくつかあります。 ここにある`u32`は符号なし32ビット整数で、小さな正の数を表すデフォルトの型に適しています。 -他の数値型については第3章で学びます。 +他の数値型については[第3章][integers]で学びます。 + + + さらに、このサンプルプログラムでは、`u32`という注釈と`secret_number`変数との比較していることから、Rustは`secret_number`変数も`u32`型であるべきだと推論しています。 つまり、いまでは二つの同じ型の値を比較することになるわけです! -[parse]: https://doc.rust-lang.org/std/primitive.str.html#method.parse - `parse`メソッドは論理的に数値に変換できる文字にしか使えないので、よくエラーになります。 たとえば文字列に`A👍%`が含まれていたら数値に変換する術はありません。 解析に失敗する可能性があるため、`parse`メソッドは`read_line`メソッドと同様に`Result`型を返します -([「`Result`型で失敗の可能性を扱う」](#result型で失敗の可能性を扱う)で説明しました)  +([「`Result`で失敗の可能性を扱う」](#resultで失敗の可能性を扱う)で説明しました)  今回も`expect`メソッドを使用して`Result`型を同じように扱います。 `parse`メソッドが文字列から数値を作成できなかったために`Result`型の`Err`列挙子を返したら、`expect`の呼び出しはゲームをクラッシュさせ、私たちが与えたメッセージを表示します。 `parse`が文字列をうまく数値へ変換できたときは`Result`型の`Ok`列挙子を返し、`expect`は`Ok`値から欲しい数値を返してくれます。 -さあ、プログラムを走らせましょう! +さあ、プログラムを走らせましょう: + + ```console $ cargo run @@ -1398,7 +1434,8 @@ which actually introduces a new problem. It doesn’t seem like the user can qui The user could always interrupt the program by using the keyboard shortcut ctrl-c. But there’s another way to escape this insatiable monster, as mentioned in the `parse` discussion in [“Comparing the -Guess to the Secret Number”](#comparing-the-guess-to-the-secret-number): if the user enters a non-number answer, the program will crash. We +Guess to the Secret Number”](#comparing-the-guess-to-the-secret-number) +: if the user enters a non-number answer, the program will crash. We can take advantage of that to allow the user to quit, as shown here: --> @@ -1407,6 +1444,15 @@ can take advantage of that to allow the user to quit, as shown here: ユーザが数字以外の答えを入力すればプログラムはクラッシュします。 それを利用して以下のようにすれば終了できます。 + + ```console $ cargo run Compiling guessing_game v0.1.0 (file:///projects/guessing_game) @@ -1435,8 +1481,8 @@ note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace ``` @@ -1511,8 +1557,8 @@ another guess instead of crashing the program @@ -1522,7 +1568,7 @@ method. + ```console $ cargo run Compiling guessing_game v0.1.0 (file:///projects/guessing_game) @@ -1614,17 +1669,17 @@ secret number. Listing 2-6 shows the final code. リスト2-6:数当てゲームの完全なコード -## まとめ +数当てゲームを無事に作り上げることができました。 +おめでとうございます! -数当てゲームを無事に作り上げることができました。 -おめでとうございます! +## まとめ [prelude]: https://doc.rust-lang.org/stable/std/prelude/index.html @@ -1669,7 +1725,6 @@ discusses structs and method syntax, and Chapter 6 explains how enums work. [string]: https://doc.rust-lang.org/stable/std/string/struct.String.html [iostdin]: https://doc.rust-lang.org/stable/std/io/struct.Stdin.html [read_line]: https://doc.rust-lang.org/stable/std/io/struct.Stdin.html#method.read_line -[ioresult]: https://doc.rust-lang.org/stable/std/io/type.Result.html [result]: https://doc.rust-lang.org/stable/std/result/enum.Result.html [enums]: ch06-00-enums.html [expect]: https://doc.rust-lang.org/stable/std/result/enum.Result.html#method.expect @@ -1677,7 +1732,9 @@ discusses structs and method syntax, and Chapter 6 explains how enums work. [randcrate]: https://crates.io/crates/rand [semver]: http://semver.org [cratesio]: https://crates.io/ -[doccargo]: http://doc.crates.io -[doccratesio]: http://doc.crates.io/crates-io.html +[doccargo]: https://doc.rust-lang.org/cargo/ +[doccratesio]: https://doc.rust-lang.org/cargo/reference/publishing.html [match]: ch06-02-match.html +[shadowing]: ch03-01-variables-and-mutability.html#シャドーイング [parse]: https://doc.rust-lang.org/stable/std/primitive.str.html#method.parse +[integers]: ch03-02-data-types.html#整数型 diff --git a/src/ch09-02-recoverable-errors-with-result.md b/src/ch09-02-recoverable-errors-with-result.md index 65be5fb61..489e7aef7 100644 --- a/src/ch09-02-recoverable-errors-with-result.md +++ b/src/ch09-02-recoverable-errors-with-result.md @@ -25,7 +25,7 @@ defined as having two variants, `Ok` and `Err`, as follows: 第2章の[「`Result`型で失敗する可能性に対処する」][handle_failure]で`Result` enumが以下のように、 `Ok`と`Err`の2列挙子からなるよう定義されていることを思い出してください: -[handle_failure]: ch02-00-guessing-game-tutorial.html#result型で失敗の可能性を扱う +[handle_failure]: ch02-00-guessing-game-tutorial.html#resultで失敗の可能性を扱う ```rust enum Result { From 49f93be9e6f17dac7142d502b9f9937bb454fa88 Mon Sep 17 00:00:00 2001 From: shinmili Date: Sun, 26 May 2024 12:58:02 +0900 Subject: [PATCH 04/10] =?UTF-8?q?ch03=20=E4=B8=80=E8=88=AC=E7=9A=84?= =?UTF-8?q?=E3=81=AA=E3=83=97=E3=83=AD=E3=82=B0=E3=83=A9=E3=83=9F=E3=83=B3?= =?UTF-8?q?=E3=82=B0=E3=81=AE=E6=A6=82=E5=BF=B5=E3=81=AE=E5=92=8C=E8=A8=B3?= =?UTF-8?q?=E3=82=92=E6=9C=80=E6=96=B0=E7=89=88=E3=81=AB=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit rust-lang/book@19c40bfd2d57641d962f3119a1c343355f1b3c5e --- .../listing-03-02/src/main.rs | 4 +- .../listing-03-03/src/main.rs | 2 +- .../listing-03-05/src/main.rs | 2 +- .../output.txt | 4 +- .../src/main.rs | 4 +- .../no-listing-02-adding-mut/src/main.rs | 4 +- .../no-listing-03-shadowing/src/main.rs | 4 +- .../output.txt | 8 +- .../src/main.rs | 4 +- .../no-listing-09-char/src/main.rs | 3 +- .../src/main.rs | 2 +- .../src/main.rs | 7 +- .../src/main.rs | 2 +- .../src/main.rs | 2 +- .../output.txt | 24 +- .../src/main.rs | 2 +- .../src/main.rs | 2 +- .../src/main.rs | 2 +- .../output.txt | 4 +- .../src/main.rs | 2 +- .../output.txt | 2 +- .../output.txt | 2 +- .../src/main.rs | 2 +- .../no-listing-32-5-loop-labels/src/main.rs | 6 +- .../src/main.rs | 2 +- .../no-listing-34-for-range/src/main.rs | 2 +- .../output.txt | 18 +- src/ch03-00-common-programming-concepts.md | 14 +- src/ch03-01-variables-and-mutability.md | 280 ++++++------ src/ch03-02-data-types.md | 411 +++++++++++------- src/ch03-03-how-functions-work.md | 196 ++++----- src/ch03-04-comments.md | 33 +- src/ch03-05-control-flow.md | 320 ++++++++------ 33 files changed, 787 insertions(+), 589 deletions(-) diff --git a/listings/ch03-common-programming-concepts/listing-03-02/src/main.rs b/listings/ch03-common-programming-concepts/listing-03-02/src/main.rs index bd5b900c4..9386ad697 100644 --- a/listings/ch03-common-programming-concepts/listing-03-02/src/main.rs +++ b/listings/ch03-common-programming-concepts/listing-03-02/src/main.rs @@ -2,6 +2,6 @@ fn main() { let condition = true; let number = if condition { 5 } else { 6 }; - // numberの値は、{}です - println!("The value of number is: {}", number); + // numberの値は、{number}です + println!("The value of number is: {number}"); } diff --git a/listings/ch03-common-programming-concepts/listing-03-03/src/main.rs b/listings/ch03-common-programming-concepts/listing-03-03/src/main.rs index 568f2bc8e..64720815c 100644 --- a/listings/ch03-common-programming-concepts/listing-03-03/src/main.rs +++ b/listings/ch03-common-programming-concepts/listing-03-03/src/main.rs @@ -2,7 +2,7 @@ fn main() { let mut number = 3; while number != 0 { - println!("{}!", number); + println!("{number}!"); number -= 1; } diff --git a/listings/ch03-common-programming-concepts/listing-03-05/src/main.rs b/listings/ch03-common-programming-concepts/listing-03-05/src/main.rs index 5eaa7a09e..b44e6b7aa 100644 --- a/listings/ch03-common-programming-concepts/listing-03-05/src/main.rs +++ b/listings/ch03-common-programming-concepts/listing-03-05/src/main.rs @@ -2,6 +2,6 @@ fn main() { let a = [10, 20, 30, 40, 50]; for element in a { - println!("the value is: {}", element); + println!("the value is: {element}"); } } diff --git a/listings/ch03-common-programming-concepts/no-listing-01-variables-are-immutable/output.txt b/listings/ch03-common-programming-concepts/no-listing-01-variables-are-immutable/output.txt index 127a0b902..4e76fa360 100644 --- a/listings/ch03-common-programming-concepts/no-listing-01-variables-are-immutable/output.txt +++ b/listings/ch03-common-programming-concepts/no-listing-01-variables-are-immutable/output.txt @@ -10,9 +10,9 @@ error[E0384]: cannot assign twice to immutable variable `x` | first assignment to `x` | (`x`への最初の代入) | help: consider making this binding mutable: `mut x` -3 | println!("The value of x is: {}", x); +3 | println!("The value of x is: {x}"); 4 | x = 6; | ^^^^^ cannot assign twice to immutable variable For more information about this error, try `rustc --explain E0384`. -error: could not compile `variables` due to previous error +error: could not compile `variables` (bin "variables") due to 1 previous error diff --git a/listings/ch03-common-programming-concepts/no-listing-01-variables-are-immutable/src/main.rs b/listings/ch03-common-programming-concepts/no-listing-01-variables-are-immutable/src/main.rs index 84d0ad8d9..046fbb406 100644 --- a/listings/ch03-common-programming-concepts/no-listing-01-variables-are-immutable/src/main.rs +++ b/listings/ch03-common-programming-concepts/no-listing-01-variables-are-immutable/src/main.rs @@ -1,6 +1,6 @@ fn main() { let x = 5; - println!("The value of x is: {}", x); // xの値は{}です + println!("The value of x is: {x}"); // xの値は{x}です x = 6; - println!("The value of x is: {}", x); + println!("The value of x is: {x}"); } diff --git a/listings/ch03-common-programming-concepts/no-listing-02-adding-mut/src/main.rs b/listings/ch03-common-programming-concepts/no-listing-02-adding-mut/src/main.rs index c4e4a1953..a57709ccf 100644 --- a/listings/ch03-common-programming-concepts/no-listing-02-adding-mut/src/main.rs +++ b/listings/ch03-common-programming-concepts/no-listing-02-adding-mut/src/main.rs @@ -1,6 +1,6 @@ fn main() { let mut x = 5; - println!("The value of x is: {}", x); + println!("The value of x is: {x}"); x = 6; - println!("The value of x is: {}", x); + println!("The value of x is: {x}"); } diff --git a/listings/ch03-common-programming-concepts/no-listing-03-shadowing/src/main.rs b/listings/ch03-common-programming-concepts/no-listing-03-shadowing/src/main.rs index 606ee68a0..03924fe1c 100644 --- a/listings/ch03-common-programming-concepts/no-listing-03-shadowing/src/main.rs +++ b/listings/ch03-common-programming-concepts/no-listing-03-shadowing/src/main.rs @@ -5,8 +5,8 @@ fn main() { { let x = x * 2; - println!("The value of x in the inner scope is: {}", x); + println!("The value of x in the inner scope is: {x}"); } - println!("The value of x is: {}", x); + println!("The value of x is: {x}"); } diff --git a/listings/ch03-common-programming-concepts/no-listing-05-mut-cant-change-types/output.txt b/listings/ch03-common-programming-concepts/no-listing-05-mut-cant-change-types/output.txt index 0bf395c6e..271ed387c 100644 --- a/listings/ch03-common-programming-concepts/no-listing-05-mut-cant-change-types/output.txt +++ b/listings/ch03-common-programming-concepts/no-listing-05-mut-cant-change-types/output.txt @@ -8,6 +8,12 @@ error[E0308]: mismatched types (型が合いません) 3 | spaces = spaces.len(); | ^^^^^^^^^^^^ expected `&str`, found `usize` | (&str型を予期しましたが、usizeが見つかりました) + | +help: try removing the method call + | +3 - spaces = spaces.len(); +3 + spaces = spaces; + | For more information about this error, try `rustc --explain E0308`. -error: could not compile `variables` due to previous error +error: could not compile `variables` (bin "variables") due to 1 previous error diff --git a/listings/ch03-common-programming-concepts/no-listing-07-numeric-operations/src/main.rs b/listings/ch03-common-programming-concepts/no-listing-07-numeric-operations/src/main.rs index 2bd8f9204..df79eb4f1 100644 --- a/listings/ch03-common-programming-concepts/no-listing-07-numeric-operations/src/main.rs +++ b/listings/ch03-common-programming-concepts/no-listing-07-numeric-operations/src/main.rs @@ -14,8 +14,8 @@ fn main() { // division // 割り算 let quotient = 56.7 / 32.2; - let floored = 2 / 3; // Results in 0 - // 結果は0 + let truncated = -5 / 3; // Results in -1 + // 結果は-1 // remainder // 余り diff --git a/listings/ch03-common-programming-concepts/no-listing-09-char/src/main.rs b/listings/ch03-common-programming-concepts/no-listing-09-char/src/main.rs index b52bd7f5c..1043f3990 100644 --- a/listings/ch03-common-programming-concepts/no-listing-09-char/src/main.rs +++ b/listings/ch03-common-programming-concepts/no-listing-09-char/src/main.rs @@ -1,5 +1,6 @@ fn main() { let c = 'z'; - let z = 'ℤ'; + let z: char = 'ℤ'; // with explicit type annotation + // 明示的型注釈付きで let heart_eyed_cat = '😻'; //ハート目の猫 } diff --git a/listings/ch03-common-programming-concepts/no-listing-11-destructuring-tuples/src/main.rs b/listings/ch03-common-programming-concepts/no-listing-11-destructuring-tuples/src/main.rs index 35dcb442e..3002bdde4 100644 --- a/listings/ch03-common-programming-concepts/no-listing-11-destructuring-tuples/src/main.rs +++ b/listings/ch03-common-programming-concepts/no-listing-11-destructuring-tuples/src/main.rs @@ -3,5 +3,5 @@ fn main() { let (x, y, z) = tup; - println!("The value of y is: {}", y); + println!("The value of y is: {y}"); } diff --git a/listings/ch03-common-programming-concepts/no-listing-15-invalid-array-access/src/main.rs b/listings/ch03-common-programming-concepts/no-listing-15-invalid-array-access/src/main.rs index a7b70697b..9d1cfcd55 100644 --- a/listings/ch03-common-programming-concepts/no-listing-15-invalid-array-access/src/main.rs +++ b/listings/ch03-common-programming-concepts/no-listing-15-invalid-array-access/src/main.rs @@ -21,9 +21,6 @@ fn main() { let element = a[index]; - println!( - "The value of the element at index {} is: {}", - // {}番目の要素の値は{}です - index, element - ); + println!("The value of the element at index {index} is: {element}"); + // {index}番目の要素の値は{element}です } diff --git a/listings/ch03-common-programming-concepts/no-listing-17-functions-with-parameters/src/main.rs b/listings/ch03-common-programming-concepts/no-listing-17-functions-with-parameters/src/main.rs index 47655ec8b..e13d54d2e 100644 --- a/listings/ch03-common-programming-concepts/no-listing-17-functions-with-parameters/src/main.rs +++ b/listings/ch03-common-programming-concepts/no-listing-17-functions-with-parameters/src/main.rs @@ -3,5 +3,5 @@ fn main() { } fn another_function(x: i32) { - println!("The value of x is: {}", x); // xの値は{}です + println!("The value of x is: {x}"); // xの値は{x}です } diff --git a/listings/ch03-common-programming-concepts/no-listing-18-functions-with-multiple-parameters/src/main.rs b/listings/ch03-common-programming-concepts/no-listing-18-functions-with-multiple-parameters/src/main.rs index 543c2ea45..b070ccb23 100644 --- a/listings/ch03-common-programming-concepts/no-listing-18-functions-with-multiple-parameters/src/main.rs +++ b/listings/ch03-common-programming-concepts/no-listing-18-functions-with-multiple-parameters/src/main.rs @@ -3,5 +3,5 @@ fn main() { } fn print_labeled_measurement(value: i32, unit_label: char) { - println!("The measurement is: {}{}", value, unit_label); + println!("The measurement is: {value}{unit_label}"); } diff --git a/listings/ch03-common-programming-concepts/no-listing-19-statements-vs-expressions/output.txt b/listings/ch03-common-programming-concepts/no-listing-19-statements-vs-expressions/output.txt index 4cf947530..2f99beed6 100644 --- a/listings/ch03-common-programming-concepts/no-listing-19-statements-vs-expressions/output.txt +++ b/listings/ch03-common-programming-concepts/no-listing-19-statements-vs-expressions/output.txt @@ -1,23 +1,14 @@ $ cargo run Compiling functions v0.1.0 (file:///projects/functions) -error: expected expression, found statement (`let`) -(エラー: 式を予期しましたが、文が見つかりました (`let`)) +error: expected expression, found `let` statement +(エラー: 式を予期しましたが、`let`文が見つかりました) --> src/main.rs:2:14 | 2 | let x = (let y = 6); - | ^^^^^^^^^ + | ^^^ | - = note: variable declaration using `let` is a statement - (注釈: `let`を使う変数宣言は、文です) - -error[E0658]: `let` expressions in this position are experimental - --> src/main.rs:2:14 - | -2 | let x = (let y = 6); - | ^^^^^^^^^ - | - = note: see issue #53667 for more information - = help: you can write `matches!(, )` instead of `let = ` + = note: only supported directly in conditions of `if` and `while` expressions + (注釈: `if` および `while` 式の条件部直下でのみ対応しています warning: unnecessary parentheses around assigned value --> src/main.rs:2:13 @@ -30,8 +21,7 @@ help: remove these parentheses | 2 - let x = (let y = 6); 2 + let x = let y = 6; - | + | -For more information about this error, try `rustc --explain E0658`. warning: `functions` (bin "functions") generated 1 warning -error: could not compile `functions` due to 2 previous errors; 1 warning emitted +error: could not compile `functions` (bin "functions") due to 1 previous error; 1 warning emitted diff --git a/listings/ch03-common-programming-concepts/no-listing-20-blocks-are-expressions/src/main.rs b/listings/ch03-common-programming-concepts/no-listing-20-blocks-are-expressions/src/main.rs index 0be7fcbf3..64b873297 100644 --- a/listings/ch03-common-programming-concepts/no-listing-20-blocks-are-expressions/src/main.rs +++ b/listings/ch03-common-programming-concepts/no-listing-20-blocks-are-expressions/src/main.rs @@ -4,5 +4,5 @@ fn main() { x + 1 }; - println!("The value of y is: {}", y); + println!("The value of y is: {y}"); } diff --git a/listings/ch03-common-programming-concepts/no-listing-21-function-return-values/src/main.rs b/listings/ch03-common-programming-concepts/no-listing-21-function-return-values/src/main.rs index 5303b1082..a11af7ec7 100644 --- a/listings/ch03-common-programming-concepts/no-listing-21-function-return-values/src/main.rs +++ b/listings/ch03-common-programming-concepts/no-listing-21-function-return-values/src/main.rs @@ -5,5 +5,5 @@ fn five() -> i32 { fn main() { let x = five(); - println!("The value of x is: {}", x); + println!("The value of x is: {x}"); } diff --git a/listings/ch03-common-programming-concepts/no-listing-22-function-parameter-and-return/src/main.rs b/listings/ch03-common-programming-concepts/no-listing-22-function-parameter-and-return/src/main.rs index b4c84437a..da9d0ddb3 100644 --- a/listings/ch03-common-programming-concepts/no-listing-22-function-parameter-and-return/src/main.rs +++ b/listings/ch03-common-programming-concepts/no-listing-22-function-parameter-and-return/src/main.rs @@ -1,7 +1,7 @@ fn main() { let x = plus_one(5); - println!("The value of x is: {}", x); + println!("The value of x is: {x}"); } fn plus_one(x: i32) -> i32 { diff --git a/listings/ch03-common-programming-concepts/no-listing-23-statements-dont-return-values/output.txt b/listings/ch03-common-programming-concepts/no-listing-23-statements-dont-return-values/output.txt index 7a684650a..d13b1c891 100644 --- a/listings/ch03-common-programming-concepts/no-listing-23-statements-dont-return-values/output.txt +++ b/listings/ch03-common-programming-concepts/no-listing-23-statements-dont-return-values/output.txt @@ -9,7 +9,7 @@ error[E0308]: mismatched types | | | implicitly returns `()` as its body has no tail or `return` expression 8 | x + 1; - | - help: consider removing this semicolon + | - help: remove this semicolon to return this value For more information about this error, try `rustc --explain E0308`. -error: could not compile `functions` due to previous error +error: could not compile `functions` (bin "functions") due to 1 previous error diff --git a/listings/ch03-common-programming-concepts/no-listing-23-statements-dont-return-values/src/main.rs b/listings/ch03-common-programming-concepts/no-listing-23-statements-dont-return-values/src/main.rs index c9c4edc19..1cec800b6 100644 --- a/listings/ch03-common-programming-concepts/no-listing-23-statements-dont-return-values/src/main.rs +++ b/listings/ch03-common-programming-concepts/no-listing-23-statements-dont-return-values/src/main.rs @@ -1,7 +1,7 @@ fn main() { let x = plus_one(5); - println!("The value of x is: {}", x); + println!("The value of x is: {x}"); } fn plus_one(x: i32) -> i32 { diff --git a/listings/ch03-common-programming-concepts/no-listing-28-if-condition-must-be-bool/output.txt b/listings/ch03-common-programming-concepts/no-listing-28-if-condition-must-be-bool/output.txt index 3a43db713..e8f033d36 100644 --- a/listings/ch03-common-programming-concepts/no-listing-28-if-condition-must-be-bool/output.txt +++ b/listings/ch03-common-programming-concepts/no-listing-28-if-condition-must-be-bool/output.txt @@ -9,4 +9,4 @@ error[E0308]: mismatched types | (bool型を予期したのに、整数変数が見つかりました) For more information about this error, try `rustc --explain E0308`. -error: could not compile `branches` due to previous error +error: could not compile `branches` (bin "branches") due to 1 previous error diff --git a/listings/ch03-common-programming-concepts/no-listing-31-arms-must-return-same-type/output.txt b/listings/ch03-common-programming-concepts/no-listing-31-arms-must-return-same-type/output.txt index a236054af..7e11035d3 100644 --- a/listings/ch03-common-programming-concepts/no-listing-31-arms-must-return-same-type/output.txt +++ b/listings/ch03-common-programming-concepts/no-listing-31-arms-must-return-same-type/output.txt @@ -11,4 +11,4 @@ error[E0308]: `if` and `else` have incompatible types | expected because of this For more information about this error, try `rustc --explain E0308`. -error: could not compile `branches` due to previous error +error: could not compile `branches` (bin "branches") due to 1 previous error diff --git a/listings/ch03-common-programming-concepts/no-listing-31-arms-must-return-same-type/src/main.rs b/listings/ch03-common-programming-concepts/no-listing-31-arms-must-return-same-type/src/main.rs index 440b286f5..df7068bcf 100644 --- a/listings/ch03-common-programming-concepts/no-listing-31-arms-must-return-same-type/src/main.rs +++ b/listings/ch03-common-programming-concepts/no-listing-31-arms-must-return-same-type/src/main.rs @@ -3,5 +3,5 @@ fn main() { let number = if condition { 5 } else { "six" }; - println!("The value of number is: {}", number); + println!("The value of number is: {number}"); } diff --git a/listings/ch03-common-programming-concepts/no-listing-32-5-loop-labels/src/main.rs b/listings/ch03-common-programming-concepts/no-listing-32-5-loop-labels/src/main.rs index b855d7576..dd8856403 100644 --- a/listings/ch03-common-programming-concepts/no-listing-32-5-loop-labels/src/main.rs +++ b/listings/ch03-common-programming-concepts/no-listing-32-5-loop-labels/src/main.rs @@ -1,11 +1,11 @@ fn main() { let mut count = 0; 'counting_up: loop { - println!("count = {}", count); + println!("count = {count}"); let mut remaining = 10; loop { - println!("remaining = {}", remaining); + println!("remaining = {remaining}"); if remaining == 9 { break; } @@ -17,5 +17,5 @@ fn main() { count += 1; } - println!("End count = {}", count); + println!("End count = {count}"); } diff --git a/listings/ch03-common-programming-concepts/no-listing-33-return-value-from-loop/src/main.rs b/listings/ch03-common-programming-concepts/no-listing-33-return-value-from-loop/src/main.rs index 6ffdab5a4..683d18bc1 100644 --- a/listings/ch03-common-programming-concepts/no-listing-33-return-value-from-loop/src/main.rs +++ b/listings/ch03-common-programming-concepts/no-listing-33-return-value-from-loop/src/main.rs @@ -9,5 +9,5 @@ fn main() { } }; - println!("The result is {}", result); + println!("The result is {result}"); } diff --git a/listings/ch03-common-programming-concepts/no-listing-34-for-range/src/main.rs b/listings/ch03-common-programming-concepts/no-listing-34-for-range/src/main.rs index e7286a84e..df5b305bc 100644 --- a/listings/ch03-common-programming-concepts/no-listing-34-for-range/src/main.rs +++ b/listings/ch03-common-programming-concepts/no-listing-34-for-range/src/main.rs @@ -1,6 +1,6 @@ fn main() { for number in (1..4).rev() { - println!("{}!", number); + println!("{number}!"); } println!("LIFTOFF!!!"); } diff --git a/listings/ch03-common-programming-concepts/output-only-01-no-type-annotations/output.txt b/listings/ch03-common-programming-concepts/output-only-01-no-type-annotations/output.txt index 8072cd10f..ded0312d5 100644 --- a/listings/ch03-common-programming-concepts/output-only-01-no-type-annotations/output.txt +++ b/listings/ch03-common-programming-concepts/output-only-01-no-type-annotations/output.txt @@ -1,12 +1,20 @@ $ cargo build Compiling no_type_annotations v0.1.0 (file:///projects/no_type_annotations) -error[E0282]: type annotations needed +error[E0284]: type annotations needed (型注釈が必要です) --> src/main.rs:2:9 | 2 | let guess = "42".parse().expect("Not a number!"); - | ^^^^^ consider giving `guess` a type - | (`guess`に型を与えることを検討してください) + | ^^^^^ ----- type must be known at this point + | (型はこの時点で既知でなくてはなりません) + | + = note: cannot satisfy `<_ as FromStr>::Err == _` + (`<_ as FromStr>::Err == _`を満たすことができません) +help: consider giving `guess` an explicit type + | (`guess`に型を与えることを検討してください) + | +2 | let guess: /* Type */ = "42".parse().expect("Not a number!"); + | ++++++++++++ -For more information about this error, try `rustc --explain E0282`. -error: could not compile `no_type_annotations` due to previous error +For more information about this error, try `rustc --explain E0284`. +error: could not compile `no_type_annotations` (bin "no_type_annotations") due to 1 previous error diff --git a/src/ch03-00-common-programming-concepts.md b/src/ch03-00-common-programming-concepts.md index 6b9f54805..9477e66ed 100644 --- a/src/ch03-00-common-programming-concepts.md +++ b/src/ch03-00-common-programming-concepts.md @@ -27,21 +27,23 @@ them early will give you a strong core to start from. これらの基礎は全てのRustプログラムに存在するものであり、それらを早期に学ぶことにより、強力な基礎を築くことになるでしょう。 -> ### キーワード +> #### キーワード > > Rust言語にも他の言語同様、キーワードが存在し、これらは言語だけが使用できるようになっています。 > これらの単語は、変数や関数名には使えないことを弁えておいてください。ほとんどのキーワードは、特別な意味を持っており、 > 自らのRustプログラムにおいて、様々な作業をこなすために使用することができます; > いくつかは、紐付けられた機能がないものの、将来Rustに追加されるかもしれない機能用に予約されています。 > キーワードの一覧は、付録Aで確認できます。 + +[appendix_a]: appendix-01-keywords.md diff --git a/src/ch03-01-variables-and-mutability.md b/src/ch03-01-variables-and-mutability.md index 77fd81a7d..0172e9a56 100644 --- a/src/ch03-01-variables-and-mutability.md +++ b/src/ch03-01-variables-and-mutability.md @@ -5,32 +5,33 @@ ## 変数と可変性 -第2章で触れた通り、変数は標準で不変になります。これは、 +[「値を変数に保持する」][storing-values-with-variables]の節で触れた通り、変数は標準で不変になります。これは、 Rustが提供する安全性や簡便な並行性の利点を享受する形でコードを書くための選択の1つです。 ところが、まだ変数を可変にするという選択肢も残されています。 どのように、そしてなぜRustは不変性を推奨するのか、さらには、なぜそれとは違う道を選びたくなることがあるのか見ていきましょう。 変数が不変であると、値が一旦名前に束縛されたら、その値を変えることができません。 -これを具体的に説明するために、*projects*ディレクトリに`cargo new --bin variables`コマンドを使って、 -*variables*という名前のプロジェクトを生成しましょう。 +これを具体的に説明するために、*projects*ディレクトリに`cargo new variables`コマンドを使って、 +*variables*という名前のプロジェクトを生成してください。 それから、新規作成した*variables*ディレクトリで、*src/main.rs*ファイルを開き、 @@ -47,11 +48,12 @@ code with the following code that won't compile just yet: ``` -これを保存し、`cargo run`コマンドでプログラムを走らせてください。次の出力に示されているようなエラーメッセージを受け取るはずです: +これを保存し、`cargo run`コマンドでプログラムを走らせてください。 +次の出力に示されているような、不変性に関するエラーメッセージを受け取るはずです: ```console {{#include ../listings/ch03-common-programming-concepts/no-listing-01-variables-are-immutable/output.txt}} @@ -59,68 +61,66 @@ message, as shown in this output: この例では、コンパイラがプログラムに潜むエラーを見つけ出す手助けをしてくれることが示されています。 -コンパイルエラーは、イライラすることもあるものですが、まだプログラムにしてほしいことを安全に行えていないだけということなのです。 +コンパイルエラーは、イライラすることもあるものですが、本当はまだプログラムにしてほしいことを安全に行えていないだけということなのです。 エラーが出るからといって、あなたがいいプログラマではないという意味ではあり*ません*! 経験豊富なRustaceanでも、コンパイルエラーを出すことはあります。 -このエラーは、エラーの原因が`不変変数xに2回代入できない`であると示しています。不変な`x`という変数に別の値を代入しようとしたからです。 +``不変変数`x`に2回代入できません``というエラーメッセージを受け取りました。 +不変な`x`という変数に別の値を代入しようとしたからです。 -以前に不変と指定された値を変えようとした時に、コンパイルエラーが出るのは重要なことです。 +不変と指定された値を変えようとした時に、コンパイルエラーが出るのは重要なことです。 なぜなら、この状況はまさしく、バグに繋がるからです。コードのある部分は、 値が変わることはないという前提のもとに処理を行い、別の部分がその値を変更していたら、 最初の部分が目論見通りに動いていない可能性があるのです。このようなバグは、発生してしまってからでは原因が追いかけづらいものです。 特に第2のコード片が、値を*時々*しか変えない場合、尚更です。 - - - -Rustでは、値が不変であると宣言したら、本当に変わらないことをコンパイラが担保してくれます。 -つまり、コードを読み書きする際に、どこでどうやって値が変化しているかを追いかける必要がなくなります。 +Rustコンパイラは、値が不変であると宣言したら、本当に変わらないことを担保してくれるので、変更を自分で追いかける必要がなくなります。 故にコードを通して正しいことを確認するのが簡単になるのです。 -しかし、可変性は時として非常に有益なこともあります。変数は、標準でのみ、不変です。つまり、 -第2章のように変数名の前に`mut`キーワードを付けることで、可変にできるわけです。この値が変化できるようにするとともに、 -`mut`により、未来の読者に対してコードの別の部分がこの変数の値を変える可能性を示すことで、その意図を汲ませることができるのです。 +しかし可変性は非常に有用で、よりコードを書きやすくしてくれることもあります。 +変数は標準では不変ですが、[第2章][storing-values-with-variables]でやったように、 +変数名の前に`mut`キーワードを付けることで、可変にできるわけです。 +また`mut`を付けることで、コードの別の部分がこの変数の値を変えるだろうと示すことによって、 +未来の読者に対してその意図を汲ませることができるのです。 -例として、*src/main.rs*ファイルを以下のように書き換えてください: +例として、*src/main.rs*ファイルを以下のように書き換えましょう: -`mut`キーワードが使われると、`x`が束縛している値を`5`から`6`に変更できます。 -変数を可変にする方が、不変変数だけがあるよりも書きやすくなるので、変数を可変にしたくなることもあるでしょう。 +`mut`キーワードが使われると、`x`に束縛されている値を`5`から`6`に変更できます。 +可変性を使うかどうかは最終的にはプログラマに任せられており、どちらがより明白と思えるかは個別の状況によるでしょう。 -考えるべきトレードオフはバグの予防以外にも、いくつかあります。例えば、大きなデータ構造を使う場合などです。 -インスタンスを可変にして変更できるようにする方が、いちいちインスタンスをコピーして新しくメモリ割り当てされたインスタンスを返すよりも速くなります。 -小規模なデータ構造なら、新規インスタンスを生成して、もっと関数型っぽいコードを書く方が通して考えやすくなるため、 -低パフォーマンスは、その簡潔性を得るのに足りうるペナルティになるかもしれません。 +### 定数 -### 変数と定数(constants)の違い - - - -変数の値を変更できないようにするといえば、他の多くの言語も持っている別のプログラミング概念を思い浮かべるかもしれません: -*定数*です。不変変数のように、定数は名前に束縛され、変更することが叶わない値のことですが、 +不変変数のように、*定数*(constants)は名前に束縛され、変更することが叶わない値のことですが、 定数と変数の間にはいくつかの違いがあります。 まず、定数には`mut`キーワードは使えません: 定数は標準で不変であるだけでなく、常に不変なのです。 - - - 定数は`let`キーワードの代わりに、`const`キーワードで宣言し、値の型は*必ず*注釈しなければなりません。 -型と型注釈については次のセクション、「データ型」で講義しますので、その詳細について気にする必要はありません。 +型と型注釈については次のセクション、[「データ型」][data-types]で講義しますので、その詳細について気にする必要はありません。 ただ単に型は常に注釈しなければならないのだと思っていてください。 -最後の違いは、定数は定数式にしかセットできないことです。関数呼び出し結果や、実行時に評価される値にはセットできません。 +最後の違いは、定数は定数式にしかセットできないことです。実行時に評価される値にはセットできません。 -定数の名前が`MAX_POINTS`で、値が100,000にセットされた定数定義の例をご覧ください。(Rustの定数の命名規則は、 -全て大文字でアンダースコアで単語区切りすることです): +これが定数定義の例です: ```rust -const MAX_POINTS: u32 = 100_000; +const THREE_HOURS_IN_SECONDS: u32 = 60 * 60 * 3; ``` -定数は、プログラムが走る期間、定義されたスコープ内でずっと有効です。従って、 -プログラムのいろんなところで使用される可能性のあるアプリケーション空間の値を定義するのに有益な選択肢になります。 +定数の名前は`THREE_HOURS_IN_SECONDS`で、その値は60(1分あたりの秒数)×60(1時間あたりの分数)×3(このプログラムで数えたい時間数)の結果にセットされています。 +Rustの定数の命名規則は、全て大文字でアンダースコアで単語区切りすることです。 +コンパイラはコンパイル時に一部の演算を評価することができるので、この定数に10,800という値を設定する代わりに、理解し検証しやすい方法でこの値を書き出すことを選択できます。 +定数宣言内でどの演算が使用できるかについてのさらなる情報は、[Rust Referenceのconstant evaluationの節][const-eval]をお読みください。 + + + +定数は、プログラムが走る期間、定義されたスコープ内でずっと有効です。 +この性質のおかげで、定数はプログラムのいろんなところで使用される可能性のあるアプリケーション空間の値を定義するのに有用です。 例えば、ゲームでプレイヤーが取得可能なポイントの最高値や、光速度などですね。 -第2章の数当てゲームのチュートリアル、「予想と秘密の数字を比較する」節で見たように、前に定義した変数と同じ名前の変数を新しく宣言でき、 -新しい変数は、前の変数を覆い隠します。Rustaceanはこれを最初の変数は、 -2番目の変数に*覆い隠さ*れたと言い、この変数を使用した際に、2番目の変数の値が現れるということです。 +[第2章][comparing-the-guess-to-the-secret-number]の数当てゲームのチュートリアルで見たように、 +前に定義した変数と同じ名前の変数を新しく宣言できます。 +Rustaceanはこれを、最初の変数は2番目の変数に*覆い隠さ*れたと言います。 +これはその変数名を使用した際に、コンパイラは2番目の変数を見るという意味です。 +2番目の変数は実質的に、最初の変数にその影を投げかけ、自身が覆い隠されるかスコープが終了するまで、 +変数名の使用を自身へのものとして扱います。 以下のようにして、同じ変数名を用いて変数を覆い隠し、`let`キーワードの使用を繰り返します: -このプログラムはまず、`x`を`5`という値に束縛します。それから`let x =`を繰り返すことで`x`を覆い隠し、 +このプログラムはまず、`x`を`5`という値に束縛します。それから`let x =`を繰り返すことで新しい変数`x`を作り、 元の値に`1`を加えることになるので、`x`の値は`6`になります。 -3番目の`let`文も`x`を覆い隠し、以前の値に`2`をかけることになるので、`x`の最終的な値は`12`になります。 -括弧を抜けるとシャドーイングは終了し、`x`の値は元の`6`に戻ります。 +次に波括弧によって作られた内側のスコープの中で、3番目の`let`文も`x`を覆い隠して新しい変数を作り、 +以前の値に`2`をかけることになるので、`x`の最終的な値は`12`になります。 +スコープが終わるとシャドーイングは終了し、`x`の値は元の`6`に戻ります。 このプログラムを走らせたら、以下のように出力するでしょう: ```console @@ -304,7 +305,7 @@ When we run this program, it will output the following: ``` `mut`と上書きのもう一つの違いは、再度`let`キーワードを使用したら、実効的には新しい変数を生成していることになるので、 値の型を変えつつ、同じ変数名を使いまわせることです。例えば、 -プログラムがユーザに何らかのテキストに対して空白文字を入力することで何個分のスペースを表示したいかを尋ねますが、 -ただ、実際にはこの入力を数値として保持したいとしましょう: +プログラムがユーザに何らかのテキストに対して空白文字を入力することで何個分のスペースを表示したいかを尋ねて、 +そうしたらこの入力を数値として保持したいとしましょう: ```rust {{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-04-shadowing-can-change-types/src/main.rs:here}} ``` -この文法要素は、容認されます。というのも、最初の`spaces`変数は文字列型であり、2番目の`spaces`変数は、 -たまたま最初の変数と同じ名前になったまっさらな変数のわけですが、数値型になるからです。故に、シャドーイングのおかげで、 +最初の`spaces`変数は文字列型であり、2番目の`spaces`変数は数値型です。故に、シャドーイングのおかげで、 異なる名前を思いつく必要がなくなるわけです。`spaces_str`と`spaces_num`などですね; 代わりに、 よりシンプルな`spaces`という名前を再利用できるわけです。一方で、この場合に`mut`を使おうとすると、 以下に示した通りですが、コンパイルエラーになるわけです: @@ -352,8 +351,7 @@ try to use `mut` for this, as shown here, we'll get a compile-time error: ``` 変数の型を可変にすることは許されていないと言われているわけです: @@ -368,3 +366,17 @@ can have. --> さあ、変数が動作する方法を見てきたので、今度は変数が取りうるデータ型について見ていきましょう。 + + + +[comparing-the-guess-to-the-secret-number]: +ch02-00-guessing-game-tutorial.html#予想と秘密の数字を比較する +[data-types]: ch03-02-data-types.html#データ型 +[storing-values-with-variables]: ch02-00-guessing-game-tutorial.html#値を変数に保持する +[const-eval]: https://doc.rust-lang.org/reference/const_eval.html diff --git a/src/ch03-02-data-types.md b/src/ch03-02-data-types.md index eb7486ce5..7d8f93849 100644 --- a/src/ch03-02-data-types.md +++ b/src/ch03-02-data-types.md @@ -6,7 +6,7 @@ @@ -18,14 +18,15 @@ Keep in mind that Rust is a *statically typed* language, which means that it must know the types of all variables at compile time. The compiler can usually infer what type we want to use based on the value and how we use it. In cases when many types are possible, such as when we converted a `String` to a numeric -type using `parse` in the “Comparing the Guess to the Secret Number” section in +type using `parse` in the [“Comparing the Guess to the Secret +Number”][comparing-the-guess-to-the-secret-number] section in Chapter 2, we must add a type annotation, like this: --> Rustは*静的型付き*言語であることを弁えておいてください。つまり、 コンパイル時に全ての変数の型が判明している必要があるということです。コンパイラは通常、値と使用方法に基づいて、 使用したい型を推論してくれます。複数の型が推論される可能性がある場合、例えば、 -第2章の「予想と秘密の数字を比較する」節で`parse`メソッドを使って`String`型を数値型に変換した時のように、 +第2章の[「予想と秘密の数字を比較する」][comparing-the-guess-to-the-secret-number]節で`parse`メソッドを使って`String`型を数値型に変換した時のように、 複数の型が可能な場合には、型注釈をつけなければいけません。以下のようにですね: ```rust @@ -33,12 +34,12 @@ let guess: u32 = "42".parse().expect("Not a number!"); // 数字ではあり ``` -ここで型注釈を付けなければ、コンパイラは以下のエラーを表示し、これは可能性のある型のうち、 +上のコード中に示す`: u32`型注釈を付けなければ、コンパイラは以下のエラーを表示し、これは可能性のある型のうち、 どの型を使用したいのかを知るのに、コンパイラがプログラマからもっと情報を得る必要があることを意味します: ```console @@ -63,7 +64,7 @@ integers, floating-point numbers, Booleans, and characters. You may recognize these from other programming languages. Let’s jump into how they work in Rust. --> -スカラー型は、単独の値を表します。Rustには主に4つのスカラー型があります: +*スカラー*型は、単独の値を表します。Rustには主に4つのスカラー型があります: 整数、浮動小数点数、論理値、最後に文字です。他のプログラミング言語でも、これらの型を見かけたことはあるでしょう。 Rustでの動作方法に飛び込みましょう。 @@ -78,15 +79,14 @@ An *integer* is a number without a fractional component. We used one integer type in Chapter 2, the `u32` type. This type declaration indicates that the value it’s associated with should be an unsigned integer (signed integer types start with `i` instead of `u`) that takes up 32 bits of space. Table 3-1 shows -the built-in integer types in Rust. Each variant in the Signed and Unsigned -columns (for example, `i16`) can be used to declare the type of an integer -value. +the built-in integer types in Rust. We can use any of these variants to declare +the type of an integer value. --> -整数とは、小数部分のない数値のことです。第2章で一つの整数型を使用しましたね。`u32`型です。 +*整数*とは、小数部分のない数値のことです。第2章で一つの整数型を使用しましたね。`u32`型です。 この型定義は、紐付けられる値が、符号なし整数(符号付き整数は`u`ではなく、`i`で始まります)になり、 これは、32ビット分のサイズを取ります。表3-1は、Rustの組み込み整数型を表示しています。 -符号付きと符号なし欄の各バリアント(例: `i16`)を使用して、整数値の型を宣言することができます。 +これらのバリアントを使用して、整数値の型を宣言することができます。 | 大きさ | 符号付き | 符号なし | -|--------|---------|---------| -| 8-bit | `i8` | `u8` | -| 16-bit | `i16` | `u16` | -| 32-bit | `i32` | `u32` | -| 64-bit | `i64` | `u64` | -| arch | `isize` | `usize` | +|---------|----------|----------| +| 8-bit | `i8` | `u8` | +| 16-bit | `i16` | `u16` | +| 32-bit | `i32` | `u32` | +| 64-bit | `i64` | `u64` | +| 128-bit | `i128` | `u128` | +| arch | `isize` | `usize` | 各バリアントは、符号付きか符号なしかを選べ、明示的なサイズを持ちます。*符号付き*と*符号なし*は、 -数値が正負を持つかどうかを示します。つまり、数値が符号を持つ必要があるかどうか(符号付き)、または、 +数値が負の数になり得るかどうかを示します。つまり、数値が符号を持つ必要があるかどうか(符号付き)、または、 絶対に正数にしかならず符号なしで表現できるかどうか(符号なし)です。これは、数値を紙に書き下すのと似ています: 符号が問題になるなら、数値はプラス記号、またはマイナス記号とともに表示されます; しかしながら、 その数値が正数であると仮定することが安全なら、符号なしで表示できるわけです。符号付き数値は、 -2の補数表現で保持されます(これが何なのか確信を持てないのであれば、ネットで検索することができます。 -まあ要するに、この解説は、この本の範疇外というわけです)。 +[2の補数][twos-complement]表現で保持されます。 -加えて、`isize`と`usize`型は、プログラムが動作しているコンピュータの種類に依存します: +加えて、`isize`と`usize`型は、表では「arch」と表記していますが、プログラムが動作しているコンピュータのアーキテクチャに依存します: 64ビットアーキテクチャなら、64ビットですし、32ビットアーキテクチャなら、32ビットになります。 整数リテラル(`訳注`: リテラルとは、見たままの値ということ)は、表3-2に示すどの形式でも記述することができます。 -バイトリテラルを除く数値リテラルは全て、 -型接尾辞(例えば、`57u8`)と`_`を見た目の区切り記号(例えば、`1_000`)に付加することができます。 +複数の数値型になることができる数値リテラルは、型を指示するために型接尾辞をつけて、`57u8`のように書くことができます。 +数値リテラルはさらに、数値を読みやすくするために見た目の区切り記号として`_`をつけて、`1_000`のように書くこともできます。 +これは`1000`と指定した場合とまったく同じ値となるでしょう。 -| 数値リテラル | 例 | -|------------------|---------------| +| 数値リテラル | 例 | +|-------------------|---------------| | 10進数 | `98_222` | | 16進数 | `0xff` | | 8進数 | `0o77` | | 2進数 | `0b1111_0000` | -| バイト (`u8`だけ) | `b'A'` | +| バイト (`u8`だけ) | `b'A'` | では、どの整数型を使うべきかはどう把握すればいいのでしょうか?もし確信が持てないのならば、 -Rustの基準型は一般的にいい選択肢になります。整数型の基準は`i32`型です: 64ビットシステム上でも、 -この型が普通最速になります。`isize`と`usize`を使う主な状況は、何らかのコレクションにアクセスすることです。 +Rustの基準型は一般的にいい開始地点になります: 整数型の基準は`i32`型です。 +`isize`と`usize`を使う主な状況は、何らかのコレクションにアクセスすることです。 + + + +> ##### 整数オーバーフロー +> +> `u8`型の変数があるとしましょう。`u8`は0から255までの間の値を取ることができます。 +> この変数を範囲外の値、例えば256に変更しようとすると、*整数オーバーフロー (integer overflow)* が発生し、次の2つのうちのどちらかの挙動になります。 +> デバッグモードでコンパイルしているときは、もしこの挙動が発生したときは実行時にプログラムを*パニック (panic)* させるような、整数オーバーフローのチェックをコンパイラが入れ込みます。 +> プログラムがエラーとともに終了するとき、Rustは*パニック*という用語を使用します; +> パニックについては第9章の[「`panic!`で回復不能なエラー」][unrecoverable-errors-with-panic]でより深く議論します。 +> +> `--release`フラグを付けてリリースモードでコンパイルしているときは、コンパイラはパニックを引き起こす整数オーバーフローチェックを入れ込み*ません*。 +> 代わりに、オーバーフローが起きたときは、プログラムは*2の補数ラップアラウンド (two's complement wrapping)* を行います。 +> 一言で言うと、その型が取ることができる最大値よりも大きい値は、その型が取ることができる最小値に「回り込む」 (“wrap around”) のです。 +> `u8`の場合は、値256は0になり、値257は1になり、という感じです。 +> プログラムはパニックはしなくなるでしょうが、変数が持っている値はおそらくプログラマが期待していたものではないでしょう。 +> 整数オーバーフローのラップアラウンドの挙動に依存するのは、エラーと考えられます。 +> +> オーバーフローが発生する可能性を明示的に取り扱うためには、プリミティブ数値型に関して標準ライブラリが提供する、以下のメソッド群を使うことができます: +> +> * `wrapping_*`メソッド(`wrapping_add`等)で、モードを問わずラップアラウンドさせる。 +> * `checked_*`メソッドで、オーバーフローが発生する場合には`None`値を返す。 +> * `overflowing_*`メソッドで、値と、オーバーフローが発生したかどうかを示す論理値を返す。 +> * `saturating_*`メソッドで、値の最小値または最大値で飽和させる。(訳注: 結果が最大値を上回る場合は最大値に、最小値を下回る場合は最小値にするという意味です) Rustにはさらに、*浮動小数点数*に対しても、2種類の基本型があり、浮動小数点数とは数値に小数点がついたもののことです。 Rustの浮動小数点型は、`f32`と`f64`で、それぞれ32ビットと64ビットサイズです。基準型は`f64`です。 なぜなら、現代のCPUでは、`f32`とほぼ同スピードにもかかわらず、より精度が高くなるからです。 +すべての浮動小数点型は符号付きです。 Rustにも全数値型に期待されうる標準的な数学演算が用意されています: 足し算、引き算、掛け算、割り算、余りです。 -以下の例では、`let`文での各演算の使用方法をご覧になれます: +整数の割り算では、0に近い方の最も近い整数に切り捨てられます。 +以下の例では、`let`文での各数学演算の使用方法をご覧になれます: これらの文の各式は、数学演算子を使用しており、一つの値に評価され、そして、変数に束縛されます。 -付録BにRustで使える演算子の一覧が載っています。 +[付録B][appendix_b]にRustで使える演算子の一覧が載っています。 他の多くの言語同様、Rustの論理値型も取りうる値は二つしかありません: `true`と`false`です。 +論理値のサイズは1バイトです。 Rustの論理値型は、`bool`と指定されます。 例です: @@ -304,12 +368,12 @@ Rustの論理値型は、`bool`と指定されます。 論理値を使う主な手段は、条件式です。例えば、`if`式などですね。`if`式のRustでの動作方法については、 -「制御フロー」節で講義します。 +[「制御フロー」][control-flow]節で講義します。 -ここまで、数値型のみ扱ってきましたが、Rustには文字も用意されています。Rustの`char`型は、 -言語の最も基本的なアルファベット型であり、以下のコードでその使用方法の一例を見ることができます。 -(`char`は、ダブルクォーテーションマークを使用する文字列に対して、シングルクォートで指定されることに注意してください。) +Rustの`char`型は、言語の最も基本的なアルファベット型です。以下は`char`値を宣言するいくつかの例です: -Rustの`char`型は、ユニコードのスカラー値を表します。これはつまり、アスキーよりもずっとたくさんのものを表せるということです。 -アクセント文字; 中国語、日本語、韓国語文字; -絵文字; ゼロ幅スペースは、全てRustでは、有効な`char`型になります。ユニコードスカラー値は、 +`char`リテラルは、ダブルクォーテーションマークを使用する文字列リテラルに対して、シングルクォートで指定することに注意してください。 +Rustの`char`型は4バイトのサイズを持ち、ユニコードのスカラー値を表します。これはつまり、アスキーよりもずっとたくさんのものを表せるということです。 +アクセント記号付き文字; 中国語、日本語、韓国語の文字; +絵文字; ゼロ幅スペースはすべて、Rustでは有効な`char`値です。ユニコードスカラー値は、 `U+0000`から`U+D7FF`までと`U+E000`から`U+10FFFF`までの範囲になります。 ところが、「文字」は実はユニコードの概念ではないので、文字とは何かという人間としての直観は、 -Rustにおける`char`値が何かとは合致しない可能性があります。この話題については、第8章の「文字列」で詳しく議論しましょう。 +Rustにおける`char`値が何かとは合致しない可能性があります。この話題については、第8章の[「文字列でUTF-8でエンコードされたテキストを保持する」][strings]で詳しく議論しましょう。 #### タプル型 -タプルは、複数の型の何らかの値を一つの複合型にまとめ上げる一般的な手段です。 +*タプル*は、様々な型の複数の値を一つの複合型にまとめ上げる汎用的な手段です。 +タプルの長さは固定です: 一度宣言されたらサイズは伸縮できません。 @@ -424,7 +490,7 @@ use pattern matching to destructure a tuple value, like this: @@ -435,13 +501,11 @@ the single tuple into three parts. Finally, the program prints the value of プログラムは`y`変数の値を出力し、`6.4`と表示されます。 -パターンマッチングを通しての分配の他にも、アクセスしたい値の番号をピリオド(`.`)に続けて書くことで、 -タプルの要素に直接アクセスすることもできます。例です: +アクセスしたい値の番号をピリオド(`.`)に続けて書くことで、タプルの要素に直接アクセスすることもできます。例です: -このプログラムは、新しいタプル`x`を作成し、添え字アクセスで各要素に対して新しい変数も作成しています。 +このプログラムは、新しいタプル`x`を作成し、タプルの各要素にそれぞれの添え字を使ってアクセスしています。 多くのプログラミング言語同様、タプルの最初の添え字は0です。 + + +値をひとつも持たないタプルは*ユニット*という特別な名前を持っています。 +この値と、それに対応する型はともに`()`と書き表され、空の値や空の戻り値型を表現します。 +式は、特に値を返さなければ、暗黙的にユニット値を返します。 + @@ -470,21 +545,19 @@ index in a tuple is 0. *配列*によっても、複数の値のコレクションを得ることができます。タプルと異なり、配列の全要素は、 -同じ型でなければなりません。Rustの配列は、他の言語と異なっています。Rustの配列は、 -固定長なのです: 一度宣言されたら、サイズを伸ばすことも縮めることもできません。 +同じ型でなければなりません。一部の他の言語の配列と異なり、Rustの配列は固定長です。 -Rustでは、配列に入れる要素は、角かっこ内にカンマ区切りリストとして記述します: +配列内の要素は、角かっこ内にカンマ区切りリストとして記述します: -配列は、ヒープよりもスタック(スタックとヒープについては第4章で(つまび)らかに議論します)にデータのメモリを確保したい時、 +配列は、ヒープよりもスタック(スタックとヒープについては[第4章][stack-and-heap]で(つまび)らかに議論します)にデータのメモリを確保したい時、 または、常に固定長の要素があることを確認したい時に有効です。 -ただ、配列は、ベクタ型ほど柔軟ではありません。ベクタは、標準ライブラリによって提供されている配列と似たようなコレクション型で、 +ただ、配列は、ベクタ型ほど柔軟ではありません。*ベクタ*は、標準ライブラリによって提供されている配列と似たようなコレクション型で、 こちらは、サイズを伸縮させることが*できます*。配列とベクタ型、どちらを使うべきか確信が持てない時は、 -おそらくベクタ型を使うべきです。第8章でベクタについて詳細に議論します。 +おそらくベクタ型を使うべきです。[第8章][vectors]でベクタについて詳細に議論します。 -ベクタ型よりも配列を使いたくなるかもしれない例は、1年の月の名前を扱うプログラムです。そのようなプログラムで、 -月を追加したり削除したりすることまずないので、配列を使用できます。常に12個要素があることもわかってますからね: +しかしながら、要素数を変えられる必要はないだろうと分かっている場合は、配列のほうが便利です。 +例えば、プログラム中で月の名前を使おうとしているなら、おそらくベクタよりも配列を使うのが良いでしょう。 +常に12個要素があることもわかってますからね: ```rust let months = ["January", "February", "March", "April", "May", "June", "July", @@ -572,12 +647,13 @@ more concise way. ##### 配列の要素にアクセスする -配列は、スタック上に確保される一塊のメモリです。添え字によって、 -配列の要素にこのようにアクセスすることができます: +配列は、あらかじめ知られた固定サイズを持ち、スタック上に確保することができる一塊のメモリです。 +添え字によって、配列の要素にこのようにアクセスすることができます: この例では、`first`という名前の変数には`1`という値が格納されます。配列の`[0]`番目にある値が、 @@ -605,13 +681,13 @@ get the value `2` from index `[1]` in the array. ##### 配列要素への無効なアクセス -配列の終端を越えて要素にアクセスしようとしたら、どうなるでしょうか? -先ほどの例を以下のように変えたとすると、コンパイルは通りますが、実行するとエラーで終了します: +配列の終端を越えて要素にアクセスしようとしたらどうなるか、見てみましょう。 +第2章の数当てゲームと同じようにユーザから配列の添え字を受け取る、次のコードを実行する場合を考えてみてください: -このコードはコンパイルされます。`cargo run`で走らせ、0, 1, 2, 3, または4をこのプログラムに入力すると配列の対応する値を出力します。もし配列の末尾を超えるような、例えば10などの数字を与えると、次のような出力が表示されます。 +このコードはコンパイルされます。`cargo run`で走らせ、`0`, `1`, `2`, `3`, または`4`をこのプログラムに入力すると配列の対応する値を出力します。 +もし配列の末尾を超えるような、例えば`10`などの数字を与えると、次のような出力が表示されます。 ```console -thread 'main' panicked at 'index out of bounds: the len is 5 but the index is 10', src/main.rs:19:19 -スレッド'main'は'範囲外アクセス: 長さは5ですが、添え字は10でした', src/main.rs:19:19 -でパニックしました +thread 'main' panicked at src/main.rs:19:19: +index out of bounds: the len is 5 but the index is 10 +(スレッド'main'はsrc/main.rs:19:19でパニックしました: +範囲外アクセス: 長さは5ですが、添え字は10でした) note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace ``` -コンパイルでは何もエラーが出なかったものの、プログラムは*実行時*エラーに陥り、 -正常終了しませんでした。要素に添え字アクセスを試みると、言語は、 -指定されたその添え字が配列長よりも小さいかを確認してくれます。添え字が配列長よりも大きければ、言語は*パニック*します。 -パニックとは、プログラムがエラーで終了したことを表すRust用語です。 +プログラムは、添え字アクセスで無効な値を使用した時点で*実行時*エラーに陥りました。 +プログラムはエラーメッセージとともに終了し、最後の`println!`文を実行しませんでした。 +要素に添え字アクセスを試みると、言語は、指定されたその添え字が配列長よりも小さいかを確認してくれます。 +添え字が配列長と等しいかより大きければ、言語は*パニック*します。 +この例の場合は特にそうですが、このチェックは実行時に行われなくてはなりません。 +なぜならコンパイラは、ユーザが後でコードを実行したときに、ユーザがどんな値を入力するか知りようがないからです。 -これは、実際に稼働しているRustの安全機構の最初の例になります。低レベル言語の多くでは、 +これは、実際に稼働しているRustのメモリ安全機構の例のひとつになります。低レベル言語の多くでは、 この種のチェックは行われないため、間違った添え字を与えると、無効なメモリにアクセスできてしまいます。 Rustでは、メモリアクセスを許可し、処理を継続する代わりに即座にプログラムを終了することで、 -この種のエラーからプログラマを保護しています。Rustのエラー処理については、第9章でもっと議論します。 +この種のエラーからプログラマを保護しています。第9章ではRustのエラー処理について、そして、 +可読性が高く安全で、パニックもしなければ不正なメモリアクセスも許さないコードをどうすれば書けるのか、もっと議論します。 + + + +[comparing-the-guess-to-the-secret-number]: +ch02-00-guessing-game-tutorial.html#予想と秘密の数字を比較する +[twos-complement]: https://ja.wikipedia.org/wiki/2の補数 +[control-flow]: ch03-05-control-flow.html#制御フロー +[strings]: ch08-02-strings.html#文字列でutf-8でエンコードされたテキストを保持する +[stack-and-heap]: ch04-01-what-is-ownership.html#スタックとヒープ +[vectors]: ch08-01-vectors.html +[unrecoverable-errors-with-panic]: ch09-01-unrecoverable-errors-with-panic.html +[appendix_b]: appendix-02-operators.md diff --git a/src/ch03-03-how-functions-work.md b/src/ch03-03-how-functions-work.md index 8c16385ff..a15a56588 100644 --- a/src/ch03-03-how-functions-work.md +++ b/src/ch03-03-how-functions-work.md @@ -5,7 +5,7 @@ ## 関数 @@ -36,12 +36,12 @@ Rustの関数と変数の命名規則は、*スネークケース*(`訳注`: som ``` -Rustにおいて関数定義は、`fn`キーワードで始まり、関数名の後に丸かっこの組が続きます。 +Rustでは、`fn`に続けて関数名と丸かっこの組を入力して関数を定義します。 波かっこが、コンパイラに関数本体の開始と終了の位置を伝えます。 定義した関数は、名前に丸かっこの組を続けることで呼び出すことができます。 `another_function`関数がプログラム内で定義されているので、`main`関数内から呼び出すことができるわけです。 ソースコード中で`another_function`を`main`関数の*後*に定義していることに注目してください; 勿論、main関数の前に定義することもできます。コンパイラは、関数がどこで定義されているかは気にしません。 -どこかで定義されていることのみ気にします。 +呼び出し元から見えるスコープ内のどこかで定義されていることのみ気にします。 行出力は、`main`関数内に書かれた順序で実行されています。最初に"Hello, world"メッセージが出て、 それから`another_function`が呼ばれて、こちらのメッセージが出力されています。 -### 関数の引数 +### 引数 -関数は、引数を持つようにも定義できます。引数とは、関数シグニチャの一部になる特別な変数のことです。 -関数に引数があると、引数の位置に実際の値を与えることができます。技術的にはこの実際の値は -*実引数*と呼ばれますが、普段の会話では、仮引数("parameter")と実引数("argument")を関数定義の変数と関数呼び出し時に渡す実際の値、 -両方の意味に区別なく使います(`訳注`: 日本語では、特別区別する意図がない限り、どちらも単に引数と呼ぶことが多いでしょう)。 +関数は、*仮引数 (parameter)* を持つよう定義することもできます。仮引数とは、関数シグニチャの一部になる特別な変数のことです。 +関数に仮引数があると、仮引数に対して具体的な値を与えることができます。 +厳密にはこの具体的な値は*実引数 (argument)* と呼ばれますが、普段の会話では、関数定義内の変数と関数呼び出し時に渡す実際の値の両方の意味で、 +*parameter*と*argument*を区別なく使う傾向にあります (`訳注`: 日本語では、特別区別する意図がない限り、どちらも単に*引数*と呼ぶことが多いでしょう)。 -以下の書き直した`another_function`では、Rustの仮引数がどのようなものかを示しています: +次の版の`another_function`では、仮引数を追加しています: `another_function`の宣言には、`x`という名前の仮引数があります。`x`の型は、 -`i32`と指定されています。値`5`が`another_function`に渡されると、`println!`マクロにより、 -フォーマット文字列中の1組の波かっこがあった位置に値`5`が出力されます。 +`i32`と指定されています。値`5`を`another_function`に渡すと、`println!`マクロにより、 +フォーマット文字列中の`x`を含む1組の波かっこがあった位置に値`5`が出力されます。 関数シグニチャにおいて、各仮引数の型を宣言しなければ*なりません*。これは、Rustの設計において、 -意図的な判断です: 関数定義で型注釈が必要不可欠ということは、コンパイラがその意図するところを推し量るのに、 +意図的な判断です: 関数定義で型注釈が必要不可欠ということは、コンパイラがその意図する型を推し量るのに、 プログラマがコードの他の箇所で使用する必要がないということを意味します。 +コンパイラも、関数が期待する型を知っていれば、より役に立つエラーメッセージを与えることができます。 -関数に複数の仮引数を持たせたいときは、仮引数定義をカンマで区切ってください。 +関数に複数の仮引数を定義したいときは、仮引数定義をカンマで区切ってください。 こんな感じです: -この例では、2引数の関数を生成しています。そして、引数はどちらも`i32`型です。それからこの関数は、 -仮引数の値を両方出力します。関数引数は、全てが同じ型である必要はありません。今回は、 -偶然同じになっただけです。 +この例では、`print_labeled_measurement`という名前の2引数の関数を生成しています。 +第1引数は`value`という名前で`i32`です。第2引数は`unit_label`という名前で`char`型です。 +この関数は`value`と`unit_label`の両方を含むテキストを出力します。 -`x`に対して値`5`、`y`に対して値`6`を渡して関数を呼び出したので、この二つの文字列は、 -この値で出力されました。 +`value`に対して値`5`、`unit_label`に対して値`'h'`を渡して関数を呼び出したので、 +プログラムの出力にはこれらの値が含まれます。 - - -### 関数本体は、文と式を含む +### 文と式 -関数本体は、文が並び、最後に式を置くか文を置くという形で形成されます。現在までには、 -式で終わらない関数だけを見てきたわけですが、式が文の一部になっているものなら見かけましたね。Rustは、式指向言語なので、 +関数本体は、文が並び、最後に式を置くか文を置くという形で形成されます。今のところ、 +私たちが見てきた関数は式で終わることはありませんでしたが、式が文の一部になっているものなら見かけましたね。Rustは、式指向言語なので、 これは理解しておくべき重要な差異になります。他の言語にこの差異はありませんので、文と式がなんなのかと、 その違いが関数本体にどんな影響を与えるかを見ていきましょう。 -実のところ、もう文と式は使っています。*文*とは、なんらかの動作をして値を返さない命令です。 -*式*は結果値に評価されます。ちょっと例を眺めてみましょう。 +* *文 (statement)* はなんらかの動作をして値を返さない命令です。 +* *式 (expression)* は結果値に評価されます。ちょっと例を眺めてみましょう。 +実のところ、もう文と式は使っています。 `let`キーワードを使用して変数を生成し、値を代入することは文になります。 リスト3-1で`let y = 6;`は文です。 @@ -273,7 +272,7 @@ asは前の文にかかるべきだが、大して意味が変わらないので 文は値を返しません。故に、`let`文を他の変数に代入することはできません。 @@ -314,19 +313,19 @@ CやRubyなどの言語とは異なる動作です。CやRubyでは、代入は そうは問屋が卸さないわけです。 -式は何かに評価され、これからあなたが書くRustコードの多くを構成します。 -簡単な数学演算(`5 + 6`など)を思い浮かべましょう。この例は、値`11`に評価される式です。式は文の一部になりえます: +式は値に評価され、これからあなたが書くRustコードの多くを構成します。 +数学演算(`5 + 6`など)を思い浮かべましょう。この例は、値`11`に評価される式です。式は文の一部になりえます: リスト3-1において、`let y = 6`という文の`6`は値`6`に評価される式です。関数呼び出しも式です。マクロ呼び出しも式です。 -新しいスコープを作る際に使用するブロック(`{}`)も式です: +波括弧で作られる新しいスコープも式です: は今回の場合、`4`に評価されるブロックです。その値が、`let`文の一部として`y`に束縛されます。 -今まで見かけてきた行と異なり、文末にセミコロンがついていない`x + 1`の行に気をつけてください。 +今まで見かけてきた行と異なり、`x + 1`の行には文末にセミコロンがついていないことに気をつけてください。 式は終端にセミコロンを含みません。式の終端にセミコロンを付けたら、文に変えてしまいます。そして、文は値を返しません。 次に関数の戻り値や式を見ていく際にこのことを肝に銘じておいてください。 @@ -373,16 +373,16 @@ Keep this in mind as you explore function return values and expressions next. 関数は、それを呼び出したコードに値を返すことができます。戻り値に名前を付けはしませんが、 -矢印(`->`)の後に型を書いて確かに宣言します。Rustでは、関数の戻り値は、関数本体ブロックの最後の式の値と同義です。 +矢印(`->`)の後に型を書いて宣言する必要があります。Rustでは、関数の戻り値は、関数本体ブロックの最後の式の値と同義です。 `return`キーワードで関数から早期リターンし、値を指定することもできますが、多くの関数は最後の式を暗黙的に返します。 こちらが、値を返す関数の例です: @@ -399,7 +399,7 @@ returns a value: @@ -437,7 +437,7 @@ because it’s an expression whose value we want to return. なぜなら、これが返したい値になる式だからです。 もう一つ別の例を見ましょう: @@ -455,7 +455,7 @@ Let's look at another example: このコードを走らせると、`The value of x is: 6`と出力されるでしょう。しかし、 @@ -472,27 +472,27 @@ expression to a statement, we'll get an error: ``` -このコードを実行すると、以下のようにエラーが出ます: +このコードをコンパイルすると、以下のようにエラーが出ます: ```console {{#include ../listings/ch03-common-programming-concepts/no-listing-23-statements-dont-return-values/output.txt}} ``` -メインのエラーメッセージである「型が合いません」でこのコードの根本的な問題が明らかになるでしょう。 +メインのエラーメッセージである`mismatched types (型が合いません)`でこのコードの根本的な問題が明らかになるでしょう。 関数`plus_one`の定義では、`i32`型を返すと言っているのに、文は値に評価されないからです。このことは、 -`()`、つまり空のタプルとして表現されています。それゆえに、何も戻り値がなく、これが関数定義と矛盾するので、 +`()`、つまりユニット型として表現されています。それゆえに、何も戻り値がなく、これが関数定義と矛盾するので、 結果としてエラーになるわけです。この出力内で、コンパイラは問題を修正する手助けになりそうなメッセージも出していますね: セミコロンを削除するよう提言しています。そして、そうすれば、エラーは直るわけです。 diff --git a/src/ch03-04-comments.md b/src/ch03-04-comments.md index c3d0ad086..22a08329c 100644 --- a/src/ch03-04-comments.md +++ b/src/ch03-04-comments.md @@ -6,13 +6,13 @@ 全プログラマは、自分のコードがわかりやすくなるよう努めますが、時として追加の説明が許されることもあります。 -このような場合、プログラマは注釈または*コメント*をソースコードに残し、コメントをコンパイラは無視しますが、 +このような場合、プログラマは*コメント*をソースコードに残し、コメントをコンパイラは無視しますが、 ソースコードを読む人間には有益なものと思えるでしょう。 -Rustでは、コメントは2連スラッシュで始め、行の終わりまで続きます。コメントが複数行にまたがる場合、 +Rustの慣用的なコメントスタイルでは、コメントは2連スラッシュで始め、行の終わりまで続きます。コメントが複数行にまたがる場合、 各行に`//`を含める必要があります。こんな感じに: ```rust @@ -48,7 +48,11 @@ Comments can also be placed at the end of lines containing code: コメントは、コードが書かれた行の末尾にも配置することができます: + + +ファイル名: src/main.rs ```rust {{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-24-comments-end-of-line/src/main.rs}} @@ -56,11 +60,15 @@ Comments can also be placed at the end of lines containing code: しかし、こちらの形式のコメントの方が見かける機会は多いでしょう。注釈しようとしているコードの1行上に書く形式です: + + ファイル名: src/main.rs ```rust @@ -69,7 +77,10 @@ separate line above the code it's annotating: -Rustには他の種類のコメント、ドキュメントコメントもあり、それについては第14章で議論します。 +Rustには他の種類のコメント、ドキュメントコメントもあり、それについては第14章の[「Crates.ioにクレートを公開する」][publishing]節で議論します。 + +[publishing]: ch14-02-publishing-to-crates-io.html diff --git a/src/ch03-05-control-flow.md b/src/ch03-05-control-flow.md index 71397a24c..aed7faa7b 100644 --- a/src/ch03-05-control-flow.md +++ b/src/ch03-05-control-flow.md @@ -5,15 +5,14 @@ ## 制御フロー -条件が真かどうかによってコードを走らせるかどうかを決定したり、 -条件が真の間繰り返しコードを走らせるか決定したりすることは、多くのプログラミング言語において、基本的な構成ブロックです。 +条件が`true`かどうかによってコードを走らせたり、 +条件が`true`の間繰り返しコードを走らせたりできることは、多くのプログラミング言語において、基本的な構成ブロックです。 Rustコードの実行フローを制御する最も一般的な文法要素は、`if`式とループです。 @@ -50,31 +49,27 @@ the `if` expression. In the *src/main.rs* file, input the following: ``` - - `if`式は全て、キーワードの`if`から始め、条件式を続けます。今回の場合、 条件式は変数`number`が5未満の値になっているかどうかをチェックします。 -条件が真の時に実行したい一連のコードを条件式の直後に波かっこで包んで配置します。`if`式の条件式と紐付けられる一連のコードは、 +条件が`true`の時に実行する一連のコードを条件式の直後に波かっこで包んで配置します。`if`式の条件式と紐付けられる一連のコードは、 時として*アーム*と呼ばれることがあります。 -第2章の「予想と秘密の数字を比較する」の節で議論した`match`式のアームと同じです。 +第2章の[「予想と秘密の数字を比較する」][comparing-the-guess-to-the-secret-number]の節で議論した`match`式のアームと同じです。 @@ -180,11 +175,11 @@ Running this code will print `number was something other than zero`. #### `else if`で複数の条件を扱う -`if`と`else`を組み合わせて`else if`式にすることで複数の条件を持たせることもできます。例です: +`if`と`else`を組み合わせて`else if`式にすることで複数の条件を使うこともできます。例です: -このプログラムを実行すると、`if`式が順番に吟味され、最初に条件が真になった本体が実行されます。 +このプログラムを実行すると、`if`式が順番に吟味され、最初に条件が`true`に評価された本体が実行されます。 6は2で割り切れるものの、`number is devisible by 2`や、 `else`ブロックの`number is not divisible by 4, 3, or 2`という出力はされないことに注目してください。 -それは、Rustが最初の真条件のブロックのみを実行し、 +それは、Rustが最初の`true`な条件のブロックのみを実行し、 条件に合ったものが見つかったら、残りはチェックすらしないからです。 -`if`は式なので、`let`文の右辺に持ってくることができます。リスト3-2のようにですね。 +`if`は式なので、`let`文の右辺に持ってきて結果を変数に代入することができます。リスト3-2のようにですね。 + リスト3-2: `if`式の結果を変数に代入する @@ -278,7 +275,7 @@ whole `if` expression depends on which block of code executes. This means the values that have the potential to be results from each arm of the `if` must be the same type; in Listing 3-2, the results of both the `if` arm and the `else` arm were `i32` integers. If the types are mismatched, as in the following -example, we'll get an error: +example, we’ll get an error: --> 一連のコードは、そのうちの最後の式に評価され、数値はそれ単独でも式になることを思い出してください。 @@ -313,17 +310,17 @@ find the problem in the program: `if`ブロックの式は整数に評価され、`else`ブロックの式は文字列に評価されます。これでは動作しません。 -変数は単独の型でなければならないからです。コンパイラは、コンパイル時に`number`変数の型を確実に把握する必要があるため、 -コンパイル時に`number`が使われている箇所全部で型が有効かどうか検査することができるのです。 +変数は単独の型でなければならず、コンパイラは、コンパイル時に`number`変数の型を確実に把握する必要があるからです。 +`number`の型を把握していることで、コンパイラは、コンパイル時に`number`が使われている箇所全部で型が有効であるか検証できるのです。 `number`の型が実行時にしか決まらないのであれば、コンパイラはそれを実行することができなくなってしまいます; どの変数に対しても、架空の複数の型があることを追いかけなければならないのであれば、コンパイラはより複雑になり、 コードに対して行える保証が少なくなってしまうでしょう。 @@ -336,9 +333,9 @@ multiple hypothetical types for any variable. 一連のコードを1回以上実行できると、しばしば役に立ちます。この作業用に、 @@ -384,19 +381,25 @@ like this: このプログラムを実行すると、プログラムを手動で止めるまで、何度も何度も続けて`again!`と出力するでしょう。 ほとんどの端末でctrl-cというショートカットが使え、 -永久ループに囚われてしまったプログラムを終了させられます。試しにやってみましょう: +永久ループに囚われてしまったプログラムに割り込むことができます。試しにやってみましょう: + + ```console $ cargo run Compiling loops v0.1.0 (file:///projects/loops) - Finished dev [unoptimized + debuginfo] target(s) in 0.29 secs + Finished dev [unoptimized + debuginfo] target(s) in 0.29s Running `target/debug/loops` again! again! @@ -406,25 +409,27 @@ again! ``` `^C`という記号が出た場所が、ctrl-cを押した場所です。`^C`の後には`again!`と表示されたり、 -されなかったりします。ストップシグナルをコードが受け取った時にループのどこにいたかによります。 +されなかったりします。割り込みシグナルをコードが受け取った時にループのどこにいたかによります。 -幸いなことに、Rustにはループを抜け出す別のより信頼できる手段があります。 +幸いなことに、Rustにはコードによってループを抜け出す手段もあります。 ループ内に`break`キーワードを配置することで、プログラムに実行を終了すべきタイミングを教えることができます。 -第2章の「正しい予想をした後に終了する」節の数当てゲーム内でこれをして、ユーザが予想を的中させ、 +第2章の[「正しい予想をした後に終了する」][quitting-after-a-correct-guess]節の数当てゲーム内でこれをして、ユーザが予想を的中させ、 ゲームに勝った時にプログラムを終了させたことを思い出してください。 + +#### ループから値を返す + + + +`loop`の使用法のひとつとして、失敗するかもしれないと分かっている操作、 +例えばスレッドがそのジョブを完了したかを確認する操作などを、リトライするというのがあります。 +さらに、コードの他の部分で使うために、ループの外に操作の結果を渡す必要があるかもしれません。 +これを行うには、ループを止めるために使っている`break`式の後ろに、返したい値を付け加えてください; +その値はループを抜けて返され、使うことができます。このように: + +```rust +{{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-33-return-value-from-loop/src/main.rs}} +``` + + + +ループの前で`counter`という変数を宣言し、`0`に初期化しています。 +次に、ループから返された値を保持するために、`result`という変数を宣言しています。 +ループの繰り返しごとに、`counter`変数に`1`を追加し、`counter`が`10`に等しいかチェックします。 +等しい場合は、値`counter * 2`とともに`break`キーワードを使用しています。 +ループの後には、値を`result`に代入する文を終了するためのセミコロンが使われています。 +最後に、`result`の値を出力していて、この場合は`20`です。 + + + +#### 複数のループを区別するループラベル + ループ内にループがある場合、`break`と`continue`は最も内側のループに適用されます。 *ループラベル*を使用することで、`break`や`continue`が適用されるループを指定することができます。 +ループラベルはシングルクオートで始める必要があります。 以下に例を示します。 @@ -477,28 +531,23 @@ doesn’t specify a label will exit the inner loop only. The `break #### `while`で条件付きループ -プログラムにとってループ内で条件式を評価できると、有益なことがしばしばあります。条件が真の間、 -ループが走るわけです。条件が真でなくなった時にプログラムは`break`を呼び出し、ループを終了します。 -このタイプのループは、`loop`、`if`、`else`、`break`を組み合わせることでも実装できます; +プログラムは、ループ内で条件式を評価することがよく必要になるでしょう。条件が`true`の間、 +ループが走るわけです。条件が`true`でなくなった時にプログラムは`break`を呼び出し、ループを終了します。 +このような挙動は、`loop`、`if`、`else`、`break`を組み合わせることでも実装できます; お望みなら、プログラムで今、試してみるのもいいでしょう。 - - - しかし、このパターンは頻出するので、Rustにはそれ用の文法要素が用意されていて、`while`ループと呼ばれます。 -リスト3-3は、`while`を使用しています: プログラムは3回ループし、それぞれカウントダウンします。 -それから、ループ後に別のメッセージを表示して終了します: +リスト3-3では、プログラムを3回ループさせるために`while`を使用しています。 +繰り返しごとにカウントダウンして、ループ後にメッセージを表示して終了します。 この文法要素により、`loop`、`if`、`else`、`break`を使った時に必要になるネストがなくなり、 -より明確になります。条件が真の間、コードは実行されます; そうでなければ、ループを抜けます. +より明確になります。条件が`true`に評価される間、コードは実行されます; そうでなければ、ループを抜けます. -`while`要素を使って配列などのコレクションの要素を覗き見ることができます。例えば、リスト3-4を見ましょう。 +配列などのコレクションの要素を覗き見るために、`while`要素を使うこともできます。 +例えば、リスト3-4のループは配列`a`の各要素を出力します。 ここで、コードは配列の要素を順番にカウントアップして覗いています。番号0から始まり、 -配列の最終番号に到達するまでループします(つまり、`index < 5`が真でなくなる時です)。 +配列の最終番号に到達するまでループします(つまり、`index < 5`が`true`でなくなる時です)。 このコードを走らせると、配列内の全要素が出力されます: ```console @@ -581,23 +632,26 @@ to fetch a sixth value from the array. 配列から6番目の値を拾おうとする前にループは実行を終了します。 -しかし、このアプローチは間違いが発生しやすいです; 添え字の長さが間違っていれば、 -プログラムはパニックしてしまいます。また遅いです。 -コンパイラが実行時にループの各回ごとに境界値チェックを行うようなコードを追加するからです。 +しかし、このアプローチは間違いが発生しやすいです; 添え字の値や判定条件が間違っていれば、 +プログラムはパニックしてしまいます。例えば、`a`配列の定義を4要素を持つように変更したのに、 +条件を`while index < 4`に更新し忘れた場合、コードはパニックするでしょう。また遅いです。 +実行時にループの各回ごとに添字が配列の境界内にあるかチェックするコードを、コンパイラが追加するからです。 -より効率的な対立案として、`for`ループを使ってコレクションの各アイテムに対してコードを実行することができます。 -`for`ループはリスト3-5のこんな見た目です。 +より簡潔な対立案として、`for`ループを使ってコレクションの各アイテムに対してコードを実行することができます。 +`for`ループはリスト3-5のコードのようになります。 -例えば、リスト3-4のコードで、`a`配列からアイテムを1つ削除したのに、条件式を`while index < 4`にするのを忘れていたら、 -コードはパニックします。`for`ループを使っていれば、配列の要素数を変えても、 -他のコードをいじることを覚えておく必要はなくなるわけです。 +`for`ループを使っていれば、配列の要素数を変えても、 +リスト3-4で使った方法のように他のコードをいじることを覚えておく必要はなくなるわけです。 `for`ループのこの安全性と簡潔性により、Rustで使用頻度の最も高いループになっています。 リスト3-3で`while`ループを使ったカウントダウンサンプルのように、一定の回数、同じコードを実行したいような状況であっても、 多くのRustaceanは、`for`ループを使うでしょう。どうやってやるかといえば、 -`Range`型を使うのです。Range型は、標準ライブラリで提供される片方の数字から始まって、 +標準ライブラリで提供される`Range`型を使うのです。`Range`型は、片方の数字から始まって、 もう片方の数字未満の数値を順番に生成する型です。 やりましたね!結構長い章でした: 変数、スカラー値と複合データ型、関数、コメント、`if`式、そして、ループについて学びました! -この章で議論した概念について経験を積みたいのであれば、以下のことをするプログラムを組んでみてください: +この章で議論した概念について経験を積むために、以下のことをするプログラムを組んでみてください: * 温度を華氏と摂氏で変換する。 -* フィボナッチ数列のn番目を生成する。 +* フィボナッチ数列の*n*番目を生成する。 * クリスマスキャロルの定番、"The Twelve Days of Christmas"の歌詞を、 曲の反復性を利用して出力する。 @@ -711,3 +763,15 @@ commonly exist in other programming languages: ownership. --> 次に進む準備ができたら、他の言語にはあまり存在*しない*Rustの概念について話しましょう: 所有権です。 + + + +[comparing-the-guess-to-the-secret-number]: +ch02-00-guessing-game-tutorial.html#予想と秘密の数字を比較する +[quitting-after-a-correct-guess]: +ch02-00-guessing-game-tutorial.html#正しい予想をした後に終了する From 005ab5777b01993e54341aadb424b6293c66e2ad Mon Sep 17 00:00:00 2001 From: shinmili Date: Sun, 26 May 2024 12:58:02 +0900 Subject: [PATCH 05/10] =?UTF-8?q?ch04=20=E6=89=80=E6=9C=89=E6=A8=A9?= =?UTF-8?q?=E3=82=92=E7=90=86=E8=A7=A3=E3=81=99=E3=82=8B=E3=81=AE=E5=92=8C?= =?UTF-8?q?=E8=A8=B3=E3=82=92=E6=9C=80=E6=96=B0=E7=89=88=E3=81=AB=E6=9B=B4?= =?UTF-8?q?=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit rust-lang/book@19c40bfd2d57641d962f3119a1c343355f1b3c5e --- .../listing-04-01/Cargo.toml | 3 +- .../listing-04-01/src/main.rs | 8 +- .../listing-04-02/Cargo.toml | 3 +- .../listing-04-03/Cargo.toml | 3 +- .../listing-04-03/src/main.rs | 28 +- .../listing-04-04/Cargo.toml | 3 +- .../listing-04-04/src/main.rs | 34 +- .../listing-04-05/Cargo.toml | 3 +- .../listing-04-05/src/main.rs | 3 +- .../listing-04-06/Cargo.toml | 3 +- .../listing-04-06/output.txt | 16 +- .../listing-04-07/Cargo.toml | 3 +- .../listing-04-08/Cargo.toml | 3 +- .../listing-04-09/Cargo.toml | 3 +- .../listing-04-09/src/main.rs | 15 +- .../Cargo.toml | 3 +- .../src/main.rs | 4 +- .../no-listing-02-string-scope/Cargo.toml | 3 +- .../no-listing-02-string-scope/src/main.rs | 10 +- .../no-listing-03-string-move/Cargo.toml | 3 +- .../Cargo.toml | 3 +- .../output.txt | 20 +- .../no-listing-05-clone/Cargo.toml | 3 +- .../no-listing-06-copy/Cargo.toml | 3 +- .../no-listing-07-reference/Cargo.toml | 3 +- .../no-listing-07-reference/src/main.rs | 1 + .../Cargo.toml | 3 +- .../src/main.rs | 6 +- .../Cargo.toml | 3 +- .../Cargo.toml | 3 +- .../output.txt | 12 +- .../Cargo.toml | 3 +- .../src/main.rs | 2 +- .../Cargo.toml | 3 +- .../output.txt | 18 +- .../src/main.rs | 6 +- .../Cargo.toml | 3 +- .../src/main.rs | 8 +- .../Cargo.toml | 3 +- .../output.txt | 22 +- .../Cargo.toml | 3 +- .../src/main.rs | 10 +- .../no-listing-16-no-dangle/Cargo.toml | 3 +- .../no-listing-17-slice/Cargo.toml | 3 +- .../no-listing-18-first-word-slice/Cargo.toml | 3 +- .../no-listing-19-slice-error/Cargo.toml | 3 +- .../no-listing-19-slice-error/output.txt | 10 +- src/ch04-00-understanding-ownership.md | 15 +- src/ch04-01-what-is-ownership.md | 860 +++++++----------- src/ch04-02-references-and-borrowing.md | 422 +++------ src/ch04-03-slices.md | 180 ++-- 51 files changed, 749 insertions(+), 1045 deletions(-) diff --git a/listings/ch04-understanding-ownership/listing-04-01/Cargo.toml b/listings/ch04-understanding-ownership/listing-04-01/Cargo.toml index 686de938f..e8847526d 100644 --- a/listings/ch04-understanding-ownership/listing-04-01/Cargo.toml +++ b/listings/ch04-understanding-ownership/listing-04-01/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "ownership" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch04-understanding-ownership/listing-04-01/src/main.rs b/listings/ch04-understanding-ownership/listing-04-01/src/main.rs index 148ad84c9..baee5d9ab 100644 --- a/listings/ch04-understanding-ownership/listing-04-01/src/main.rs +++ b/listings/ch04-understanding-ownership/listing-04-01/src/main.rs @@ -1,9 +1,9 @@ fn main() { // ANCHOR: here - { // s is not valid here, it’s not yet declared - let s = "hello"; // s is valid from this point forward + { // sは、ここでは有効ではない。まだ宣言されていない + let s = "hello"; // sは、ここから有効になる - // do stuff with s - } // this scope is now over, and s is no longer valid + // sで作業をする + } // このスコープは終わり。もうsは有効ではない // ANCHOR_END: here } \ No newline at end of file diff --git a/listings/ch04-understanding-ownership/listing-04-02/Cargo.toml b/listings/ch04-understanding-ownership/listing-04-02/Cargo.toml index 686de938f..e8847526d 100644 --- a/listings/ch04-understanding-ownership/listing-04-02/Cargo.toml +++ b/listings/ch04-understanding-ownership/listing-04-02/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "ownership" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch04-understanding-ownership/listing-04-03/Cargo.toml b/listings/ch04-understanding-ownership/listing-04-03/Cargo.toml index 686de938f..e8847526d 100644 --- a/listings/ch04-understanding-ownership/listing-04-03/Cargo.toml +++ b/listings/ch04-understanding-ownership/listing-04-03/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "ownership" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch04-understanding-ownership/listing-04-03/src/main.rs b/listings/ch04-understanding-ownership/listing-04-03/src/main.rs index 23906b430..221679d95 100644 --- a/listings/ch04-understanding-ownership/listing-04-03/src/main.rs +++ b/listings/ch04-understanding-ownership/listing-04-03/src/main.rs @@ -1,23 +1,23 @@ fn main() { - let s = String::from("hello"); // s comes into scope + let s = String::from("hello"); // sがスコープに入る - takes_ownership(s); // s's value moves into the function... - // ... and so is no longer valid here + takes_ownership(s); // sの値が関数にムーブされ... + // ... ここではもう有効ではない - let x = 5; // x comes into scope + let x = 5; // xがスコープに入る - makes_copy(x); // x would move into the function, - // but i32 is Copy, so it’s okay to still - // use x afterward + makes_copy(x); // xも関数にムーブされるが、 + // i32はCopyなので、この後にxを使っても + // 大丈夫 -} // Here, x goes out of scope, then s. But because s's value was moved, nothing - // special happens. +} // ここでxがスコープを抜け、sもスコープを抜ける。ただし、sの値はムーブされているので、 + // 何も特別なことは起こらない。 -fn takes_ownership(some_string: String) { // some_string comes into scope +fn takes_ownership(some_string: String) { // some_stringがスコープに入る。 println!("{}", some_string); -} // Here, some_string goes out of scope and `drop` is called. The backing - // memory is freed. +} // ここでsome_stringがスコープを抜け、`drop`が呼ばれる。後ろ盾してたメモリが解放される。 + // 後ろ盾してたメモリが解放される。 -fn makes_copy(some_integer: i32) { // some_integer comes into scope +fn makes_copy(some_integer: i32) { // some_integerがスコープに入る println!("{}", some_integer); -} // Here, some_integer goes out of scope. Nothing special happens. +} // ここでsome_integerがスコープを抜ける。何も特別なことはない。 diff --git a/listings/ch04-understanding-ownership/listing-04-04/Cargo.toml b/listings/ch04-understanding-ownership/listing-04-04/Cargo.toml index 686de938f..e8847526d 100644 --- a/listings/ch04-understanding-ownership/listing-04-04/Cargo.toml +++ b/listings/ch04-understanding-ownership/listing-04-04/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "ownership" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch04-understanding-ownership/listing-04-04/src/main.rs b/listings/ch04-understanding-ownership/listing-04-04/src/main.rs index e3e54a818..bb3aa1842 100644 --- a/listings/ch04-understanding-ownership/listing-04-04/src/main.rs +++ b/listings/ch04-understanding-ownership/listing-04-04/src/main.rs @@ -1,29 +1,25 @@ fn main() { - let s1 = gives_ownership(); // gives_ownership moves its return - // value into s1 + let s1 = gives_ownership(); // gives_ownershipは、戻り値をs1に + // ムーブする - let s2 = String::from("hello"); // s2 comes into scope + let s2 = String::from("hello"); // s2がスコープに入る - let s3 = takes_and_gives_back(s2); // s2 is moved into - // takes_and_gives_back, which also - // moves its return value into s3 -} // Here, s3 goes out of scope and is dropped. s2 goes out of scope but was - // moved, so nothing happens. s1 goes out of scope and is dropped. + let s3 = takes_and_gives_back(s2); // s2はtakes_and_gives_backにムーブされ + // 戻り値もs3にムーブされる +} // ここで、s3はスコープを抜け、ドロップされる。s2もスコープを抜けるが、ムーブされているので、 + // 何も起きない。s1もスコープを抜け、ドロップされる。 -fn gives_ownership() -> String { // gives_ownership will move its - // return value into the function - // that calls it +fn gives_ownership() -> String { // gives_ownershipは、戻り値を + // 呼び出した関数にムーブする - let some_string = String::from("hello"); // some_string comes into scope + let some_string = String::from("hello"); // some_stringがスコープに入る - some_string // some_string is returned and - // moves out to the calling - // function + some_string // some_stringが返され、呼び出し元関数に + // ムーブされる } -// takes_and_gives_back will take a String and return one -fn takes_and_gives_back(a_string: String) -> String { // a_string comes into - // scope +// takes_and_gives_backは、Stringを一つ受け取り、返す。 +fn takes_and_gives_back(a_string: String) -> String { // a_stringがスコープに入る。 - a_string // a_string is returned and moves out to the calling function + a_string // a_stringが返され、呼び出し元関数にムーブされる } diff --git a/listings/ch04-understanding-ownership/listing-04-05/Cargo.toml b/listings/ch04-understanding-ownership/listing-04-05/Cargo.toml index 686de938f..e8847526d 100644 --- a/listings/ch04-understanding-ownership/listing-04-05/Cargo.toml +++ b/listings/ch04-understanding-ownership/listing-04-05/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "ownership" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch04-understanding-ownership/listing-04-05/src/main.rs b/listings/ch04-understanding-ownership/listing-04-05/src/main.rs index 22aee1419..1f0faaa93 100644 --- a/listings/ch04-understanding-ownership/listing-04-05/src/main.rs +++ b/listings/ch04-understanding-ownership/listing-04-05/src/main.rs @@ -3,11 +3,12 @@ fn main() { let (s2, len) = calculate_length(s1); + //'{}'の長さは、{}です println!("The length of '{}' is {}.", s2, len); } fn calculate_length(s: String) -> (String, usize) { - let length = s.len(); // len() returns the length of a String + let length = s.len(); // len()メソッドは、Stringの長さを返します (s, length) } diff --git a/listings/ch04-understanding-ownership/listing-04-06/Cargo.toml b/listings/ch04-understanding-ownership/listing-04-06/Cargo.toml index 686de938f..e8847526d 100644 --- a/listings/ch04-understanding-ownership/listing-04-06/Cargo.toml +++ b/listings/ch04-understanding-ownership/listing-04-06/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "ownership" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch04-understanding-ownership/listing-04-06/output.txt b/listings/ch04-understanding-ownership/listing-04-06/output.txt index 98f438f61..019356390 100644 --- a/listings/ch04-understanding-ownership/listing-04-06/output.txt +++ b/listings/ch04-understanding-ownership/listing-04-06/output.txt @@ -1,16 +1,18 @@ $ cargo run Compiling ownership v0.1.0 (file:///projects/ownership) error[E0596]: cannot borrow `*some_string` as mutable, as it is behind a `&` reference + (`*some_string`は`&`参照の背後にあるため、それを可変として借用することはできません) --> src/main.rs:8:5 | -7 | fn change(some_string: &String) { - | ------- help: consider changing this to be a mutable reference: `&mut std::string::String` 8 | some_string.push_str(", world"); | ^^^^^^^^^^^ `some_string` is a `&` reference, so the data it refers to cannot be borrowed as mutable - -error: aborting due to previous error + | (`some_string`は`&`参照なので、それが指すデータを可変として借用することはできません) + | +help: consider changing this to be a mutable reference + (これを可変参照に変更することを検討してください) + | +7 | fn change(some_string: &mut String) { + | +++ For more information about this error, try `rustc --explain E0596`. -error: could not compile `ownership`. - -To learn more, run the command again with --verbose. +error: could not compile `ownership` (bin "ownership") due to 1 previous error diff --git a/listings/ch04-understanding-ownership/listing-04-07/Cargo.toml b/listings/ch04-understanding-ownership/listing-04-07/Cargo.toml index dddcb5a14..e8847526d 100644 --- a/listings/ch04-understanding-ownership/listing-04-07/Cargo.toml +++ b/listings/ch04-understanding-ownership/listing-04-07/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "ownership" version = "0.1.0" -authors = ["Carol (Nichols || Goulding) "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch04-understanding-ownership/listing-04-08/Cargo.toml b/listings/ch04-understanding-ownership/listing-04-08/Cargo.toml index 686de938f..e8847526d 100644 --- a/listings/ch04-understanding-ownership/listing-04-08/Cargo.toml +++ b/listings/ch04-understanding-ownership/listing-04-08/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "ownership" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch04-understanding-ownership/listing-04-09/Cargo.toml b/listings/ch04-understanding-ownership/listing-04-09/Cargo.toml index 686de938f..e8847526d 100644 --- a/listings/ch04-understanding-ownership/listing-04-09/Cargo.toml +++ b/listings/ch04-understanding-ownership/listing-04-09/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "ownership" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch04-understanding-ownership/listing-04-09/src/main.rs b/listings/ch04-understanding-ownership/listing-04-09/src/main.rs index b3447e826..fb632583d 100644 --- a/listings/ch04-understanding-ownership/listing-04-09/src/main.rs +++ b/listings/ch04-understanding-ownership/listing-04-09/src/main.rs @@ -16,14 +16,21 @@ fn first_word(s: &str) -> &str { fn main() { let my_string = String::from("hello world"); - // first_word works on slices of `String`s - // first_wordは`String`のスライスに対して機能する + // `first_word` works on slices of `String`s, whether partial or whole + // `first_word`は`String`の全体または部分へのスライスに対して機能する + let word = first_word(&my_string[0..6]); let word = first_word(&my_string[..]); + // `first_word` also works on references to `String`s, which are equivalent + // to whole slices of `String`s + // `first_word`は`String`の参照に対しても機能する。この場合は + // `String`全体へのスライスと同等。 + let word = first_word(&my_string); let my_string_literal = "hello world"; - // first_word works on slices of string literals - // first_wordは文字列リテラルのスライスに対して機能する + // `first_word` works on slices of string literals, whether partial or whole + // `first_word`は文字列リテラルの全体または部分へのスライスに対して機能する + let word = first_word(&my_string_literal[0..6]); let word = first_word(&my_string_literal[..]); // Because string literals *are* string slices already, diff --git a/listings/ch04-understanding-ownership/no-listing-01-can-mutate-string/Cargo.toml b/listings/ch04-understanding-ownership/no-listing-01-can-mutate-string/Cargo.toml index 686de938f..e8847526d 100644 --- a/listings/ch04-understanding-ownership/no-listing-01-can-mutate-string/Cargo.toml +++ b/listings/ch04-understanding-ownership/no-listing-01-can-mutate-string/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "ownership" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch04-understanding-ownership/no-listing-01-can-mutate-string/src/main.rs b/listings/ch04-understanding-ownership/no-listing-01-can-mutate-string/src/main.rs index b68f0f1e7..e9782f2d6 100644 --- a/listings/ch04-understanding-ownership/no-listing-01-can-mutate-string/src/main.rs +++ b/listings/ch04-understanding-ownership/no-listing-01-can-mutate-string/src/main.rs @@ -2,8 +2,8 @@ fn main() { // ANCHOR: here let mut s = String::from("hello"); - s.push_str(", world!"); // push_str() appends a literal to a String + s.push_str(", world!"); // push_str()関数は、リテラルをStringに付け加える - println!("{}", s); // This will print `hello, world!` + println!("{}", s); // これは`hello, world!`と出力する // ANCHOR_END: here } diff --git a/listings/ch04-understanding-ownership/no-listing-02-string-scope/Cargo.toml b/listings/ch04-understanding-ownership/no-listing-02-string-scope/Cargo.toml index 686de938f..e8847526d 100644 --- a/listings/ch04-understanding-ownership/no-listing-02-string-scope/Cargo.toml +++ b/listings/ch04-understanding-ownership/no-listing-02-string-scope/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "ownership" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch04-understanding-ownership/no-listing-02-string-scope/src/main.rs b/listings/ch04-understanding-ownership/no-listing-02-string-scope/src/main.rs index 7e6d46f83..db803b700 100644 --- a/listings/ch04-understanding-ownership/no-listing-02-string-scope/src/main.rs +++ b/listings/ch04-understanding-ownership/no-listing-02-string-scope/src/main.rs @@ -1,10 +1,10 @@ fn main() { // ANCHOR: here - { - let s = String::from("hello"); // s is valid from this point forward + { + let s = String::from("hello"); // sはここから有効になる - // do stuff with s - } // this scope is now over, and s is no - // longer valid + // sで作業をする + } // このスコープはここでおしまい。sは + // もう有効ではない // ANCHOR_END: here } diff --git a/listings/ch04-understanding-ownership/no-listing-03-string-move/Cargo.toml b/listings/ch04-understanding-ownership/no-listing-03-string-move/Cargo.toml index 686de938f..e8847526d 100644 --- a/listings/ch04-understanding-ownership/no-listing-03-string-move/Cargo.toml +++ b/listings/ch04-understanding-ownership/no-listing-03-string-move/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "ownership" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch04-understanding-ownership/no-listing-04-cant-use-after-move/Cargo.toml b/listings/ch04-understanding-ownership/no-listing-04-cant-use-after-move/Cargo.toml index 686de938f..e8847526d 100644 --- a/listings/ch04-understanding-ownership/no-listing-04-cant-use-after-move/Cargo.toml +++ b/listings/ch04-understanding-ownership/no-listing-04-cant-use-after-move/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "ownership" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch04-understanding-ownership/no-listing-04-cant-use-after-move/output.txt b/listings/ch04-understanding-ownership/no-listing-04-cant-use-after-move/output.txt index 910332ac1..793b6a6e9 100644 --- a/listings/ch04-understanding-ownership/no-listing-04-cant-use-after-move/output.txt +++ b/listings/ch04-understanding-ownership/no-listing-04-cant-use-after-move/output.txt @@ -1,19 +1,25 @@ $ cargo run Compiling ownership v0.1.0 (file:///projects/ownership) error[E0382]: borrow of moved value: `s1` + (ムーブされた値の借用: `s1`) --> src/main.rs:5:28 | 2 | let s1 = String::from("hello"); - | -- move occurs because `s1` has type `std::string::String`, which does not implement the `Copy` trait + | -- move occurs because `s1` has type `String`, which does not implement the `Copy` trait + | (`s1`は`String`型を持ち、これは`Copy`トレイトを実装していないので、ムーブが発生します) 3 | let s2 = s1; | -- value moved here -4 | + | (ここで値がムーブされました) +4 | 5 | println!("{}, world!", s1); | ^^ value borrowed here after move - -error: aborting due to previous error + | (ムーブ後にここで借用されています) + | + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider cloning the value if the performance cost is acceptable + | +3 | let s2 = s1.clone(); + | ++++++++ For more information about this error, try `rustc --explain E0382`. -error: could not compile `ownership`. - -To learn more, run the command again with --verbose. +error: could not compile `ownership` (bin "ownership") due to 1 previous error diff --git a/listings/ch04-understanding-ownership/no-listing-05-clone/Cargo.toml b/listings/ch04-understanding-ownership/no-listing-05-clone/Cargo.toml index 686de938f..e8847526d 100644 --- a/listings/ch04-understanding-ownership/no-listing-05-clone/Cargo.toml +++ b/listings/ch04-understanding-ownership/no-listing-05-clone/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "ownership" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch04-understanding-ownership/no-listing-06-copy/Cargo.toml b/listings/ch04-understanding-ownership/no-listing-06-copy/Cargo.toml index 686de938f..e8847526d 100644 --- a/listings/ch04-understanding-ownership/no-listing-06-copy/Cargo.toml +++ b/listings/ch04-understanding-ownership/no-listing-06-copy/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "ownership" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch04-understanding-ownership/no-listing-07-reference/Cargo.toml b/listings/ch04-understanding-ownership/no-listing-07-reference/Cargo.toml index 686de938f..e8847526d 100644 --- a/listings/ch04-understanding-ownership/no-listing-07-reference/Cargo.toml +++ b/listings/ch04-understanding-ownership/no-listing-07-reference/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "ownership" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch04-understanding-ownership/no-listing-07-reference/src/main.rs b/listings/ch04-understanding-ownership/no-listing-07-reference/src/main.rs index fd32a5fc9..34ca14ed5 100644 --- a/listings/ch04-understanding-ownership/no-listing-07-reference/src/main.rs +++ b/listings/ch04-understanding-ownership/no-listing-07-reference/src/main.rs @@ -6,6 +6,7 @@ fn main() { let len = calculate_length(&s1); // ANCHOR_END: here + // '{}'の長さは、{}です println!("The length of '{}' is {}.", s1, len); } diff --git a/listings/ch04-understanding-ownership/no-listing-08-reference-with-annotations/Cargo.toml b/listings/ch04-understanding-ownership/no-listing-08-reference-with-annotations/Cargo.toml index 686de938f..e8847526d 100644 --- a/listings/ch04-understanding-ownership/no-listing-08-reference-with-annotations/Cargo.toml +++ b/listings/ch04-understanding-ownership/no-listing-08-reference-with-annotations/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "ownership" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch04-understanding-ownership/no-listing-08-reference-with-annotations/src/main.rs b/listings/ch04-understanding-ownership/no-listing-08-reference-with-annotations/src/main.rs index 6e40b8c30..73704d016 100644 --- a/listings/ch04-understanding-ownership/no-listing-08-reference-with-annotations/src/main.rs +++ b/listings/ch04-understanding-ownership/no-listing-08-reference-with-annotations/src/main.rs @@ -7,8 +7,8 @@ fn main() { } // ANCHOR: here -fn calculate_length(s: &String) -> usize { // s is a reference to a String +fn calculate_length(s: &String) -> usize { // sはStringへの参照 s.len() -} // Here, s goes out of scope. But because it does not have ownership of what - // it refers to, nothing happens. +} // ここで、sはスコープ外になる。けど、参照しているものの所有権を持っているわけではないので + // 何も起こらない // ANCHOR_END: here diff --git a/listings/ch04-understanding-ownership/no-listing-09-fixes-listing-04-06/Cargo.toml b/listings/ch04-understanding-ownership/no-listing-09-fixes-listing-04-06/Cargo.toml index 686de938f..e8847526d 100644 --- a/listings/ch04-understanding-ownership/no-listing-09-fixes-listing-04-06/Cargo.toml +++ b/listings/ch04-understanding-ownership/no-listing-09-fixes-listing-04-06/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "ownership" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch04-understanding-ownership/no-listing-10-multiple-mut-not-allowed/Cargo.toml b/listings/ch04-understanding-ownership/no-listing-10-multiple-mut-not-allowed/Cargo.toml index 686de938f..e8847526d 100644 --- a/listings/ch04-understanding-ownership/no-listing-10-multiple-mut-not-allowed/Cargo.toml +++ b/listings/ch04-understanding-ownership/no-listing-10-multiple-mut-not-allowed/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "ownership" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch04-understanding-ownership/no-listing-10-multiple-mut-not-allowed/output.txt b/listings/ch04-understanding-ownership/no-listing-10-multiple-mut-not-allowed/output.txt index cb69a714b..ae47fb288 100644 --- a/listings/ch04-understanding-ownership/no-listing-10-multiple-mut-not-allowed/output.txt +++ b/listings/ch04-understanding-ownership/no-listing-10-multiple-mut-not-allowed/output.txt @@ -1,19 +1,19 @@ $ cargo run Compiling ownership v0.1.0 (file:///projects/ownership) error[E0499]: cannot borrow `s` as mutable more than once at a time + (一度に`s`を可変として2回以上借用することはできません) --> src/main.rs:5:14 | 4 | let r1 = &mut s; | ------ first mutable borrow occurs here + | (最初の可変借用はここで発生しています) 5 | let r2 = &mut s; | ^^^^^^ second mutable borrow occurs here -6 | + | (2つ目の可変借用はここで発生しています) +6 | 7 | println!("{}, {}", r1, r2); | -- first borrow later used here - -error: aborting due to previous error + | (最初の参照はここで後で使用されています) For more information about this error, try `rustc --explain E0499`. -error: could not compile `ownership`. - -To learn more, run the command again with --verbose. +error: could not compile `ownership` (bin "ownership") due to 1 previous error diff --git a/listings/ch04-understanding-ownership/no-listing-11-muts-in-separate-scopes/Cargo.toml b/listings/ch04-understanding-ownership/no-listing-11-muts-in-separate-scopes/Cargo.toml index 686de938f..e8847526d 100644 --- a/listings/ch04-understanding-ownership/no-listing-11-muts-in-separate-scopes/Cargo.toml +++ b/listings/ch04-understanding-ownership/no-listing-11-muts-in-separate-scopes/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "ownership" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch04-understanding-ownership/no-listing-11-muts-in-separate-scopes/src/main.rs b/listings/ch04-understanding-ownership/no-listing-11-muts-in-separate-scopes/src/main.rs index 4b1a5a383..f8b382574 100644 --- a/listings/ch04-understanding-ownership/no-listing-11-muts-in-separate-scopes/src/main.rs +++ b/listings/ch04-understanding-ownership/no-listing-11-muts-in-separate-scopes/src/main.rs @@ -4,7 +4,7 @@ fn main() { { let r1 = &mut s; - } // r1 goes out of scope here, so we can make a new reference with no problems. + } // r1はここでスコープを抜けるので、問題なく新しい参照を作ることができる。 let r2 = &mut s; // ANCHOR_END: here diff --git a/listings/ch04-understanding-ownership/no-listing-12-immutable-and-mutable-not-allowed/Cargo.toml b/listings/ch04-understanding-ownership/no-listing-12-immutable-and-mutable-not-allowed/Cargo.toml index 686de938f..e8847526d 100644 --- a/listings/ch04-understanding-ownership/no-listing-12-immutable-and-mutable-not-allowed/Cargo.toml +++ b/listings/ch04-understanding-ownership/no-listing-12-immutable-and-mutable-not-allowed/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "ownership" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch04-understanding-ownership/no-listing-12-immutable-and-mutable-not-allowed/output.txt b/listings/ch04-understanding-ownership/no-listing-12-immutable-and-mutable-not-allowed/output.txt index cd4168f8c..af9520170 100644 --- a/listings/ch04-understanding-ownership/no-listing-12-immutable-and-mutable-not-allowed/output.txt +++ b/listings/ch04-understanding-ownership/no-listing-12-immutable-and-mutable-not-allowed/output.txt @@ -1,20 +1,20 @@ $ cargo run Compiling ownership v0.1.0 (file:///projects/ownership) error[E0502]: cannot borrow `s` as mutable because it is also borrowed as immutable + (`s`は不変で借用されているので、可変で借用できません) --> src/main.rs:6:14 | -4 | let r1 = &s; // no problem +4 | let r1 = &s; // 問題なし | -- immutable borrow occurs here -5 | let r2 = &s; // no problem -6 | let r3 = &mut s; // BIG PROBLEM + | (不変借用はここで発生しています) +5 | let r2 = &s; // 問題なし +6 | let r3 = &mut s; // 大問題! | ^^^^^^ mutable borrow occurs here -7 | + | (可変借用はここで発生しています) +7 | 8 | println!("{}, {}, and {}", r1, r2, r3); | -- immutable borrow later used here - -error: aborting due to previous error + | (不変借用はその後ここで使われています) For more information about this error, try `rustc --explain E0502`. -error: could not compile `ownership`. - -To learn more, run the command again with --verbose. +error: could not compile `ownership` (bin "ownership") due to 1 previous error diff --git a/listings/ch04-understanding-ownership/no-listing-12-immutable-and-mutable-not-allowed/src/main.rs b/listings/ch04-understanding-ownership/no-listing-12-immutable-and-mutable-not-allowed/src/main.rs index 0da04c010..4d145502d 100644 --- a/listings/ch04-understanding-ownership/no-listing-12-immutable-and-mutable-not-allowed/src/main.rs +++ b/listings/ch04-understanding-ownership/no-listing-12-immutable-and-mutable-not-allowed/src/main.rs @@ -2,9 +2,9 @@ fn main() { // ANCHOR: here let mut s = String::from("hello"); - let r1 = &s; // no problem - let r2 = &s; // no problem - let r3 = &mut s; // BIG PROBLEM + let r1 = &s; // 問題なし + let r2 = &s; // 問題なし + let r3 = &mut s; // 大問題! println!("{}, {}, and {}", r1, r2, r3); // ANCHOR_END: here diff --git a/listings/ch04-understanding-ownership/no-listing-13-reference-scope-ends/Cargo.toml b/listings/ch04-understanding-ownership/no-listing-13-reference-scope-ends/Cargo.toml index 686de938f..e8847526d 100644 --- a/listings/ch04-understanding-ownership/no-listing-13-reference-scope-ends/Cargo.toml +++ b/listings/ch04-understanding-ownership/no-listing-13-reference-scope-ends/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "ownership" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch04-understanding-ownership/no-listing-13-reference-scope-ends/src/main.rs b/listings/ch04-understanding-ownership/no-listing-13-reference-scope-ends/src/main.rs index 3b0a7da65..751a87472 100644 --- a/listings/ch04-understanding-ownership/no-listing-13-reference-scope-ends/src/main.rs +++ b/listings/ch04-understanding-ownership/no-listing-13-reference-scope-ends/src/main.rs @@ -2,12 +2,12 @@ fn main() { // ANCHOR: here let mut s = String::from("hello"); - let r1 = &s; // no problem - let r2 = &s; // no problem + let r1 = &s; // 問題なし + let r2 = &s; // 問題なし println!("{} and {}", r1, r2); - // r1 and r2 are no longer used after this point + // r1とr2はもうこれ以降使用されません - let r3 = &mut s; // no problem + let r3 = &mut s; // 問題なし println!("{}", r3); // ANCHOR_END: here } diff --git a/listings/ch04-understanding-ownership/no-listing-14-dangling-reference/Cargo.toml b/listings/ch04-understanding-ownership/no-listing-14-dangling-reference/Cargo.toml index 686de938f..e8847526d 100644 --- a/listings/ch04-understanding-ownership/no-listing-14-dangling-reference/Cargo.toml +++ b/listings/ch04-understanding-ownership/no-listing-14-dangling-reference/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "ownership" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch04-understanding-ownership/no-listing-14-dangling-reference/output.txt b/listings/ch04-understanding-ownership/no-listing-14-dangling-reference/output.txt index 6381d2a30..c049f9e0e 100644 --- a/listings/ch04-understanding-ownership/no-listing-14-dangling-reference/output.txt +++ b/listings/ch04-understanding-ownership/no-listing-14-dangling-reference/output.txt @@ -1,16 +1,26 @@ $ cargo run Compiling ownership v0.1.0 (file:///projects/ownership) error[E0106]: missing lifetime specifier +(エラー: ライフタイム指定子がありません) --> src/main.rs:5:16 | 5 | fn dangle() -> &String { - | ^ help: consider giving it a 'static lifetime: `&'static` + | ^ expected named lifetime parameter + | (名前付きのライフタイムパラメータが期待されていました) | = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from - -error: aborting due to previous error + = (助言: この関数の戻り値型は、借用した値を含んでいますが、借用される値がどこにもありません) +help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static` +(助言: `'static`ライフタイムを使うことを検討してください、ただし`const`または`static`から借用した値を返すのでない限り、これはあまり使われません) + | +5 | fn dangle() -> &'static String { + | +++++++ +help: instead, you are more likely to want to return an owned value +(助言: または、所有権を持つ値を返す方がいいかもしれません) + | +5 - fn dangle() -> &String { +5 + fn dangle() -> String { + | For more information about this error, try `rustc --explain E0106`. -error: could not compile `ownership`. - -To learn more, run the command again with --verbose. +error: could not compile `ownership` (bin "ownership") due to 1 previous error diff --git a/listings/ch04-understanding-ownership/no-listing-15-dangling-reference-annotated/Cargo.toml b/listings/ch04-understanding-ownership/no-listing-15-dangling-reference-annotated/Cargo.toml index 686de938f..e8847526d 100644 --- a/listings/ch04-understanding-ownership/no-listing-15-dangling-reference-annotated/Cargo.toml +++ b/listings/ch04-understanding-ownership/no-listing-15-dangling-reference-annotated/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "ownership" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch04-understanding-ownership/no-listing-15-dangling-reference-annotated/src/main.rs b/listings/ch04-understanding-ownership/no-listing-15-dangling-reference-annotated/src/main.rs index 9fbb372a0..7cd451070 100644 --- a/listings/ch04-understanding-ownership/no-listing-15-dangling-reference-annotated/src/main.rs +++ b/listings/ch04-understanding-ownership/no-listing-15-dangling-reference-annotated/src/main.rs @@ -3,11 +3,11 @@ fn main() { } // ANCHOR: here -fn dangle() -> &String { // dangle returns a reference to a String +fn dangle() -> &String { // dangleはStringへの参照を返す - let s = String::from("hello"); // s is a new String + let s = String::from("hello"); // sは新しいString - &s // we return a reference to the String, s -} // Here, s goes out of scope, and is dropped. Its memory goes away. - // Danger! + &s // String sへの参照を返す +} // ここで、sはスコープを抜け、ドロップされる。そのメモリは消される。 + // 危険だ // ANCHOR_END: here diff --git a/listings/ch04-understanding-ownership/no-listing-16-no-dangle/Cargo.toml b/listings/ch04-understanding-ownership/no-listing-16-no-dangle/Cargo.toml index 686de938f..e8847526d 100644 --- a/listings/ch04-understanding-ownership/no-listing-16-no-dangle/Cargo.toml +++ b/listings/ch04-understanding-ownership/no-listing-16-no-dangle/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "ownership" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch04-understanding-ownership/no-listing-17-slice/Cargo.toml b/listings/ch04-understanding-ownership/no-listing-17-slice/Cargo.toml index 686de938f..e8847526d 100644 --- a/listings/ch04-understanding-ownership/no-listing-17-slice/Cargo.toml +++ b/listings/ch04-understanding-ownership/no-listing-17-slice/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "ownership" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch04-understanding-ownership/no-listing-18-first-word-slice/Cargo.toml b/listings/ch04-understanding-ownership/no-listing-18-first-word-slice/Cargo.toml index 686de938f..e8847526d 100644 --- a/listings/ch04-understanding-ownership/no-listing-18-first-word-slice/Cargo.toml +++ b/listings/ch04-understanding-ownership/no-listing-18-first-word-slice/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "ownership" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch04-understanding-ownership/no-listing-19-slice-error/Cargo.toml b/listings/ch04-understanding-ownership/no-listing-19-slice-error/Cargo.toml index 686de938f..e8847526d 100644 --- a/listings/ch04-understanding-ownership/no-listing-19-slice-error/Cargo.toml +++ b/listings/ch04-understanding-ownership/no-listing-19-slice-error/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "ownership" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch04-understanding-ownership/no-listing-19-slice-error/output.txt b/listings/ch04-understanding-ownership/no-listing-19-slice-error/output.txt index a1d9caf11..26341bfc5 100644 --- a/listings/ch04-understanding-ownership/no-listing-19-slice-error/output.txt +++ b/listings/ch04-understanding-ownership/no-listing-19-slice-error/output.txt @@ -7,18 +7,14 @@ error[E0502]: cannot borrow `s` as mutable because it is also borrowed as immuta 16 | let word = first_word(&s); | -- immutable borrow occurs here | (不変借用はここで発生しています) -17 | +17 | 18 | s.clear(); // error! | ^^^^^^^^^ mutable borrow occurs here | (可変借用はここで発生しています) -19 | +19 | 20 | println!("the first word is: {}", word); | ---- immutable borrow later used here (不変借用はその後ここで使われています) -error: aborting due to previous error - For more information about this error, try `rustc --explain E0502`. -error: could not compile `ownership`. - -To learn more, run the command again with --verbose. +error: could not compile `ownership` (bin "ownership") due to 1 previous error diff --git a/src/ch04-00-understanding-ownership.md b/src/ch04-00-understanding-ownership.md index 220d4a1b1..a3bf3029e 100644 --- a/src/ch04-00-understanding-ownership.md +++ b/src/ch04-00-understanding-ownership.md @@ -5,13 +5,14 @@ # 所有権を理解する -所有権はRustの最もユニークな機能であり、これのおかげでガベージコレクタなしで安全性担保を行うことができるのです。 -故に、Rustにおいて、所有権がどう動作するのかを理解するのは重要です。この章では、所有権以外にも、関連する機能を +所有権はRustの最もユニークな機能であり、それ以外の言語機能と深く関連しています。 +所有権のおかげで、Rustはガベージコレクタの必要なしにメモリ安全性を担保することができていて、 +そのため所有権の仕組みを理解しておくことが重要です。この章では、所有権以外にも、関連する機能を いくつか話していきます: 借用、スライス、そして、コンパイラがデータをメモリにどう配置するかです。 diff --git a/src/ch04-01-what-is-ownership.md b/src/ch04-01-what-is-ownership.md index 2733433d8..9ee58b4ff 100644 --- a/src/ch04-01-what-is-ownership.md +++ b/src/ch04-01-what-is-ownership.md @@ -5,38 +5,38 @@ ## 所有権とは? -Rustの中心的な機能は、*所有権*です。この機能は、説明するのは簡単なのですが、言語の残りの機能全てにかかるほど -深い裏の意味を含んでいるのです。 +*所有権*とは、Rustプログラムがメモリをどのように管理するかを支配している、規則の集合です。 全てのプログラムは、実行中にコンピュータのメモリの使用方法を管理する必要があります。プログラムが動作するにつれて、 定期的に使用されていないメモリを検索するガベージコレクションを持つ言語もありますが、他の言語では、 プログラマが明示的にメモリを確保したり、解放したりしなければなりません。Rustでは第3の選択肢を取っています: -メモリは、コンパイラがコンパイル時にチェックする一定の規則とともに所有権システムを通じて管理されています。 -どの所有権機能も、実行中にプログラムの動作を遅くすることはありません。 +メモリは、コンパイラがチェックする一定の規則とともに所有権システムを通じて管理されています。 +規則のうちどれかひとつにでも違反すれば、プログラムはコンパイルできないでしょう。 +どの所有権機能も、実行中にプログラムの動作を遅くすることはないでしょう。 所有権は多くのプログラマにとって新しい概念なので、慣れるまでに時間がかかります。 -嬉しいことに、Rustと、所有権システムの規則の経験を積むと、より自然に安全かつ効率的なコードを構築できるようになります。 +嬉しいことに、Rustと、所有権システムの規則の経験を積んでいくにつれて、 +自然に安全かつ効率的なコードを構築するのはだんだん簡単だと思えるようになるでしょう。 その調子でいきましょう! - - - - - - - - - - - - - - - - - > ### スタックとヒープ > > 多くのプログラミング言語において、スタックとヒープについて考える機会はそう多くないでしょう。 > しかし、Rustのようなシステムプログラミング言語においては、値がスタックに積まれるかヒープに置かれるかは、 -> 言語の振る舞い方や、特定の決断を下す理由などに影響以上のものを与えるのです。 +> 言語の振る舞いや、特定の決断を下す理由などに影響を与えるのです。 > この章の後半でスタックとヒープを交えて所有権の一部が解説されるので、ここでちょっと予行演習をしておきましょう。 > > スタックもヒープも、実行時にコードが使用できるメモリの一部になりますが、異なる手段で構成されています。 @@ -147,23 +130,24 @@ PROD: START BOX > 途中や一番下に追加したり、取り除いたりすることもできません。データを追加することは、 > *スタックにpushする*といい、データを取り除くことは、*スタックからpopする*と表現します(`訳注`: > 日本語では単純に英語をそのまま活用してプッシュ、ポップと表現するでしょう)。 +> スタック上のデータは全て既知の固定サイズでなければなりません。 +> コンパイル時にサイズがわからなかったり、サイズが可変のデータについては、代わりにヒープに格納しなければなりません。 > -> データへのアクセス方法のおかげで、スタックは高速です: 新しいデータを置いたり、 -> データを取得する場所を探す必要が絶対にないわけです。というのも、その場所は常に一番上だからですね。 -> スタックを高速にする特性は他にもあり、それはスタック上のデータは全て既知の固定サイズでなければならないということです。 -> -> コンパイル時にサイズがわからなかったり、サイズが可変のデータについては、代わりにヒープに格納することができます。 > ヒープは、もっとごちゃごちゃしています: ヒープにデータを置く時、あるサイズのスペースを求めます。 -> OSはヒープ上に十分な大きさの空の領域を見つけ、使用中にし、*ポインタ*を返します。ポインタとは、その場所へのアドレスです。 -> この過程は、*ヒープに領域を確保する(allocating on the heap)*と呼ばれ、時としてそのフレーズを単に*allocateする*などと省略したりします。 +> メモリアロケータはヒープ上に十分な大きさの空の領域を見つけ、使用中にし、*ポインタ*を返します。ポインタとは、その場所へのアドレスです。 +> この過程は、*ヒープに領域を確保する (allocating on the heap)* と呼ばれ、時としてそのフレーズを単に*allocateする*などと省略したりします > (`訳注`: こちらもこなれた日本語訳はないでしょう。allocateは「メモリを確保する」と訳したいところですが) -> スタックに値を積むことは、メモリ確保とは考えられません。ポインタは、既知の固定サイズなので、 +> (スタックに値を積むことは、メモリ確保とは考えられません)。ヒープへのポインタは、既知の固定サイズなので、 > スタックに保管することができますが、実データが必要になったら、ポインタを追いかける必要があります。 -> > レストランで席を確保することを考えましょう。入店したら、グループの人数を告げ、 > 店員が全員座れる空いている席を探し、そこまで誘導します。もしグループの誰かが遅れて来るのなら、 > 着いた席の場所を尋ねてあなたを発見することができます。 > +> スタックにデータを積むほうが、ヒープ上にメモリを確保するより高速です。 +> アロケータが新しいデータを置くための場所を探さなくていいからです。というのも、その場所は常にスタックの一番上だからですね。 +> それと比べて、ヒープ上にメモリを確保するのはより手間の多い仕事です。 +> アロケータはまずデータを入れるのに充分な大きさの場所を探して、そして次のメモリ確保に備えて予約をしないといけないからです。 +> > ヒープへのデータアクセスは、スタックのデータへのアクセスよりも低速です。 > ポインタを追って目的の場所に到達しなければならないからです。現代のプロセッサは、メモリをあちこち行き来しなければ、 > より速くなります。似た例えを続けましょう。レストランで多くのテーブルから注文を受ける給仕人を考えましょう。最も効率的なのは、 @@ -171,7 +155,7 @@ PROD: START BOX > それからテーブルBの注文、さらにまたA、それからまたBと渡り歩くのは、かなり低速な過程になってしまうでしょう。 > 同じ意味で、プロセッサは、 > データが隔離されている(ヒープではそうなっている可能性がある)よりも近くにある(スタックではこうなる)ほうが、 -> 仕事をうまくこなせるのです。ヒープに大きな領域を確保する行為も時間がかかることがあります。 +> 仕事をうまくこなせるのです。 > > コードが関数を呼び出すと、関数に渡された値(ヒープのデータへのポインタも含まれる可能性あり)と、 > 関数のローカル変数がスタックに載ります。関数の実行が終了すると、それらの値はスタックから取り除かれます。 @@ -179,12 +163,8 @@ PROD: START BOX > どの部分のコードがどのヒープ上のデータを使用しているか把握すること、ヒープ上の重複するデータを最小化すること、 > メモリ不足にならないようにヒープ上の未使用のデータを掃除することは全て、所有権が解決する問題です。 > 一度所有権を理解したら、あまり頻繁にスタックとヒープに関して考える必要はなくなるでしょうが、 -> ヒープデータを管理することが所有権の存在する理由だと知っていると、所有権がありのままで動作する理由を -> 説明するのに役立つこともあります。 +> 所有権の主な目的はヒープデータを管理することだと知っていると、所有権がどうしてこうなっているのか説明するのに役立つこともあります。 > - -まず、所有権のルールについて見ていきましょう。 -この規則を具体化する例を扱っていく間もこれらのルールを肝に銘じておいてください: +まず、所有権の規則について見ていきましょう。 +この規則を具体化する例を扱っていく間もこれらの規則を肝に銘じておいてください: -* Rustの各値は、*所有者*と呼ばれる変数と対応している。 +* Rustの各値には、*所有者*が存在する。 * いかなる時も所有者は一つである。 * 所有者がスコープから外れたら、値は破棄される。 @@ -217,27 +197,25 @@ work through the examples that illustrate them: ### 変数スコープ -第2章で、Rustプログラムの例はすでに見ています。もう基本的な記法は通り過ぎたので、 -`fn main() {`というコードはもう例に含みません。従って、例をなぞっているなら、 -これからの例は`main`関数に手動で入れ込まなければいけなくなるでしょう。結果的に、例は少々簡潔になり、 -定型コードよりも具体的な詳細に集中しやすくなります。 +もう基本的なRustの文法は通り過ぎたので、`fn main() {`というコードはもう例に含みません。 +従って、例をなぞっているなら、これからの例は`main`関数に手動で入れ込むようにしてください。 +結果的に、例は少々簡潔になり、定型コードよりも具体的な詳細に集中しやすくなります。 所有権の最初の例として、何らかの変数の*スコープ*について見ていきましょう。スコープとは、 -要素が有効になるプログラム内の範囲のことです。以下のような変数があるとしましょう: +要素が有効になるプログラム内の範囲のことです。以下の変数を例に取ります: ```rust let s = "hello"; @@ -246,37 +224,23 @@ let s = "hello"; 変数`s`は、文字列リテラルを参照し、ここでは、文字列の値はプログラムのテキストとしてハードコードされています。 この変数は、宣言された地点から、現在の*スコープ*の終わりまで有効になります。リスト4-1には、 -変数`s`が有効な場所に関する注釈がコメントで付記されています。 +変数`s`が有効な場所に関する注釈がコメントで付記されたプログラムを示します。 - +{{#rustdoc_include ../listings/ch04-understanding-ownership/listing-04-01/src/main.rs:here}} +``` -```rust -{ // sは、ここでは有効ではない。まだ宣言されていない - let s = "hello"; // sは、ここから有効になる - - // sで作業をする -} // このスコープは終わり。もうsは有効ではない -``` - - - リスト4-1: 変数と有効なスコープ -* `s`が*スコープに入る*と、有効になる -* *スコープを抜ける*まで、有効なまま +* `s`がスコープに*入る*と、有効になる。 +* スコープを*抜ける*まで、有効なまま。 -ここで、スコープと変数が有効になる期間の関係は、他の言語に類似しています。さて、この理解のもとに、 +今のところ、スコープと、変数が有効である期間の関係は、他の言語のそれに類似しています。さて、この理解のもとに、 `String`型を導入して構築していきましょう。 - -所有権の規則を具体化するには、第3章の「データ型」節で講義したものよりも、より複雑なデータ型が必要になります。 -以前講義した型は全てスタックに保管され、スコープが終わるとスタックから取り除かれますが、 -ヒープに確保されるデータ型を観察して、 +than those we covered in the [“Data Types”][data-types] section +of Chapter 3. The types covered previously are of a known size, can be stored +on the stack and popped off the stack when their scope is over, and can be +quickly and trivially copied to make a new, independent instance if another +part of code needs to use the same value in a different scope. But we want to +look at data that is stored on the heap and explore how Rust knows when to +clean up that data, and the `String` type is a great example. +--> + +所有権の規則を具体化するには、第3章の[「データ型」][data-types]節で講義したものよりも、より複雑なデータ型が必要になります。 +以前講義した型は、既知のサイズを持ち、スタックに置いておいてスコープが終わるとスタックから取り除かれるという扱いが可能でした。 +さらに、コードの別の場所で同じ値を異なるスコープを持たせて使う必要があるなら、 +新しい、独立したインスタンスに、高速に、そして自明にコピーすることができました。 +が、ヒープに確保されるデータ型を観察して、 コンパイラがどうそのデータを掃除すべきタイミングを把握しているかを掘り下げていきたいと思います。 +`String`型はその好例です。 -ここでは、例として`String`型を使用し、`String`型の所有権にまつわる部分に着目しましょう。 -また、この観点は、標準ライブラリや自分で生成する他の複雑なデータ型にも適用されます。 -`String`型については、第8章でより深く議論します。 +`String`型の所有権にまつわる部分に着目しましょう。 +またこの観点は、標準ライブラリから提供されたか自分で作成したかを問わず、他の複雑なデータ型にも適用されます。 +`String`型については、[第8章][ch8]でより深く議論します。 既に文字列リテラルは見かけましたね。文字列リテラルでは、文字列の値はプログラムにハードコードされます。 @@ -357,51 +327,35 @@ let s = String::from("hello"); ``` -この二重コロンは、`string_from`などの名前を使うのではなく、 -`String`型直下の`from`関数を特定する働きをする演算子です。この記法について詳しくは、 -第5章の「メソッド記法」節と、第7章の「モジュール定義」でモジュールを使った名前空間分けについて話をするときに議論します。 +この二重コロン`::`演算子は、`string_from`などの名前を使うのではなく、 +`String`型直下の`from`関数を特定する働きをします。この記法について詳しくは、 +第5章の[「メソッド記法」][method-syntax]節と、第7章の[「モジュールツリーの要素を示すためのパス」][paths-module-tree]でモジュールを使った名前空間分けについて話をするときに議論します。 -この種の文字列は、可変化することが*できます*: +この種の文字列は、変更することが*できます*: - - - - - -```rust -let mut s = String::from("hello"); - -s.push_str(", world!"); // push_str()関数は、リテラルをStringに付け加える - -println!("{}", s); // これは`hello, world!`と出力する -``` -では、ここでの違いは何でしょうか?なぜ、`String`型は可変化できるのに、リテラルはできないのでしょうか? +では、ここでの違いは何でしょうか?なぜ、`String`型は変更できるのに、リテラルはできないのでしょうか? 違いは、これら二つの型がメモリを扱う方法にあります。 @@ -434,13 +388,13 @@ to hold the contents. This means: ヒープに確保して内容を保持します。つまり: -* メモリは、実行時にOSに要求される。 -* `String`型を使用し終わったら、OSにこのメモリを返還する方法が必要である。 +* メモリは、実行時にメモリアロケータに要求される。 +* `String`型を使用し終わったら、アロケータにこのメモリを返還する方法が必要である。 - - - ```rust -{ - let s = String::from("hello"); // sはここから有効になる - - // sで作業をする -} // このスコープはここでおしまい。sは - // もう有効ではない +{{#rustdoc_include ../listings/ch04-understanding-ownership/no-listing-02-string-scope/src/main.rs:here}} ``` -`String`型が必要とするメモリをOSに返還することが自然な地点があります: `s`変数がスコープを抜ける時です。 -変数がスコープを抜ける時、Rustは特別な関数を呼んでくれます。この関数は、`drop`と呼ばれ、 +`String`型が必要とするメモリをアロケータに返還することが自然な地点があります: `s`変数がスコープを抜ける時です。 +変数がスコープを抜ける時、Rustは特別な関数を呼んでくれます。この関数は、[`drop`][drop]と呼ばれ、 ここに`String`型の書き手はメモリを返還するコードを配置することができます。Rustは、閉じ波括弧で自動的に`drop`関数を呼び出します。 > 注釈: C++では、要素の生存期間の終了地点でリソースを解放するこのパターンを時に、 @@ -540,11 +478,16 @@ we’ve allocated on the heap. Let’s explore some of those situations now. ヒープ上に確保されたデータを複数の変数に使用させるようなもっと複雑な場面では、コードの振る舞いは、 予期しないものになる可能性もあります。これから、そのような場面を掘り下げてみましょう。 + + + -#### 変数とデータの相互作用法: ムーブ +#### ムーブによる変数とデータの相互作用 + リスト4-2: 変数`x`の整数値を`y`に代入する @@ -584,17 +528,16 @@ Now let’s look at the `String` version: では、`String`バージョンを見ていきましょう: ```rust -let s1 = String::from("hello"); -let s2 = s1; +{{#rustdoc_include ../listings/ch04-understanding-ownership/no-listing-03-string-move/src/main.rs:here}} ``` -このコードは先ほどのコードに酷似していますので、動作方法も同じだと思い込んでしまうかもしれません: +このコードは酷似していますので、動作方法も同じだと思い込んでしまうかもしれません: 要するに、2行目で`s1`の値をコピーし、`s2`に束縛するということです。ところが、 これは全く起こることを言い当てていません。 @@ -612,26 +555,34 @@ heap that holds the contents. 右側には、中身を保持したヒープ上のメモリがあります。 -メモリ上の文字列 +2個の表: 1個目の表はスタック上のs1の表現を含み、表はs1の長さ(5)、許容量(5)、
+そして2個目の表の最初の値へのポインタからなる。2個目の表はヒープ上の文字列データのバイト単位の表現を含む。 - + 図4-1: `s1`に束縛された`"hello"`という値を保持する`String`のメモリ上の表現 長さは、`String`型の中身が現在使用しているメモリ量をバイトで表したものです。許容量は、 -`String`型がOSから受け取った全メモリ量をバイトで表したものです。長さと許容量の違いは問題になることですが、 +`String`型がアロケータから受け取った全メモリ量をバイトで表したものです。長さと許容量の違いは問題になることですが、 この文脈では違うので、とりあえずは、許容量を無視しても構わないでしょう。 -同じ値を指すs1とs2 +3個の表: 表s1とs2はスタック上の文字列s1とs2それぞれを表現し、どちらもヒープ上の同じ文字列データを指している。 - + 図4-2: `s1`のポインタ、長さ、許容量のコピーを保持する変数`s2`のメモリ上での表現 @@ -668,13 +624,18 @@ Rustが代わりにヒープデータもコピーするという選択をして ヒープ上のデータが大きい時に`s2 = s1`という処理の実行時性能がとても悪くなっていた可能性があるでしょう。 -2箇所へのs1とs2 +4個の表: 2個の表はs1とs2のスタックデータを表現し、それぞれがヒープ上の文字列データのコピーを指している。 - + 図4-3: Rustがヒープデータもコピーしていた場合に`s2 = s1`という処理が行なった可能性のあること @@ -696,27 +657,18 @@ corruption, which can potentially lead to security vulnerabilities. セキュリティ上の脆弱性を生む可能性があります。 - - -メモリ安全性を保証するために、Rustにおいてこの場面で起こることの詳細がもう一つあります。 -確保されたメモリをコピーしようとする代わりに、コンパイラは、`s1`が最早有効ではないと考え、 +メモリ安全性を保証するために、`let s2 = s1;`の行の後、コンパイラは`s1`が最早有効ではないとみなします。 故に`s1`がスコープを抜けた際に何も解放する必要がなくなるわけです。`s2`の生成後に`s1`を使用しようとしたら、 どうなるかを確認してみましょう。動かないでしょう: -```rust,ignore -let s1 = String::from("hello"); -let s2 = s1; - -println!("{}, world!", s1); +```rust,ignore,does_not_compile +{{#rustdoc_include ../listings/ch04-understanding-ownership/no-listing-04-cant-use-after-move/src/main.rs:here}} ``` src/main.rs:5:28 - | -3 | let s2 = s1; - | -- value moved here -4 | -5 | println!("{}, world!", s1); - | ^^ value used here after move - | (ムーブ後にここで使用されています) - | - = note: move occurs because `s1` has type `std::string::String`, which does - not implement the `Copy` trait - (注釈: ムーブが起きたのは、`s1`が`std::string::String`という - `Copy`トレイトを実装していない型だからです) +```console +{{#include ../listings/ch04-understanding-ownership/no-listing-04-cant-use-after-move/output.txt}} ``` -他の言語を触っている間に"shallow copy"と"deep copy"という用語を耳にしたことがあるなら、 -データのコピーなしにポインタと長さ、許容量をコピーするという概念は、shallow copyのように思えるかもしれません。 +他の言語を触っている間に*shallow copy*と*deep copy*という用語を耳にしたことがあるなら、 +データのコピーなしにポインタと長さ、許容量をコピーするという概念は、shallow copyすることのように思えるかもしれません。 ですが、コンパイラは最初の変数をも無効化するので、shallow copyと呼ばれる代わりに、 *ムーブ*として知られているわけです。この例では、`s1`は`s2`に*ムーブ*されたと表現するでしょう。 以上より、実際に起きることを図4-4に示してみました。 -s2にムーブされたs1 +3個の表: 表s1とs2はスタック上の文字列s1とs2それぞれを表現し、どちらもヒープ上の同じ文字列データを指している。
+s1はもう有効ではないので、表s1はグレー表示されている。
+s2だけがヒープデータにアクセスするために使用できる。 - + 図4-4: `s1`が無効化された後のメモリ表現 @@ -788,11 +734,16 @@ copying can be assumed to be inexpensive in terms of runtime performance. 自動的にデータの"deep copy"が行われることは絶対にないわけです。それ故に、あらゆる*自動*コピーは、実行時性能の観点で言うと、 悪くないと考えてよいことになります。 + -#### 変数とデータの相互作用法: クローン + + +#### クローンによる変数とデータの相互作用 まだ話題にしていない別の問題があります。 この整数を使用したコードは、一部をリスト4-2で示しましたが、うまく動作する有効なものです: ```rust -let x = 5; -let y = x; - -println!("x = {}, y = {}", x, y); +{{#rustdoc_include ../listings/ch04-understanding-ownership/no-listing-06-copy/src/main.rs:here}} ``` その理由は、整数のようなコンパイル時に既知のサイズを持つ型は、スタック上にすっぽり保持されるので、 @@ -881,41 +826,51 @@ differently from the usual shallow copying and we can leave it out. Rustには`Copy`トレイトと呼ばれる特別な注釈があり、 -整数のようなスタックに保持される型に対して配置することができます(トレイトについては第10章でもっと詳しく話します)。 -型が`Copy`トレイトに適合していれば、代入後も古い変数が使用可能になります。コンパイラは、 -型やその一部分でも`Drop`トレイトを実装している場合、`Copy`トレイトによる注釈をさせてくれません。 +整数のようなスタックに保持される型に対して配置することができます(トレイトについては[第10章][traits]でもっと詳しく話します)。 +型が`Copy`トレイトを実装していれば、その型を持つ変数はムーブされず、代わりに自明な方法でにコピーされます。 +そのため、他の変数に代入した後でも、元の変数は有効なままです。 + + + +コンパイラは、型やその一部分でも`Drop`トレイトを実装している場合、`Copy`による注釈をさせてくれません。 型の値がスコープを外れた時に何か特別なことを起こす必要がある場合に、`Copy`注釈を追加すると、コンパイルエラーが出ます。 -型に`Copy`注釈をつける方法について学ぶには、付録Cの「導出可能なトレイト」をご覧ください。 +型に`Copy`注釈をつけてトレイトを実装する方法について学ぶには、付録Cの[「導出可能なトレイト」][derivable-traits]をご覧ください。 -では、どの型が`Copy`なのでしょうか?ある型について、ドキュメントをチェックすればいいのですが、 -一般規則として、単純なスカラー値の集合は何でも`Copy`であり、メモリ確保が必要だったり、 -何らかの形態のリソースだったりするものは`Copy`ではありません。ここに`Copy`の型の一部を並べておきます。 +では、どの型が`Copy`トレイトを実装しているのでしょうか? +確実に知るためには、調べたい型のドキュメントをチェックすればいいのですが、 +一般規則として、単純なスカラー値の集合は何でも`Copy`を実装でき、メモリ確保が必要だったり、 +何らかの形態のリソースだったりするものは`Copy`を実装できません。ここに`Copy`を実装する型の一部を並べておきます。 * あらゆる整数型。`u32`など。 @@ -932,13 +887,13 @@ be sure, but as a general rule, any group of simple scalar values can be ### 所有権と関数 -意味論的に、関数に値を渡すことと、値を変数に代入することは似ています。関数に変数を渡すと、 +関数に値を渡すことと、値を変数に代入することの仕組みは似ています。関数に変数を渡すと、 代入のようにムーブやコピーされます。リスト4-3は変数がスコープに入ったり、 抜けたりする地点について注釈してある例です。 @@ -948,75 +903,15 @@ showing where variables go into and out of scope. ファイル名: src/main.rs - - - - - - - - - - - +{{#rustdoc_include ../listings/ch04-understanding-ownership/listing-04-03/src/main.rs}} +``` -```rust -fn main() { - let s = String::from("hello"); // sがスコープに入る - - takes_ownership(s); // sの値が関数にムーブされ... - // ... ここではもう有効ではない - - let x = 5; // xがスコープに入る - - makes_copy(x); // xも関数にムーブされるが、 - // i32はCopyなので、この後にxを使っても - // 大丈夫 - -} // ここでxがスコープを抜け、sもスコープを抜ける。ただし、sの値はムーブされているので、何も特別なことは起こらない。 - // - -fn takes_ownership(some_string: String) { // some_stringがスコープに入る。 - println!("{}", some_string); -} // ここでsome_stringがスコープを抜け、`drop`が呼ばれる。後ろ盾してたメモリが解放される。 - // - -fn makes_copy(some_integer: i32) { // some_integerがスコープに入る - println!("{}", some_integer); -} // ここでsome_integerがスコープを抜ける。何も特別なことはない。 -``` - - - リスト4-3: 所有権とスコープが注釈された関数群 -値を返すことでも、所有権は移動します。リスト4-4は、リスト4-3と似た注釈のついた例です。 +値を返すことでも、所有権は移動します。リスト4-4に値を返す関数の例を、リスト4-3と似た注釈を付けて示します。 - - - - - - - - - - - - - - - -```rust -fn main() { - let s1 = gives_ownership(); // gives_ownershipは、戻り値をs1に - // ムーブする - - let s2 = String::from("hello"); // s2がスコープに入る - - let s3 = takes_and_gives_back(s2); // s2はtakes_and_gives_backにムーブされ - // 戻り値もs3にムーブされる -} // ここで、s3はスコープを抜け、ドロップされる。s2もスコープを抜けるが、ムーブされているので、 - // 何も起きない。s1もスコープを抜け、ドロップされる。 - -fn gives_ownership() -> String { // gives_ownershipは、戻り値を - // 呼び出した関数にムーブする - - let some_string = String::from("hello"); // some_stringがスコープに入る - - some_string // some_stringが返され、呼び出し元関数に - // ムーブされる -} - -// takes_and_gives_backは、Stringを一つ受け取り、返す。 -fn takes_and_gives_back(a_string: String) -> String { // a_stringがスコープに入る。 - - a_string // a_stringが返され、呼び出し元関数にムーブされる -} +{{#rustdoc_include ../listings/ch04-understanding-ownership/listing-04-04/src/main.rs}} ``` +heap goes out of scope, the value will be cleaned up by `drop` unless ownership +of the data has been moved to another variable. 変数の所有権は、毎回同じパターンを辿っています: 別の変数に値を代入すると、ムーブされます。 -ヒープにデータを含む変数がスコープを抜けると、データが別の変数に所有されるようムーブされていない限り、 +ヒープにデータを含む変数がスコープを抜けると、データの所有権が別の変数にムーブされていない限り、 `drop`により片付けられるでしょう。 -所有権を取り、またその所有権を戻す、ということを全ての関数でしていたら、ちょっとめんどくさいですね。 +これでもいいのですが、所有権を取り、またその所有権を戻す、ということを全ての関数でしていたら、ちょっとめんどくさいですね。 関数に値は使わせるものの所有権を取らないようにさせるにはどうするべきでしょうか。 返したいと思うかもしれない関数本体で発生したあらゆるデータとともに、再利用したかったら、渡されたものをまた返さなきゃいけないのは、 非常に煩わしいことです。 -タプルで、複数の値を返すことは可能です。リスト4-5のようにですね。 +Rustでは、タプルを使って複数の値を返すことができます。リスト4-5のようにですね。 - - - - - - - - - ```rust -fn main() { - let s1 = String::from("hello"); - - let (s2, len) = calculate_length(s1); - - //'{}'の長さは、{}です - println!("The length of '{}' is {}.", s2, len); -} - -fn calculate_length(s: String) -> (String, usize) { - let length = s.len(); // len()メソッドは、Stringの長さを返します - - (s, length) -} +{{#rustdoc_include ../listings/ch04-understanding-ownership/listing-04-05/src/main.rs}} ``` でも、これでは、大袈裟すぎますし、ありふれているはずの概念に対して、作業量が多すぎます。 -私たちにとって幸運なことに、Rustにはこの概念に対する機能があり、*参照*と呼ばれます。 +私たちにとって幸運なことに、Rustには所有権を移動することなく値を使うための機能があり、*参照*と呼ばれます。 + + + +[data-types]: ch03-02-data-types.html#データ型 +[ch8]: ch08-02-strings.html +[traits]: ch10-02-traits.html +[derivable-traits]: appendix-03-derivable-traits.html +[method-syntax]: ch05-03-method-syntax.html#メソッド記法 +[paths-module-tree]: ch07-03-paths-for-referring-to-an-item-in-the-module-tree.html +[drop]: https://doc.rust-lang.org/std/ops/trait.Drop.html#tymethod.drop diff --git a/src/ch04-02-references-and-borrowing.md b/src/ch04-02-references-and-borrowing.md index ddd58b726..04fef7157 100644 --- a/src/ch04-02-references-and-borrowing.md +++ b/src/ch04-02-references-and-borrowing.md @@ -8,16 +8,23 @@ The issue with the tuple code in Listing 4-5 is that we have to return the `String` to the calling function so we can still use the `String` after the call to `calculate_length`, because the `String` was moved into -`calculate_length`. +`calculate_length`. Instead, we can provide a reference to the `String` value. +A *reference* is like a pointer in that it’s an address we can follow to access +the data stored at that address; that data is owned by some other variable. +Unlike a pointer, a reference is guaranteed to point to a valid value of a +particular type for the life of that reference. --> リスト4-5のタプルコードの問題は、`String`型を呼び出し元の関数に戻さないと、`calculate_length`を呼び出した後に、 `String`オブジェクトが使えなくなることであり、これは`String`オブジェクトが`calculate_length`にムーブされてしまうためでした。 +代わりに、`String`値への参照を渡すことができます。 +*参照*はアドレスであり、それを辿ってそのアドレスに置かれているデータにアクセスできるという点で、ポインタと似ています; +データは他の変数によって所有されています。 +ポインタと異なる点としては、参照はその生存期間中を通して、特定の型の有効な値を指していることが保証されています。 ここで、値の所有権をもらう代わりに引数としてオブジェクトへの参照を取る`calculate_length`関数を定義し、 @@ -30,43 +37,30 @@ value: ファイル名: src/main.rs ```rust -fn main() { - let s1 = String::from("hello"); - - let len = calculate_length(&s1); - - // '{}'の長さは、{}です - println!("The length of '{}' is {}.", s1, len); -} - -fn calculate_length(s: &String) -> usize { - s.len() -} +{{#rustdoc_include ../listings/ch04-understanding-ownership/no-listing-07-reference/src/main.rs:all}} ``` まず、変数宣言と関数の戻り値にあったタプルコードは全てなくなったことに気付いてください。 2番目に、`&s1`を`calcuate_length`に渡し、その定義では、`String`型ではなく、`&String`を受け取っていることに注目してください。 +これらのアンド記号が参照を表しており、これのおかげで所有権をもらうことなく値を参照することができるのです。 +図4-5にこの概念を描写します。 - -これらのアンド記号が参照であり、これのおかげで所有権をもらうことなく値を参照することができるのです。 -図4-5はその図解です。 - - -文字列s1を指す&String型のs +3個の表: sの表はs1の表へのポインタのみを含む。
+s1の表はs1のスタックデータを含み、ヒープ上の文字列データを指している。 > 注釈: `&`による参照の逆は、*参照外し*であり、参照外し演算子の`*`で達成できます。 @@ -92,22 +86,17 @@ Let’s take a closer look at the function call here: ここの関数呼び出しについて、もっと詳しく見てみましょう: ```rust -# fn calculate_length(s: &String) -> usize { -# s.len() -# } -let s1 = String::from("hello"); - -let len = calculate_length(&s1); +{{#rustdoc_include ../listings/ch04-understanding-ownership/no-listing-07-reference/src/main.rs:here}} ``` この`&s1`という記法により、`s1`の値を*参照する*参照を生成することができますが、これを所有することはありません。 -所有してないということは、指している値は、参照がスコープを抜けてもドロップされないということです。 +所有してないということは、指している値は、参照が使用されなくなってもドロップされないということです。 - ```rust -fn calculate_length(s: &String) -> usize { // sはStringへの参照 - s.len() -} // ここで、sはスコープ外になる。けど、参照しているものの所有権を持っているわけではないので - // 何も起こらない +{{#rustdoc_include ../listings/ch04-understanding-ownership/no-listing-08-reference-with-annotations/src/main.rs:here}} ``` -変数`s`が有効なスコープは、あらゆる関数の引数のものと同じですが、所有権はないので、`s`がスコープを抜けても、 -参照が指しているものをドロップすることはありません。関数が実際の値の代わりに参照を引数に取ると、 +変数`s`が有効なスコープは通常の関数の引数のものと同じですが、`s`はそれが指す値に対する所有権を持っていないので、 +`s`が使用されなくなっても指している値をドロップすることはありません。関数が実際の値の代わりに参照を引数に取ると、 所有権をもらわないので、所有権を返す目的で値を返す必要はありません。 -関数の引数に参照を取ることを*借用*と呼びます。現実生活のように、誰かが何かを所有していたら、 -それを借りることができます。用が済んだら、返さなきゃいけないわけです。 +参照を作成することを*借用*と呼びます。現実生活のように、誰かが何かを所有していたら、 +それを借りることができます。用が済んだら、返さないといけません。持っているのとは違うのです。 @@ -168,16 +146,8 @@ Listing 4-6. Spoiler alert: it doesn’t work! ファイル名: src/main.rs -```rust,ignore -fn main() { - let s = String::from("hello"); - - change(&s); -} - -fn change(some_string: &String) { - some_string.push_str(", world"); -} +```rust,ignore,does_not_compile +{{#rustdoc_include ../listings/ch04-understanding-ownership/listing-04-06/src/main.rs}} ``` error.rs:8:5 - | -7 | fn change(some_string: &String) { - | ------- use `&mut String` here to make mutable -8 | some_string.push_str(", world"); - | ^^^^^^^^^^^ cannot borrow as mutable +```console +{{#include ../listings/ch04-understanding-ownership/listing-04-06/output.txt}} ``` -### 可変な参照 +### 可変参照 -一捻り加えるだけでリスト4-6のコードのエラーは解決します: +借用された値を変更できるようにするには、代わりに*可変参照*を使うという一捻りを加えるだけでよく、 +これでリスト4-6のコードを修正できます: -始めに、`s`を`mut`に変えなければなりませんでした。そして、`&mut s`で可変な参照を生成し、 -`some_string: &mut String`で可変な参照を受け入れなければなりませんでした。 +まず`s`が`mut`となるように変更します。次に、`change`関数を呼ぶところで`&mut s`によって可変参照を作成し、 +さらに関数シグネチャを、`some_string: &mut String`で可変参照を受け入れるように更新します。 +これにより、`change`関数は借用する値を変更しようとすることがとても明確になります。 -ところが、可変な参照には大きな制約が一つあります: 特定のスコープで、ある特定のデータに対しては、 -一つしか可変な参照を持てないことです。こちらのコードは失敗します: +可変参照には大きな制約が一つあります: ある値への可変参照が存在するなら、その値への参照を他に作ることはできません。 +このコードは`s`への可変参照を2個作成しようとしていますが、これは失敗します: src/main.rs:5:14 - | -4 | let r1 = &mut s; - | ------ first mutable borrow occurs here - | (最初の可変な参照はここ) -5 | let r2 = &mut s; - | ^^^^^^ second mutable borrow occurs here - | (二つ目の可変な参照はここ) -6 | -7 | println!("{}, {}", r1, r2); - | -- first borrow later used here - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0499`. -error: could not compile `ownership` - -To learn more, run the command again with --verbose. +```console +{{#include ../listings/ch04-understanding-ownership/no-listing-10-multiple-mut-not-allowed/output.txt}} ``` -この制約は、可変化を許可するものの、それを非常に統制の取れた形で行えます。これは、新たなRustaceanにとっては、 -壁です。なぜなら、多くの言語では、いつでも好きな時に可変化できるからです。 +このエラーによると、一度に`s`を可変として2回以上借用することはできないので、このコードは不正だ、とのことです。 +最初の可変借用は`r1`にあり、`println!`で使用されるまで続かないといけませんが、この可変借用の作成から使用までの間に、 +`r1`と同じデータを借用する別の可変借用を`r2`に作成しようとしました。 +同じデータへの複数の可変参照が同時に存在することを禁止する、という制約は、可変化を許可するものの、 +それを非常に統制の取れた形で行えます。これは、新たなRustaceanにとっては、 +壁です。なぜなら、多くの言語では、いつでも好きな時に可変化できるからです。 この制約がある利点は、コンパイラがコンパイル時にデータ競合を防ぐことができる点です。 -データ競合とは、競合条件と類似していて、これら3つの振る舞いが起きる時に発生します: +データ競合とは、競合状態と類似していて、これら3つの振る舞いが起きる時に発生します: データ競合は未定義の振る舞いを引き起こし、実行時に追いかけようとした時に特定し解決するのが難しい問題です。 -しかし、Rustは、データ競合が起こるコードをコンパイルさえしないので、この問題が発生しないようにしてくれるわけです。 +しかし、Rustは、データ競合が起こるコードのコンパイルを拒否することで、この問題が発生しないようにしてくれるわけです。 +{{#rustdoc_include ../listings/ch04-understanding-ownership/no-listing-11-muts-in-separate-scopes/src/main.rs:here}} +``` - +コンパイラは可変と不変な参照を組み合わせることに関しても、似たような規則を強制します。このコードはエラーになります: - - -```rust -let mut s = String::from("hello"); -{ - let r1 = &mut s; + -} // r1はここでスコープを抜けるので、問題なく新しい参照を作ることができる +これがエラーです: -let r2 = &mut s; +```console +{{#include ../listings/ch04-understanding-ownership/no-listing-12-immutable-and-mutable-not-allowed/output.txt}} ``` -可変と不変な参照を組み合わせることに関しても、似たような規則が存在しています。このコードはエラーになります: +ふう!*さらに*不変な参照をしている間は、同じ値に対して可変な参照をすることはできません。 - - -```rust,ignore -let mut s = String::from("hello"); - -let r1 = &s; // 問題なし -let r2 = &s; // 問題なし -let r3 = &mut s; // 大問題! -``` +不変参照の使用者は、それ以降に値が突然変わることなんて予想してません! +しかしながら、複数の不変参照をすることは許されています。 +データを読み込んでいるだけの人に、他人がデータを読み込むことに対して影響を与える能力はないからです。 -これがエラーです: +参照のスコープは、それが導入されたところから始まり、その参照が最後に使用される時点まで続きます。 +例えば、次のコードはコンパイルできるでしょう。不変参照の最後の使用箇所である`println!`は、 +可変参照が導入されるよりも前に発生するからです: -```text -error[E0502]: cannot borrow `s` as mutable because it is also borrowed as -immutable -(エラー: `s`は不変で借用されているので、可変で借用できません) - --> borrow_thrice.rs:6:19 - | -4 | let r1 = &s; // no problem - | - immutable borrow occurs here -5 | let r2 = &s; // no problem -6 | let r3 = &mut s; // BIG PROBLEM - | ^ mutable borrow occurs here -7 | } - | - immutable borrow ends here +```rust,edition2021 +{{#rustdoc_include ../listings/ch04-understanding-ownership/no-listing-13-reference-scope-ends/src/main.rs:here}} ``` -ふう!*さらに*不変な参照をしている間は、可変な参照をすることはできません。不変参照の使用者は、 -それ以降に値が突然変わることなんて予想してません!しかしながら、複数の不変参照をすることは可能です。 -データを読み込んでいるだけの人に、他人がデータを読み込むことに対して影響を与える能力はないからです。 +不変参照`r1`と`r2`のスコープは、それらが最後に使用される`println!`の後で終了します。 +これは可変参照`r3`が作成されるより前のことです。これらのスコープは重なっていないので、 +このコードは許可されます: コンパイラは、スコープの終了より前の時点で参照がもはや使用されていないということを、 +判別できるのです。 -これらのエラーは、時としてイライラするものではありますが、Rustコンパイラがバグの可能性を早期に指摘してくれ(それも実行時ではなくコンパイル時に)、 +借用エラーは、時としてイライラするものではありますが、Rustコンパイラがバグの可能性を早期に指摘してくれ(それも実行時ではなくコンパイル時に)、 問題の発生箇所をズバリ示してくれるのだと覚えておいてください。そうして想定通りにデータが変わらない理由を追いかける必要がなくなります。 -ダングリング参照作りを試してみますが、コンパイラはこれをコンパイルエラーで阻止します: +ダングリング参照を作ってみて、コンパイラがどのようにこれをコンパイルエラーで阻止するか見てみましょう: main.rs:5:16 - | -5 | fn dangle() -> &String { - | ^ expected lifetime parameter - | - = help: this function's return type contains a borrowed value, but there is no - value for it to be borrowed from - (助言: この関数の戻り値型は、借用した値を含んでいますが、借用される値がどこにもありません) - = help: consider giving it a 'static lifetime - ('staticライフタイムを与えることを考慮してみてください) +```console +{{#include ../listings/ch04-understanding-ownership/no-listing-14-dangling-reference/output.txt}} ``` -このエラーメッセージは、まだ講義していない機能について触れています: *ライフタイム*です。 +このエラーメッセージは、まだ講義していない機能について触れています: ライフタイムです。 ライフタイムについては第10章で詳しく議論しますが、ライフタイムに関する部分を無視すれば、 このメッセージは、確かにこのコードが問題になる理由に関する鍵を握っています: ```text this function's return type contains a borrowed value, but there is no value -for it to be borrowed from. +for it to be borrowed from ``` - - - - - ファイル名: src/main.rs -```rust,ignore -fn dangle() -> &String { // dangleはStringへの参照を返す - - let s = String::from("hello"); // sは新しいString - - &s // String sへの参照を返す -} // ここで、sはスコープを抜け、ドロップされる。そのメモリは消される。 - // 危険だ +```rust,ignore,does_not_compile +{{#rustdoc_include ../listings/ch04-understanding-ownership/no-listing-15-dangling-reference-annotated/src/main.rs:here}} ``` diff --git a/src/ch04-03-slices.md b/src/ch04-03-slices.md index e33bc3742..a9a0ed65c 100644 --- a/src/ch04-03-slices.md +++ b/src/ch04-03-slices.md @@ -5,44 +5,46 @@ ## スライス型 -所有権のない別のデータ型は、*スライス*です。スライスにより、コレクション全体ではなく、 -その内の一連の要素を参照することができます。 +*スライス*により、コレクション全体ではなく、その内の連続した要素の列を参照することができます。 +スライスは参照の一種であり、そのため所有権を持っていません。 -ちょっとしたプログラミングの問題を考えてみましょう: 文字列を受け取って、その文字列中の最初の単語を返す関数を書いてください。 +ちょっとしたプログラミングの問題を考えてみましょう: スペースで区切られた複数の単語からなる文字列を受け取って、その文字列中の最初の単語を返す関数を書いてください。 関数が文字列中に空白を見つけられなかったら、文字列全体が一つの単語に違いないので、文字列全体が返されるべきです。 -この関数のシグニチャについて考えてみましょう: +スライスが解決しようとしている問題を理解するために、スライスを使わずにこの関数のシグネチャをどう書くかという問題を通して、 +考えてみましょう。 ```rust,ignore fn first_word(s: &String) -> ? ``` -この関数、`first_word`は引数に`&String`をとります。所有権はいらないので、これで十分です。 +`first_word`関数は引数に`&String`をとります。所有権はいらないので、これで十分です。 ですが、何を返すべきでしょうか?文字列の*一部*について語る方法が全くありません。しかし、 -単語の終端の添え字を返すことができますね。リスト4-7に示したように、その方法を試してみましょう。 +空白によって示される単語の終端の添え字を返すことができますね。リスト4-7に示したように、その方法を試してみましょう。 `String`の値を要素ごとに見て、空白かどうかを確かめる必要があるので、 @@ -85,35 +87,37 @@ Next, we create an iterator over the array of bytes using the `iter` method: ``` -イテレータについて詳しくは、第13章で議論します。今は、`iter`は、コレクション内の各要素を返すメソッドであること、 +イテレータについて詳しくは、[第13章][ch13]で議論します。今は、`iter`は、コレクション内の各要素を返すメソッドであること、 `enumerate`が`iter`の結果をラップして、(結果をそのまま返す)代わりにタプルの一部として各要素を返すことを知っておいてください。 `enumerate`から返ってくるタプルの第1要素は、添え字であり、2番目の要素は、(コレクションの)要素への参照になります。 これは、手動で添え字を計算するよりも少しだけ便利です。 -`enumerate`メソッドがタプルを返すので、Rustのあらゆる場所同様、パターンを使って、そのタプルを分配できます。 -従って、`for`ループ内で、タプルの添え字に対する`i`とタプルの1バイトに対応する`&item`を含むパターンを指定しています。 +`enumerate`メソッドがタプルを返すので、パターンを使って、そのタプルを分配できます。 +パターンについては[第6章][ch6]でさらに議論します。 +`for`ループ内で、タプルの添え字に対する`i`とタプルの1バイトに対応する`&item`を含むパターンを指定しています。 `.iter().enumerate()`から要素への参照を取得するので、パターンに`&`を使っています。 `for`ループ内で、バイトリテラル表記を使用して空白を表すバイトを検索しています。空白が見つかったら、その位置を返します。 @@ -184,8 +188,8 @@ fn second_word(s: &String) -> (usize, usize) { 今、私たちは開始*と*終端の添え字を追うようになりました。特定の状態のデータから計算されたが、 @@ -214,29 +218,23 @@ A *string slice* is a reference to part of a `String`, and it looks like this: ``` -これは、`String`全体への参照を取ることに似ていますが、余計な`[0..5]`という部分が付いています。 -`String`全体への参照ではなく、`String`の一部への参照です。 - - - -`[starting_index..ending_index]`と指定することで、角かっこに範囲を使い、スライスを生成できます。 +`hello`は`String`全体への参照ではなく、追加の`[0..5]`という部分で指定された、`String`の一部への参照です。 +`[starting_index..ending_index]`と指定することで、角かっこに範囲を使い、スライスを生成します。 ここで、`starting_index`はスライスの最初の位置、`ending_index`はスライスの終端位置よりも、 1大きい値です。内部的には、スライスデータ構造は、開始地点とスライスの長さを保持しており、 スライスの長さは`ending_index`から`starting_index`を引いたものに対応します。以上より、 -`let world = &s[6..11];`の場合には、`world`は`s`の添え字6のバイトへのポインタと5という長さを持つスライスになるでしょう。 +`let world = &s[6..11];`の場合には、`world`は`s`の添え字6のバイトへのポインタと`5`という長さを持つスライスになるでしょう。 -文字列sの6バイト目へのポインタと長さ5を保持するworld +3個の表: sのスタックデータを表現するテーブルは、ヒープ上の文字列データ"hello world"のテーブル内の添え字0のバイトを指している。
+3個目の表はスライスworldのスタックデータを表現していて、長さの値5を持ち、ヒープデータの表のバイト6を指している。 -Rustの`..`という範囲記法で、最初の番号(ゼロ)から始めたければ、2連ピリオドの前に値を書かなければいいです。 +Rustの`..`という範囲記法で、添え字0から始めたければ、2連ピリオドの前に値を書かなければいいです。 換言すれば、これらは等価です: ```rust @@ -338,10 +342,10 @@ slice. The type that signifies “string slice” is written as `&str`: ``` リスト4-7で取った方法と同じように、最初の空白を探すことで単語の終端の添え字を取得しています。 @@ -367,7 +371,7 @@ fn second_word(s: &String) -> &str { ``` 借用規則から、何かへの不変な参照がある時、さらに可変な参照を得ることはできないことを思い出してください。 -`clear`は`String`を切り詰める必要があるので、可変な参照を得る必要があります。Rustはこれを認めないので、コンパイルが失敗します。 +`clear`は`String`を切り詰める必要があるので、可変な参照を得る必要があります。 +`clear`の呼び出しの後の`println!`は`word`中の参照を使用するので、不変参照はその時点でもまだ有効でなくてはいけません。 +Rustは`clear`中の可変参照と`word`中の不変参照が同時に存在することを認めないので、コンパイルが失敗します。 RustのおかげでAPIが使いやすくなるだけでなく、ある種のエラー全てを完全にコンパイル時に排除してくれるのです! + + + -#### 文字列リテラルはスライスである +#### スライスとしての文字列リテラル もし、文字列スライスがあるなら、それを直接渡せます。`String`があるなら、 -その`String`全体のスライスを渡せます。`String`への参照の代わりに文字列スライスを取るよう関数を定義すると、 +その`String`のスライスか、`String`への参照を渡せます。この柔軟性は、第15章の[「関数やメソッドで暗黙的な参照外し型強制」][deref-coercions]で扱う機能、 +*参照外し型強制*の利点を活用して実現されています。 + + + +`String`への参照の代わりに文字列スライスを取るよう関数を定義すると、 何も機能を失うことなくAPIをより一般的で有益なものにできるのです。 Filename: src/main.rs @@ -508,7 +531,7 @@ without losing any functionality: 文字列リテラルは、ご想像通り、文字列に特化したものです。ですが、もっと一般的なスライス型も存在します。 @@ -519,8 +542,8 @@ let a = [1, 2, 3, 4, 5]; ``` 文字列の一部を参照したくなる可能性があるのと同様、配列の一部を参照したくなる可能性もあります。 @@ -530,6 +553,8 @@ to part of an array. We’d do so like this: let a = [1, 2, 3, 4, 5]; let slice = &a[1..3]; + +assert_eq!(slice, &[2, 3]); ``` + +[ch13]: ch13-02-iterators.html +[ch6]: ch06-02-match.html#値に束縛されるパターン [strings]: ch08-02-strings.html#文字列でutf-8でエンコードされたテキストを保持する +[deref-coercions]: ch15-02-deref.html#関数やメソッドで暗黙的な参照外し型強制 From 7dce9e15dfa4aa9bb17212a042ef4c47d958854f Mon Sep 17 00:00:00 2001 From: shinmili Date: Sun, 26 May 2024 12:58:02 +0900 Subject: [PATCH 06/10] =?UTF-8?q?ch05=20=E6=A7=8B=E9=80=A0=E4=BD=93?= =?UTF-8?q?=E3=82=92=E4=BD=BF=E7=94=A8=E3=81=97=E3=81=A6=E9=96=A2=E4=BF=82?= =?UTF-8?q?=E3=81=AE=E3=81=82=E3=82=8B=E3=83=87=E3=83=BC=E3=82=BF=E3=82=92?= =?UTF-8?q?=E6=A7=8B=E9=80=A0=E5=8C=96=E3=81=99=E3=82=8B=E3=81=AE=E5=92=8C?= =?UTF-8?q?=E8=A8=B3=E3=82=92=E6=9C=80=E6=96=B0=E7=89=88=E3=81=AB=E6=9B=B4?= =?UTF-8?q?=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit rust-lang/book@19c40bfd2d57641d962f3119a1c343355f1b3c5e --- .../listing-05-01/Cargo.toml | 3 +- .../listing-05-01/src/main.rs | 2 +- .../listing-05-02/Cargo.toml | 3 +- .../listing-05-02/src/main.rs | 10 +- .../listing-05-03/Cargo.toml | 3 +- .../listing-05-03/src/main.rs | 10 +- .../listing-05-04/Cargo.toml | 3 +- .../listing-05-04/src/main.rs | 6 +- .../listing-05-05/Cargo.toml | 3 +- .../listing-05-05/src/main.rs | 6 +- .../listing-05-06/Cargo.toml | 3 +- .../listing-05-06/src/main.rs | 14 +- .../listing-05-07/Cargo.toml | 3 +- .../listing-05-07/src/main.rs | 11 +- .../listing-05-08/Cargo.lock | 3 +- .../listing-05-08/Cargo.toml | 5 +- .../listing-05-08/output.txt | 5 +- .../listing-05-08/src/main.rs | 1 + .../listing-05-09/Cargo.lock | 3 +- .../listing-05-09/Cargo.toml | 5 +- .../listing-05-10/Cargo.lock | 3 +- .../listing-05-10/Cargo.toml | 5 +- .../listing-05-11/Cargo.lock | 3 +- .../listing-05-11/Cargo.toml | 5 +- .../listing-05-11/output.txt | 13 +- .../listing-05-11/src/main.rs | 1 + .../listing-05-12/Cargo.lock | 3 +- .../listing-05-12/Cargo.toml | 5 +- .../listing-05-12/output.txt | 4 +- .../listing-05-13/Cargo.lock | 3 +- .../listing-05-13/Cargo.toml | 5 +- .../listing-05-13/src/main.rs | 1 + .../listing-05-14/Cargo.lock | 3 +- .../listing-05-14/Cargo.toml | 5 +- .../listing-05-15/Cargo.lock | 3 +- .../listing-05-15/Cargo.toml | 5 +- .../listing-05-16/Cargo.lock | 3 +- .../listing-05-16/Cargo.toml | 5 +- .../no-listing-01-tuple-structs/Cargo.toml | 3 +- .../no-listing-01-tuple-structs/src/main.rs | 8 +- .../Cargo.toml | 3 +- .../output.txt | 33 +- .../src/main.rs | 2 +- .../Cargo.lock | 3 +- .../Cargo.toml | 5 +- .../src/main.rs | 4 +- .../Cargo.lock | 7 + .../Cargo.toml | 6 + .../src/main.rs | 5 + .../no-listing-05-dbg-macro/Cargo.lock | 5 + .../no-listing-05-dbg-macro/Cargo.toml | 6 + .../no-listing-05-dbg-macro/output.txt | 9 + .../no-listing-05-dbg-macro/src/main.rs | 15 + .../Cargo.lock | 5 + .../Cargo.toml | 6 + .../src/main.rs | 25 + .../output-only-01-debug/Cargo.lock | 3 +- .../output-only-01-debug/Cargo.toml | 5 +- .../output-only-01-debug/output.txt | 24 +- .../output-only-02-pretty-debug/Cargo.lock | 3 +- .../output-only-02-pretty-debug/Cargo.toml | 5 +- .../output-only-02-pretty-debug/output.txt | 4 +- src/ch05-00-structs.md | 31 +- src/ch05-01-defining-structs.md | 573 ++++++++++-------- src/ch05-02-example-structs.md | 347 ++++++----- src/ch05-03-method-syntax.md | 425 ++++++------- 66 files changed, 973 insertions(+), 774 deletions(-) create mode 100644 listings/ch05-using-structs-to-structure-related-data/no-listing-04-unit-like-structs/Cargo.lock create mode 100644 listings/ch05-using-structs-to-structure-related-data/no-listing-04-unit-like-structs/Cargo.toml create mode 100644 listings/ch05-using-structs-to-structure-related-data/no-listing-04-unit-like-structs/src/main.rs create mode 100644 listings/ch05-using-structs-to-structure-related-data/no-listing-05-dbg-macro/Cargo.lock create mode 100644 listings/ch05-using-structs-to-structure-related-data/no-listing-05-dbg-macro/Cargo.toml create mode 100644 listings/ch05-using-structs-to-structure-related-data/no-listing-05-dbg-macro/output.txt create mode 100644 listings/ch05-using-structs-to-structure-related-data/no-listing-05-dbg-macro/src/main.rs create mode 100644 listings/ch05-using-structs-to-structure-related-data/no-listing-06-method-field-interaction/Cargo.lock create mode 100644 listings/ch05-using-structs-to-structure-related-data/no-listing-06-method-field-interaction/Cargo.toml create mode 100644 listings/ch05-using-structs-to-structure-related-data/no-listing-06-method-field-interaction/src/main.rs diff --git a/listings/ch05-using-structs-to-structure-related-data/listing-05-01/Cargo.toml b/listings/ch05-using-structs-to-structure-related-data/listing-05-01/Cargo.toml index 431e5c305..3232b6065 100644 --- a/listings/ch05-using-structs-to-structure-related-data/listing-05-01/Cargo.toml +++ b/listings/ch05-using-structs-to-structure-related-data/listing-05-01/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "structs" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch05-using-structs-to-structure-related-data/listing-05-01/src/main.rs b/listings/ch05-using-structs-to-structure-related-data/listing-05-01/src/main.rs index a7cff6ec2..16dd15b29 100644 --- a/listings/ch05-using-structs-to-structure-related-data/listing-05-01/src/main.rs +++ b/listings/ch05-using-structs-to-structure-related-data/listing-05-01/src/main.rs @@ -1,9 +1,9 @@ // ANCHOR: here struct User { + active: bool, username: String, email: String, sign_in_count: u64, - active: bool, } // ANCHOR_END: here diff --git a/listings/ch05-using-structs-to-structure-related-data/listing-05-02/Cargo.toml b/listings/ch05-using-structs-to-structure-related-data/listing-05-02/Cargo.toml index 431e5c305..3232b6065 100644 --- a/listings/ch05-using-structs-to-structure-related-data/listing-05-02/Cargo.toml +++ b/listings/ch05-using-structs-to-structure-related-data/listing-05-02/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "structs" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch05-using-structs-to-structure-related-data/listing-05-02/src/main.rs b/listings/ch05-using-structs-to-structure-related-data/listing-05-02/src/main.rs index 390c8ff19..122d25164 100644 --- a/listings/ch05-using-structs-to-structure-related-data/listing-05-02/src/main.rs +++ b/listings/ch05-using-structs-to-structure-related-data/listing-05-02/src/main.rs @@ -1,17 +1,17 @@ struct User { + active: bool, username: String, email: String, sign_in_count: u64, - active: bool, } +// ANCHOR: here fn main() { - // ANCHOR: here let user1 = User { - email: String::from("someone@example.com"), - username: String::from("someusername123"), active: true, + username: String::from("someusername123"), + email: String::from("someone@example.com"), sign_in_count: 1, }; - // ANCHOR_END: here } +// ANCHOR_END: here diff --git a/listings/ch05-using-structs-to-structure-related-data/listing-05-03/Cargo.toml b/listings/ch05-using-structs-to-structure-related-data/listing-05-03/Cargo.toml index 431e5c305..3232b6065 100644 --- a/listings/ch05-using-structs-to-structure-related-data/listing-05-03/Cargo.toml +++ b/listings/ch05-using-structs-to-structure-related-data/listing-05-03/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "structs" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch05-using-structs-to-structure-related-data/listing-05-03/src/main.rs b/listings/ch05-using-structs-to-structure-related-data/listing-05-03/src/main.rs index c599c9d60..35eea8a9a 100644 --- a/listings/ch05-using-structs-to-structure-related-data/listing-05-03/src/main.rs +++ b/listings/ch05-using-structs-to-structure-related-data/listing-05-03/src/main.rs @@ -1,19 +1,19 @@ struct User { + active: bool, username: String, email: String, sign_in_count: u64, - active: bool, } +// ANCHOR: here fn main() { - // ANCHOR: here let mut user1 = User { - email: String::from("someone@example.com"), - username: String::from("someusername123"), active: true, + username: String::from("someusername123"), + email: String::from("someone@example.com"), sign_in_count: 1, }; user1.email = String::from("anotheremail@example.com"); - // ANCHOR_END: here } +// ANCHOR_END: here diff --git a/listings/ch05-using-structs-to-structure-related-data/listing-05-04/Cargo.toml b/listings/ch05-using-structs-to-structure-related-data/listing-05-04/Cargo.toml index 431e5c305..3232b6065 100644 --- a/listings/ch05-using-structs-to-structure-related-data/listing-05-04/Cargo.toml +++ b/listings/ch05-using-structs-to-structure-related-data/listing-05-04/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "structs" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch05-using-structs-to-structure-related-data/listing-05-04/src/main.rs b/listings/ch05-using-structs-to-structure-related-data/listing-05-04/src/main.rs index f934d4c00..8614561c1 100644 --- a/listings/ch05-using-structs-to-structure-related-data/listing-05-04/src/main.rs +++ b/listings/ch05-using-structs-to-structure-related-data/listing-05-04/src/main.rs @@ -1,16 +1,16 @@ struct User { + active: bool, username: String, email: String, sign_in_count: u64, - active: bool, } // ANCHOR: here fn build_user(email: String, username: String) -> User { User { - email: email, - username: username, active: true, + username: username, + email: email, sign_in_count: 1, } } diff --git a/listings/ch05-using-structs-to-structure-related-data/listing-05-05/Cargo.toml b/listings/ch05-using-structs-to-structure-related-data/listing-05-05/Cargo.toml index 431e5c305..3232b6065 100644 --- a/listings/ch05-using-structs-to-structure-related-data/listing-05-05/Cargo.toml +++ b/listings/ch05-using-structs-to-structure-related-data/listing-05-05/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "structs" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch05-using-structs-to-structure-related-data/listing-05-05/src/main.rs b/listings/ch05-using-structs-to-structure-related-data/listing-05-05/src/main.rs index 1833aa8e4..c893c86a9 100644 --- a/listings/ch05-using-structs-to-structure-related-data/listing-05-05/src/main.rs +++ b/listings/ch05-using-structs-to-structure-related-data/listing-05-05/src/main.rs @@ -1,16 +1,16 @@ struct User { + active: bool, username: String, email: String, sign_in_count: u64, - active: bool, } // ANCHOR: here fn build_user(email: String, username: String) -> User { User { - email, - username, active: true, + username, + email, sign_in_count: 1, } } diff --git a/listings/ch05-using-structs-to-structure-related-data/listing-05-06/Cargo.toml b/listings/ch05-using-structs-to-structure-related-data/listing-05-06/Cargo.toml index 431e5c305..3232b6065 100644 --- a/listings/ch05-using-structs-to-structure-related-data/listing-05-06/Cargo.toml +++ b/listings/ch05-using-structs-to-structure-related-data/listing-05-06/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "structs" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch05-using-structs-to-structure-related-data/listing-05-06/src/main.rs b/listings/ch05-using-structs-to-structure-related-data/listing-05-06/src/main.rs index 6c6d83d9b..15e7690e1 100644 --- a/listings/ch05-using-structs-to-structure-related-data/listing-05-06/src/main.rs +++ b/listings/ch05-using-structs-to-structure-related-data/listing-05-06/src/main.rs @@ -1,24 +1,28 @@ struct User { + active: bool, username: String, email: String, sign_in_count: u64, - active: bool, } +// ANCHOR: here fn main() { + // --snip-- + // ANCHOR_END: here + let user1 = User { email: String::from("someone@example.com"), username: String::from("someusername123"), active: true, sign_in_count: 1, }; - // ANCHOR: here + let user2 = User { - email: String::from("another@example.com"), - username: String::from("anotherusername567"), active: user1.active, + username: user1.username, + email: String::from("another@example.com"), sign_in_count: user1.sign_in_count, }; - // ANCHOR_END: here } +// ANCHOR_END: here diff --git a/listings/ch05-using-structs-to-structure-related-data/listing-05-07/Cargo.toml b/listings/ch05-using-structs-to-structure-related-data/listing-05-07/Cargo.toml index 431e5c305..3232b6065 100644 --- a/listings/ch05-using-structs-to-structure-related-data/listing-05-07/Cargo.toml +++ b/listings/ch05-using-structs-to-structure-related-data/listing-05-07/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "structs" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch05-using-structs-to-structure-related-data/listing-05-07/src/main.rs b/listings/ch05-using-structs-to-structure-related-data/listing-05-07/src/main.rs index 17cef457b..008ad18f6 100644 --- a/listings/ch05-using-structs-to-structure-related-data/listing-05-07/src/main.rs +++ b/listings/ch05-using-structs-to-structure-related-data/listing-05-07/src/main.rs @@ -1,23 +1,26 @@ struct User { + active: bool, username: String, email: String, sign_in_count: u64, - active: bool, } +// ANCHOR: here fn main() { + // --snip-- + // ANCHOR_END: here + let user1 = User { email: String::from("someone@example.com"), username: String::from("someusername123"), active: true, sign_in_count: 1, }; - // ANCHOR: here + let user2 = User { email: String::from("another@example.com"), - username: String::from("anotherusername567"), ..user1 }; - // ANCHOR_END: here } +// ANCHOR_END: here diff --git a/listings/ch05-using-structs-to-structure-related-data/listing-05-08/Cargo.lock b/listings/ch05-using-structs-to-structure-related-data/listing-05-08/Cargo.lock index bede081a0..4aabe7da6 100644 --- a/listings/ch05-using-structs-to-structure-related-data/listing-05-08/Cargo.lock +++ b/listings/ch05-using-structs-to-structure-related-data/listing-05-08/Cargo.lock @@ -1,6 +1,5 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. [[package]] -name = "structs" +name = "rectangles" version = "0.1.0" - diff --git a/listings/ch05-using-structs-to-structure-related-data/listing-05-08/Cargo.toml b/listings/ch05-using-structs-to-structure-related-data/listing-05-08/Cargo.toml index 431e5c305..4a279a450 100644 --- a/listings/ch05-using-structs-to-structure-related-data/listing-05-08/Cargo.toml +++ b/listings/ch05-using-structs-to-structure-related-data/listing-05-08/Cargo.toml @@ -1,7 +1,6 @@ [package] -name = "structs" +name = "rectangles" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch05-using-structs-to-structure-related-data/listing-05-08/output.txt b/listings/ch05-using-structs-to-structure-related-data/listing-05-08/output.txt index 88e10d320..aaedb98a4 100644 --- a/listings/ch05-using-structs-to-structure-related-data/listing-05-08/output.txt +++ b/listings/ch05-using-structs-to-structure-related-data/listing-05-08/output.txt @@ -1,5 +1,6 @@ $ cargo run - Compiling structs v0.1.0 (file:///projects/structs) + Compiling rectangles v0.1.0 (file:///projects/rectangles) Finished dev [unoptimized + debuginfo] target(s) in 0.42s - Running `target/debug/structs` + Running `target/debug/rectangles` The area of the rectangle is 1500 square pixels. +(長方形の面積は、1500平方ピクセルです) diff --git a/listings/ch05-using-structs-to-structure-related-data/listing-05-08/src/main.rs b/listings/ch05-using-structs-to-structure-related-data/listing-05-08/src/main.rs index f324529fd..587e870bb 100644 --- a/listings/ch05-using-structs-to-structure-related-data/listing-05-08/src/main.rs +++ b/listings/ch05-using-structs-to-structure-related-data/listing-05-08/src/main.rs @@ -4,6 +4,7 @@ fn main() { let height1 = 50; println!( + // 長方形の面積は、{}平方ピクセルです "The area of the rectangle is {} square pixels.", area(width1, height1) ); diff --git a/listings/ch05-using-structs-to-structure-related-data/listing-05-09/Cargo.lock b/listings/ch05-using-structs-to-structure-related-data/listing-05-09/Cargo.lock index bede081a0..4aabe7da6 100644 --- a/listings/ch05-using-structs-to-structure-related-data/listing-05-09/Cargo.lock +++ b/listings/ch05-using-structs-to-structure-related-data/listing-05-09/Cargo.lock @@ -1,6 +1,5 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. [[package]] -name = "structs" +name = "rectangles" version = "0.1.0" - diff --git a/listings/ch05-using-structs-to-structure-related-data/listing-05-09/Cargo.toml b/listings/ch05-using-structs-to-structure-related-data/listing-05-09/Cargo.toml index 431e5c305..4a279a450 100644 --- a/listings/ch05-using-structs-to-structure-related-data/listing-05-09/Cargo.toml +++ b/listings/ch05-using-structs-to-structure-related-data/listing-05-09/Cargo.toml @@ -1,7 +1,6 @@ [package] -name = "structs" +name = "rectangles" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch05-using-structs-to-structure-related-data/listing-05-10/Cargo.lock b/listings/ch05-using-structs-to-structure-related-data/listing-05-10/Cargo.lock index bede081a0..4aabe7da6 100644 --- a/listings/ch05-using-structs-to-structure-related-data/listing-05-10/Cargo.lock +++ b/listings/ch05-using-structs-to-structure-related-data/listing-05-10/Cargo.lock @@ -1,6 +1,5 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. [[package]] -name = "structs" +name = "rectangles" version = "0.1.0" - diff --git a/listings/ch05-using-structs-to-structure-related-data/listing-05-10/Cargo.toml b/listings/ch05-using-structs-to-structure-related-data/listing-05-10/Cargo.toml index 431e5c305..4a279a450 100644 --- a/listings/ch05-using-structs-to-structure-related-data/listing-05-10/Cargo.toml +++ b/listings/ch05-using-structs-to-structure-related-data/listing-05-10/Cargo.toml @@ -1,7 +1,6 @@ [package] -name = "structs" +name = "rectangles" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch05-using-structs-to-structure-related-data/listing-05-11/Cargo.lock b/listings/ch05-using-structs-to-structure-related-data/listing-05-11/Cargo.lock index bede081a0..4aabe7da6 100644 --- a/listings/ch05-using-structs-to-structure-related-data/listing-05-11/Cargo.lock +++ b/listings/ch05-using-structs-to-structure-related-data/listing-05-11/Cargo.lock @@ -1,6 +1,5 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. [[package]] -name = "structs" +name = "rectangles" version = "0.1.0" - diff --git a/listings/ch05-using-structs-to-structure-related-data/listing-05-11/Cargo.toml b/listings/ch05-using-structs-to-structure-related-data/listing-05-11/Cargo.toml index 431e5c305..4a279a450 100644 --- a/listings/ch05-using-structs-to-structure-related-data/listing-05-11/Cargo.toml +++ b/listings/ch05-using-structs-to-structure-related-data/listing-05-11/Cargo.toml @@ -1,7 +1,6 @@ [package] -name = "structs" +name = "rectangles" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch05-using-structs-to-structure-related-data/listing-05-11/output.txt b/listings/ch05-using-structs-to-structure-related-data/listing-05-11/output.txt index 1e03d0625..d19319d00 100644 --- a/listings/ch05-using-structs-to-structure-related-data/listing-05-11/output.txt +++ b/listings/ch05-using-structs-to-structure-related-data/listing-05-11/output.txt @@ -1,6 +1,7 @@ $ cargo run - Compiling structs v0.1.0 (file:///projects/structs) + Compiling rectangles v0.1.0 (file:///projects/rectangles) error[E0277]: `Rectangle` doesn't implement `std::fmt::Display` +(エラー: `Rectangle`は`std::fmt::Display`を実装していません) --> src/main.rs:12:29 | 12 | println!("rect1 is {}", rect1); @@ -8,11 +9,9 @@ error[E0277]: `Rectangle` doesn't implement `std::fmt::Display` | = help: the trait `std::fmt::Display` is not implemented for `Rectangle` = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead - = note: required by `std::fmt::Display::fmt` - -error: aborting due to previous error + (ヘルプ: `std::fmt::Display`は`Rectangle`に対して実装されていません) + (注釈: フォーマット文字列では代わりに`{:?}`(またはpretty-printするためには{:#?})が使用できるかもしれません) + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) For more information about this error, try `rustc --explain E0277`. -error: could not compile `structs`. - -To learn more, run the command again with --verbose. +error: could not compile `rectangles` (bin "rectangles") due to 1 previous error diff --git a/listings/ch05-using-structs-to-structure-related-data/listing-05-11/src/main.rs b/listings/ch05-using-structs-to-structure-related-data/listing-05-11/src/main.rs index 0ff8dcc8c..5e45f74e8 100644 --- a/listings/ch05-using-structs-to-structure-related-data/listing-05-11/src/main.rs +++ b/listings/ch05-using-structs-to-structure-related-data/listing-05-11/src/main.rs @@ -9,5 +9,6 @@ fn main() { height: 50, }; + // rect1は{}です println!("rect1 is {}", rect1); } diff --git a/listings/ch05-using-structs-to-structure-related-data/listing-05-12/Cargo.lock b/listings/ch05-using-structs-to-structure-related-data/listing-05-12/Cargo.lock index bede081a0..4aabe7da6 100644 --- a/listings/ch05-using-structs-to-structure-related-data/listing-05-12/Cargo.lock +++ b/listings/ch05-using-structs-to-structure-related-data/listing-05-12/Cargo.lock @@ -1,6 +1,5 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. [[package]] -name = "structs" +name = "rectangles" version = "0.1.0" - diff --git a/listings/ch05-using-structs-to-structure-related-data/listing-05-12/Cargo.toml b/listings/ch05-using-structs-to-structure-related-data/listing-05-12/Cargo.toml index 431e5c305..4a279a450 100644 --- a/listings/ch05-using-structs-to-structure-related-data/listing-05-12/Cargo.toml +++ b/listings/ch05-using-structs-to-structure-related-data/listing-05-12/Cargo.toml @@ -1,7 +1,6 @@ [package] -name = "structs" +name = "rectangles" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch05-using-structs-to-structure-related-data/listing-05-12/output.txt b/listings/ch05-using-structs-to-structure-related-data/listing-05-12/output.txt index 3abfb4257..c37be6b5b 100644 --- a/listings/ch05-using-structs-to-structure-related-data/listing-05-12/output.txt +++ b/listings/ch05-using-structs-to-structure-related-data/listing-05-12/output.txt @@ -1,5 +1,5 @@ $ cargo run - Compiling structs v0.1.0 (file:///projects/structs) + Compiling rectangles v0.1.0 (file:///projects/rectangles) Finished dev [unoptimized + debuginfo] target(s) in 0.48s - Running `target/debug/structs` + Running `target/debug/rectangles` rect1 is Rectangle { width: 30, height: 50 } diff --git a/listings/ch05-using-structs-to-structure-related-data/listing-05-13/Cargo.lock b/listings/ch05-using-structs-to-structure-related-data/listing-05-13/Cargo.lock index bede081a0..4aabe7da6 100644 --- a/listings/ch05-using-structs-to-structure-related-data/listing-05-13/Cargo.lock +++ b/listings/ch05-using-structs-to-structure-related-data/listing-05-13/Cargo.lock @@ -1,6 +1,5 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. [[package]] -name = "structs" +name = "rectangles" version = "0.1.0" - diff --git a/listings/ch05-using-structs-to-structure-related-data/listing-05-13/Cargo.toml b/listings/ch05-using-structs-to-structure-related-data/listing-05-13/Cargo.toml index 431e5c305..4a279a450 100644 --- a/listings/ch05-using-structs-to-structure-related-data/listing-05-13/Cargo.toml +++ b/listings/ch05-using-structs-to-structure-related-data/listing-05-13/Cargo.toml @@ -1,7 +1,6 @@ [package] -name = "structs" +name = "rectangles" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch05-using-structs-to-structure-related-data/listing-05-13/src/main.rs b/listings/ch05-using-structs-to-structure-related-data/listing-05-13/src/main.rs index e4f45e868..a5c6cb1f9 100644 --- a/listings/ch05-using-structs-to-structure-related-data/listing-05-13/src/main.rs +++ b/listings/ch05-using-structs-to-structure-related-data/listing-05-13/src/main.rs @@ -17,6 +17,7 @@ fn main() { }; println!( + // 長方形の面積は{}平方ピクセルです。 "The area of the rectangle is {} square pixels.", rect1.area() ); diff --git a/listings/ch05-using-structs-to-structure-related-data/listing-05-14/Cargo.lock b/listings/ch05-using-structs-to-structure-related-data/listing-05-14/Cargo.lock index bede081a0..4aabe7da6 100644 --- a/listings/ch05-using-structs-to-structure-related-data/listing-05-14/Cargo.lock +++ b/listings/ch05-using-structs-to-structure-related-data/listing-05-14/Cargo.lock @@ -1,6 +1,5 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. [[package]] -name = "structs" +name = "rectangles" version = "0.1.0" - diff --git a/listings/ch05-using-structs-to-structure-related-data/listing-05-14/Cargo.toml b/listings/ch05-using-structs-to-structure-related-data/listing-05-14/Cargo.toml index 431e5c305..4a279a450 100644 --- a/listings/ch05-using-structs-to-structure-related-data/listing-05-14/Cargo.toml +++ b/listings/ch05-using-structs-to-structure-related-data/listing-05-14/Cargo.toml @@ -1,7 +1,6 @@ [package] -name = "structs" +name = "rectangles" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch05-using-structs-to-structure-related-data/listing-05-15/Cargo.lock b/listings/ch05-using-structs-to-structure-related-data/listing-05-15/Cargo.lock index bede081a0..4aabe7da6 100644 --- a/listings/ch05-using-structs-to-structure-related-data/listing-05-15/Cargo.lock +++ b/listings/ch05-using-structs-to-structure-related-data/listing-05-15/Cargo.lock @@ -1,6 +1,5 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. [[package]] -name = "structs" +name = "rectangles" version = "0.1.0" - diff --git a/listings/ch05-using-structs-to-structure-related-data/listing-05-15/Cargo.toml b/listings/ch05-using-structs-to-structure-related-data/listing-05-15/Cargo.toml index 431e5c305..4a279a450 100644 --- a/listings/ch05-using-structs-to-structure-related-data/listing-05-15/Cargo.toml +++ b/listings/ch05-using-structs-to-structure-related-data/listing-05-15/Cargo.toml @@ -1,7 +1,6 @@ [package] -name = "structs" +name = "rectangles" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch05-using-structs-to-structure-related-data/listing-05-16/Cargo.lock b/listings/ch05-using-structs-to-structure-related-data/listing-05-16/Cargo.lock index bede081a0..4aabe7da6 100644 --- a/listings/ch05-using-structs-to-structure-related-data/listing-05-16/Cargo.lock +++ b/listings/ch05-using-structs-to-structure-related-data/listing-05-16/Cargo.lock @@ -1,6 +1,5 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. [[package]] -name = "structs" +name = "rectangles" version = "0.1.0" - diff --git a/listings/ch05-using-structs-to-structure-related-data/listing-05-16/Cargo.toml b/listings/ch05-using-structs-to-structure-related-data/listing-05-16/Cargo.toml index 431e5c305..4a279a450 100644 --- a/listings/ch05-using-structs-to-structure-related-data/listing-05-16/Cargo.toml +++ b/listings/ch05-using-structs-to-structure-related-data/listing-05-16/Cargo.toml @@ -1,7 +1,6 @@ [package] -name = "structs" +name = "rectangles" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch05-using-structs-to-structure-related-data/no-listing-01-tuple-structs/Cargo.toml b/listings/ch05-using-structs-to-structure-related-data/no-listing-01-tuple-structs/Cargo.toml index 431e5c305..3232b6065 100644 --- a/listings/ch05-using-structs-to-structure-related-data/no-listing-01-tuple-structs/Cargo.toml +++ b/listings/ch05-using-structs-to-structure-related-data/no-listing-01-tuple-structs/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "structs" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch05-using-structs-to-structure-related-data/no-listing-01-tuple-structs/src/main.rs b/listings/ch05-using-structs-to-structure-related-data/no-listing-01-tuple-structs/src/main.rs index 4c92c5d77..0d993162b 100644 --- a/listings/ch05-using-structs-to-structure-related-data/no-listing-01-tuple-structs/src/main.rs +++ b/listings/ch05-using-structs-to-structure-related-data/no-listing-01-tuple-structs/src/main.rs @@ -1,9 +1,7 @@ -fn main() { - // ANCHOR: here - struct Color(i32, i32, i32); - struct Point(i32, i32, i32); +struct Color(i32, i32, i32); +struct Point(i32, i32, i32); +fn main() { let black = Color(0, 0, 0); let origin = Point(0, 0, 0); - // ANCHOR_END: here } diff --git a/listings/ch05-using-structs-to-structure-related-data/no-listing-02-reference-in-struct/Cargo.toml b/listings/ch05-using-structs-to-structure-related-data/no-listing-02-reference-in-struct/Cargo.toml index dec1c4bd5..d36dbc1d3 100644 --- a/listings/ch05-using-structs-to-structure-related-data/no-listing-02-reference-in-struct/Cargo.toml +++ b/listings/ch05-using-structs-to-structure-related-data/no-listing-02-reference-in-struct/Cargo.toml @@ -1,8 +1,7 @@ [package] name = "structs" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/listings/ch05-using-structs-to-structure-related-data/no-listing-02-reference-in-struct/output.txt b/listings/ch05-using-structs-to-structure-related-data/no-listing-02-reference-in-struct/output.txt index 9a75534c3..5f9344c51 100644 --- a/listings/ch05-using-structs-to-structure-related-data/no-listing-02-reference-in-struct/output.txt +++ b/listings/ch05-using-structs-to-structure-related-data/no-listing-02-reference-in-struct/output.txt @@ -1,20 +1,31 @@ $ cargo run Compiling structs v0.1.0 (file:///projects/structs) error[E0106]: missing lifetime specifier - --> src/main.rs:2:15 + --> src/main.rs:3:15 + | +3 | username: &str, + | ^ expected named lifetime parameter + | +help: consider introducing a named lifetime parameter + | +1 ~ struct User<'a> { +2 | active: bool, +3 ~ username: &'a str, | -2 | username: &str, - | ^ expected lifetime parameter error[E0106]: missing lifetime specifier - --> src/main.rs:3:12 + --> src/main.rs:4:12 + | +4 | email: &str, + | ^ expected named lifetime parameter + | +help: consider introducing a named lifetime parameter + | +1 ~ struct User<'a> { +2 | active: bool, +3 | username: &str, +4 ~ email: &'a str, | -3 | email: &str, - | ^ expected lifetime parameter - -error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0106`. -error: could not compile `structs`. - -To learn more, run the command again with --verbose. +error: could not compile `structs` (bin "structs") due to 2 previous errors diff --git a/listings/ch05-using-structs-to-structure-related-data/no-listing-02-reference-in-struct/src/main.rs b/listings/ch05-using-structs-to-structure-related-data/no-listing-02-reference-in-struct/src/main.rs index 3cf6ffa4f..96092d042 100644 --- a/listings/ch05-using-structs-to-structure-related-data/no-listing-02-reference-in-struct/src/main.rs +++ b/listings/ch05-using-structs-to-structure-related-data/no-listing-02-reference-in-struct/src/main.rs @@ -1,8 +1,8 @@ struct User { + active: bool, username: &str, email: &str, sign_in_count: u64, - active: bool, } fn main() { diff --git a/listings/ch05-using-structs-to-structure-related-data/no-listing-03-associated-functions/Cargo.lock b/listings/ch05-using-structs-to-structure-related-data/no-listing-03-associated-functions/Cargo.lock index bede081a0..4aabe7da6 100644 --- a/listings/ch05-using-structs-to-structure-related-data/no-listing-03-associated-functions/Cargo.lock +++ b/listings/ch05-using-structs-to-structure-related-data/no-listing-03-associated-functions/Cargo.lock @@ -1,6 +1,5 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. [[package]] -name = "structs" +name = "rectangles" version = "0.1.0" - diff --git a/listings/ch05-using-structs-to-structure-related-data/no-listing-03-associated-functions/Cargo.toml b/listings/ch05-using-structs-to-structure-related-data/no-listing-03-associated-functions/Cargo.toml index 431e5c305..4a279a450 100644 --- a/listings/ch05-using-structs-to-structure-related-data/no-listing-03-associated-functions/Cargo.toml +++ b/listings/ch05-using-structs-to-structure-related-data/no-listing-03-associated-functions/Cargo.toml @@ -1,7 +1,6 @@ [package] -name = "structs" +name = "rectangles" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch05-using-structs-to-structure-related-data/no-listing-03-associated-functions/src/main.rs b/listings/ch05-using-structs-to-structure-related-data/no-listing-03-associated-functions/src/main.rs index d5b1692a4..47fedc552 100644 --- a/listings/ch05-using-structs-to-structure-related-data/no-listing-03-associated-functions/src/main.rs +++ b/listings/ch05-using-structs-to-structure-related-data/no-listing-03-associated-functions/src/main.rs @@ -6,8 +6,8 @@ struct Rectangle { // ANCHOR: here impl Rectangle { - fn square(size: u32) -> Rectangle { - Rectangle { + fn square(size: u32) -> Self { + Self { width: size, height: size, } diff --git a/listings/ch05-using-structs-to-structure-related-data/no-listing-04-unit-like-structs/Cargo.lock b/listings/ch05-using-structs-to-structure-related-data/no-listing-04-unit-like-structs/Cargo.lock new file mode 100644 index 000000000..fb30ed9c8 --- /dev/null +++ b/listings/ch05-using-structs-to-structure-related-data/no-listing-04-unit-like-structs/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "structs" +version = "0.1.0" diff --git a/listings/ch05-using-structs-to-structure-related-data/no-listing-04-unit-like-structs/Cargo.toml b/listings/ch05-using-structs-to-structure-related-data/no-listing-04-unit-like-structs/Cargo.toml new file mode 100644 index 000000000..3232b6065 --- /dev/null +++ b/listings/ch05-using-structs-to-structure-related-data/no-listing-04-unit-like-structs/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "structs" +version = "0.1.0" +edition = "2021" + +[dependencies] diff --git a/listings/ch05-using-structs-to-structure-related-data/no-listing-04-unit-like-structs/src/main.rs b/listings/ch05-using-structs-to-structure-related-data/no-listing-04-unit-like-structs/src/main.rs new file mode 100644 index 000000000..d48c94e99 --- /dev/null +++ b/listings/ch05-using-structs-to-structure-related-data/no-listing-04-unit-like-structs/src/main.rs @@ -0,0 +1,5 @@ +struct AlwaysEqual; + +fn main() { + let subject = AlwaysEqual; +} diff --git a/listings/ch05-using-structs-to-structure-related-data/no-listing-05-dbg-macro/Cargo.lock b/listings/ch05-using-structs-to-structure-related-data/no-listing-05-dbg-macro/Cargo.lock new file mode 100644 index 000000000..4aabe7da6 --- /dev/null +++ b/listings/ch05-using-structs-to-structure-related-data/no-listing-05-dbg-macro/Cargo.lock @@ -0,0 +1,5 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "rectangles" +version = "0.1.0" diff --git a/listings/ch05-using-structs-to-structure-related-data/no-listing-05-dbg-macro/Cargo.toml b/listings/ch05-using-structs-to-structure-related-data/no-listing-05-dbg-macro/Cargo.toml new file mode 100644 index 000000000..4a279a450 --- /dev/null +++ b/listings/ch05-using-structs-to-structure-related-data/no-listing-05-dbg-macro/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "rectangles" +version = "0.1.0" +edition = "2021" + +[dependencies] diff --git a/listings/ch05-using-structs-to-structure-related-data/no-listing-05-dbg-macro/output.txt b/listings/ch05-using-structs-to-structure-related-data/no-listing-05-dbg-macro/output.txt new file mode 100644 index 000000000..bfb88ebee --- /dev/null +++ b/listings/ch05-using-structs-to-structure-related-data/no-listing-05-dbg-macro/output.txt @@ -0,0 +1,9 @@ +$ cargo run + Compiling rectangles v0.1.0 (file:///projects/rectangles) + Finished dev [unoptimized + debuginfo] target(s) in 0.61s + Running `target/debug/rectangles` +[src/main.rs:10:16] 30 * scale = 60 +[src/main.rs:14:5] &rect1 = Rectangle { + width: 60, + height: 50, +} diff --git a/listings/ch05-using-structs-to-structure-related-data/no-listing-05-dbg-macro/src/main.rs b/listings/ch05-using-structs-to-structure-related-data/no-listing-05-dbg-macro/src/main.rs new file mode 100644 index 000000000..dd0342959 --- /dev/null +++ b/listings/ch05-using-structs-to-structure-related-data/no-listing-05-dbg-macro/src/main.rs @@ -0,0 +1,15 @@ +#[derive(Debug)] +struct Rectangle { + width: u32, + height: u32, +} + +fn main() { + let scale = 2; + let rect1 = Rectangle { + width: dbg!(30 * scale), + height: 50, + }; + + dbg!(&rect1); +} diff --git a/listings/ch05-using-structs-to-structure-related-data/no-listing-06-method-field-interaction/Cargo.lock b/listings/ch05-using-structs-to-structure-related-data/no-listing-06-method-field-interaction/Cargo.lock new file mode 100644 index 000000000..4aabe7da6 --- /dev/null +++ b/listings/ch05-using-structs-to-structure-related-data/no-listing-06-method-field-interaction/Cargo.lock @@ -0,0 +1,5 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "rectangles" +version = "0.1.0" diff --git a/listings/ch05-using-structs-to-structure-related-data/no-listing-06-method-field-interaction/Cargo.toml b/listings/ch05-using-structs-to-structure-related-data/no-listing-06-method-field-interaction/Cargo.toml new file mode 100644 index 000000000..4a279a450 --- /dev/null +++ b/listings/ch05-using-structs-to-structure-related-data/no-listing-06-method-field-interaction/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "rectangles" +version = "0.1.0" +edition = "2021" + +[dependencies] diff --git a/listings/ch05-using-structs-to-structure-related-data/no-listing-06-method-field-interaction/src/main.rs b/listings/ch05-using-structs-to-structure-related-data/no-listing-06-method-field-interaction/src/main.rs new file mode 100644 index 000000000..f893f095c --- /dev/null +++ b/listings/ch05-using-structs-to-structure-related-data/no-listing-06-method-field-interaction/src/main.rs @@ -0,0 +1,25 @@ +#[derive(Debug)] +struct Rectangle { + width: u32, + height: u32, +} + +// ANCHOR: here +impl Rectangle { + fn width(&self) -> bool { + self.width > 0 + } +} + +fn main() { + let rect1 = Rectangle { + width: 30, + height: 50, + }; + + if rect1.width() { + // 長方形は非ゼロの幅を持っています; それは{}です + println!("The rectangle has a nonzero width; it is {}", rect1.width); + } +} +// ANCHOR_END: here diff --git a/listings/ch05-using-structs-to-structure-related-data/output-only-01-debug/Cargo.lock b/listings/ch05-using-structs-to-structure-related-data/output-only-01-debug/Cargo.lock index bede081a0..4aabe7da6 100644 --- a/listings/ch05-using-structs-to-structure-related-data/output-only-01-debug/Cargo.lock +++ b/listings/ch05-using-structs-to-structure-related-data/output-only-01-debug/Cargo.lock @@ -1,6 +1,5 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. [[package]] -name = "structs" +name = "rectangles" version = "0.1.0" - diff --git a/listings/ch05-using-structs-to-structure-related-data/output-only-01-debug/Cargo.toml b/listings/ch05-using-structs-to-structure-related-data/output-only-01-debug/Cargo.toml index 431e5c305..4a279a450 100644 --- a/listings/ch05-using-structs-to-structure-related-data/output-only-01-debug/Cargo.toml +++ b/listings/ch05-using-structs-to-structure-related-data/output-only-01-debug/Cargo.toml @@ -1,7 +1,6 @@ [package] -name = "structs" +name = "rectangles" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch05-using-structs-to-structure-related-data/output-only-01-debug/output.txt b/listings/ch05-using-structs-to-structure-related-data/output-only-01-debug/output.txt index c891d9342..5c67e0b06 100644 --- a/listings/ch05-using-structs-to-structure-related-data/output-only-01-debug/output.txt +++ b/listings/ch05-using-structs-to-structure-related-data/output-only-01-debug/output.txt @@ -1,18 +1,22 @@ $ cargo run - Compiling structs v0.1.0 (file:///projects/structs) -error[E0277]: `Rectangle` doesn't implement `std::fmt::Debug` + Compiling rectangles v0.1.0 (file:///projects/rectangles) +error[E0277]: `Rectangle` doesn't implement `Debug` +(エラー: `Rectangle`は`Debug`を実装していません) --> src/main.rs:12:31 | 12 | println!("rect1 is {:?}", rect1); | ^^^^^ `Rectangle` cannot be formatted using `{:?}` | - = help: the trait `std::fmt::Debug` is not implemented for `Rectangle` - = note: add `#[derive(Debug)]` or manually implement `std::fmt::Debug` - = note: required by `std::fmt::Debug::fmt` - -error: aborting due to previous error + = help: the trait `Debug` is not implemented for `Rectangle` + = note: add `#[derive(Debug)]` to `Rectangle` or manually `impl Debug for Rectangle` + (ヘルプ: トレイト`Debug`は`Rectangle`に対して実装されていません) + (注釈: `Rectangle`に`#[derive(Debug)]`を追加するか、手動で`impl Debug for Rectangle`してください) + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `Rectangle` with `#[derive(Debug)]` + | +1 + #[derive(Debug)] +2 | struct Rectangle { + | For more information about this error, try `rustc --explain E0277`. -error: could not compile `structs`. - -To learn more, run the command again with --verbose. +error: could not compile `rectangles` (bin "rectangles") due to 1 previous error diff --git a/listings/ch05-using-structs-to-structure-related-data/output-only-02-pretty-debug/Cargo.lock b/listings/ch05-using-structs-to-structure-related-data/output-only-02-pretty-debug/Cargo.lock index bede081a0..4aabe7da6 100644 --- a/listings/ch05-using-structs-to-structure-related-data/output-only-02-pretty-debug/Cargo.lock +++ b/listings/ch05-using-structs-to-structure-related-data/output-only-02-pretty-debug/Cargo.lock @@ -1,6 +1,5 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. [[package]] -name = "structs" +name = "rectangles" version = "0.1.0" - diff --git a/listings/ch05-using-structs-to-structure-related-data/output-only-02-pretty-debug/Cargo.toml b/listings/ch05-using-structs-to-structure-related-data/output-only-02-pretty-debug/Cargo.toml index 431e5c305..4a279a450 100644 --- a/listings/ch05-using-structs-to-structure-related-data/output-only-02-pretty-debug/Cargo.toml +++ b/listings/ch05-using-structs-to-structure-related-data/output-only-02-pretty-debug/Cargo.toml @@ -1,7 +1,6 @@ [package] -name = "structs" +name = "rectangles" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch05-using-structs-to-structure-related-data/output-only-02-pretty-debug/output.txt b/listings/ch05-using-structs-to-structure-related-data/output-only-02-pretty-debug/output.txt index 099ef9eac..db6deed9b 100644 --- a/listings/ch05-using-structs-to-structure-related-data/output-only-02-pretty-debug/output.txt +++ b/listings/ch05-using-structs-to-structure-related-data/output-only-02-pretty-debug/output.txt @@ -1,7 +1,7 @@ $ cargo run - Compiling structs v0.1.0 (file:///projects/structs) + Compiling rectangles v0.1.0 (file:///projects/rectangles) Finished dev [unoptimized + debuginfo] target(s) in 0.48s - Running `target/debug/structs` + Running `target/debug/rectangles` rect1 is Rectangle { width: 30, height: 50, diff --git a/src/ch05-00-structs.md b/src/ch05-00-structs.md index 28fca40bf..16458e0af 100644 --- a/src/ch05-00-structs.md +++ b/src/ch05-00-structs.md @@ -5,19 +5,26 @@ # 構造体を使用して関係のあるデータを構造化する *struct*または、*構造体*は、意味のあるグループを形成する複数の関連した値をまとめ、名前付けできる独自のデータ型です。 あなたがオブジェクト指向言語に造詣が深いなら、*struct*はオブジェクトのデータ属性みたいなものです。 -この章では、タプルと構造体を対照的に比較し、構造体の使用法をデモし、メソッドや関連関数を定義して、 -構造体のデータに紐付く振る舞いを指定する方法について議論します。構造体と*enum*(第6章で議論します)は、 -自分のプログラム領域で新しい型を定義し、Rustのコンパイル時型精査機能をフル活用する構成要素になります。 +この章では、すでに学習したものに積み重ねる目的でタプルと構造体を対照的に比較し、データをまとめるのに構造体がより良い方法となるのはどういう場合かを示します。 + + + +構造体を定義してインスタンス化する方法を実演します。 +関連関数、特に*メソッド*と呼ばれる種類の関連関数を定義して、構造体型に紐付く振る舞いを指定する方法について議論します。 +構造体と*enum*(第6章で議論します)は、自分のプログラム領域で新しい型を定義し、Rustのコンパイル時型精査機能をフル活用する構成要素になります。 \ No newline at end of file diff --git a/src/ch05-01-defining-structs.md b/src/ch05-01-defining-structs.md index f53841954..ba2a031be 100644 --- a/src/ch05-01-defining-structs.md +++ b/src/ch05-01-defining-structs.md @@ -5,16 +5,18 @@ ## 構造体を定義し、インスタンス化する -構造体は第3章で議論したタプルと似ています。タプル同様、構造体の一部を異なる型にできます。 -一方タプルとは違って、各データ片には名前をつけるので、値の意味が明確になります。 -この名前のおかげで、構造体はタプルに比して、より柔軟になるわけです: データの順番に頼って、 +構造体は、[「タプル型」][tuples]の節で議論したタプルと、どちらも関係する複数の値を抱えるという点で似ています。 +タプル同様、構造体の一部を異なる型にできます。 +一方タプルとは違って、構造体では各データ片には名前をつけるので、値の意味が明確になります。 +これらの名前が付いていることで、構造体はタプルに比して、より柔軟になるわけです: データの順番に頼って、 インスタンスの値を指定したり、アクセスしたりする必要がないのです。 + +ファイル名: src/main.rs + ```rust -struct User { - username: String, - email: String, - sign_in_count: u64, - active: bool, -} +{{#rustdoc_include ../listings/ch05-using-structs-to-structure-related-data/listing-05-01/src/main.rs:here}} ``` 構造体を定義した後に使用するには、各フィールドに対して具体的な値を指定して構造体の*インスタンス*を生成します。 -インスタンスは、構造体名を記述し、`key: value`ペアを含む波かっこを付け加えることで生成します。 +インスタンスは、構造体名を記述し、*key: value*ペアを含む波かっこを付け加えることで生成します。 ここで、キーはフィールド名、値はそのフィールドに格納したいデータになります。フィールドは、 構造体で宣言した通りの順番に指定する必要はありません。換言すると、構造体定義とは、 型に対する一般的な雛形のようなものであり、インスタンスは、その雛形を特定のデータで埋め、その型の値を生成するわけです。 例えば、リスト5-2で示されたように特定のユーザを宣言することができます。 + + +ファイル名: src/main.rs + ```rust -# struct User { -# username: String, -# email: String, -# sign_in_count: u64, -# active: bool, -# } -# -let user1 = User { - email: String::from("someone@example.com"), - username: String::from("someusername123"), - active: true, - sign_in_count: 1, -}; +{{#rustdoc_include ../listings/ch05-using-structs-to-structure-related-data/listing-05-02/src/main.rs:here}} ``` -構造体から特定の値を得るには、ドット記法が使えます。このユーザのEメールアドレスだけが欲しいなら、 -この値を使いたかった場所全部で`user1.email`が使えます。インスタンスが可変であれば、 -ドット記法を使い特定のフィールドに代入することで値を変更できます。リスト5-3では、 -可変な`User`インスタンスの`email`フィールド値を変更する方法を示しています。 +構造体から特定の値を得るには、ドット記法を使います。例えば、 +このユーザのEメールアドレスにアクセスするには、`user1.email`を使います。 +インスタンスが可変であれば、ドット記法を使い特定のフィールドに代入することで値を変更できます。 +リスト5-3では、可変な`User`インスタンスの`email`フィールド値を変更する方法を示しています。 + + + +ファイル名: src/main.rs ```rust -# struct User { -# username: String, -# email: String, -# sign_in_count: u64, -# active: bool, -# } -# -let mut user1 = User { - email: String::from("someone@example.com"), - username: String::from("someusername123"), - active: true, - sign_in_count: 1, -}; - -user1.email = String::from("anotheremail@example.com"); +{{#rustdoc_include ../listings/ch05-using-structs-to-structure-related-data/listing-05-03/src/main.rs:here}} ``` + +ファイル名: src/main.rs + ```rust -# struct User { -# username: String, -# email: String, -# sign_in_count: u64, -# active: bool, -# } -# -fn build_user(email: String, username: String) -> User { - User { - email: email, - username: username, - active: true, - sign_in_count: 1, - } -} +{{#rustdoc_include ../listings/ch05-using-structs-to-structure-related-data/listing-05-04/src/main.rs:here}} ``` 構造体のフィールドと同じ名前を関数の引数にもつけることは筋が通っていますが、 @@ -182,47 +163,44 @@ would get even more annoying. Luckily, there's a convenient shorthand! 構造体にもっとフィールドがあれば、名前を繰り返すことはさらに煩わしくなるでしょう。 幸運なことに、便利な省略記法があります! + -### フィールドと変数が同名の時にフィールド初期化省略記法を使う + + +### フィールド初期化省略記法を使う 仮引数名と構造体のフィールド名がリスト5-4では、全く一緒なので、*フィールド初期化省略*記法を使って`build_user`を書き換えても、 -振る舞いは全く同じにしつつ、リスト5-5に示したように`email`と`username`を繰り返さなくてもよくなります。 +振る舞いは全く同じにしつつ、リスト5-5に示したように`username`と`email`を繰り返さなくてもよくなります。 + + + +ファイル名: src/main.rs ```rust -# struct User { -# username: String, -# email: String, -# sign_in_count: u64, -# active: bool, -# } -# -fn build_user(email: String, username: String) -> User { - User { - email, - username, - active: true, - sign_in_count: 1, - } -} +{{#rustdoc_include ../listings/ch05-using-structs-to-structure-related-data/listing-05-05/src/main.rs:here}} ``` -リスト5-5: `email`と`username`引数が構造体のフィールドと同名なので、 +リスト5-5: `username`と`email`引数が構造体のフィールドと同名なので、 フィールド初期化省略法を使用する`build_user`関数 ### 構造体更新記法で他のインスタンスからインスタンスを生成する -多くは前のインスタンスの値を使用しつつ、変更する箇所もある形で新しいインスタンスを生成できるとしばしば有用です。 +他のインスタンスからの値の多くの部分を含みつつ、一部を変更する形で新しいインスタンスを生成できるとしばしば有用です。 *構造体更新記法*でそうすることができます。 -まず、リスト5-6では、更新記法なしで`user2`に新しい`User`インスタンスを生成する方法を示しています。 -`email`と`username`には新しい値をセットしていますが、それ以外にはリスト5-2で生成した`user1`の値を使用しています。 +まず、リスト5-6では、更新記法なしで普通に`user2`に新しい`User`インスタンスを生成する方法を示しています。 +`email`には新しい値をセットしていますが、それ以外にはリスト5-2で生成した`user1`の値を使用しています。 + + + +ファイル名: src/main.rs ```rust -# struct User { -# username: String, -# email: String, -# sign_in_count: u64, -# active: bool, -# } -# -# let user1 = User { -# email: String::from("someone@example.com"), -# username: String::from("someusername123"), -# active: true, -# sign_in_count: 1, -# }; -# -let user2 = User { - email: String::from("another@example.com"), - username: String::from("anotherusername567"), - active: user1.active, - sign_in_count: user1.sign_in_count, -}; +{{#rustdoc_include ../listings/ch05-using-structs-to-structure-related-data/listing-05-06/src/main.rs:here}} ``` リスト5-6: `user1`の一部の値を使用しつつ、新しい`User`インスタンスを生成する @@ -300,203 +266,275 @@ explicitly set should have the same value as the fields in the given instance. 構造体更新記法を使用すると、リスト5-7に示したように、コード量を減らしつつ、同じ効果を達成できます。`..`という記法により、 明示的にセットされていない残りのフィールドが、与えられたインスタンスのフィールドと同じ値になるように指定します。 + + +ファイル名: src/main.rs + ```rust -# struct User { -# username: String, -# email: String, -# sign_in_count: u64, -# active: bool, -# } -# -# let user1 = User { -# email: String::from("someone@example.com"), -# username: String::from("someusername123"), -# active: true, -# sign_in_count: 1, -# }; -# -let user2 = User { - email: String::from("another@example.com"), - username: String::from("anotherusername567"), - ..user1 -}; +{{#rustdoc_include ../listings/ch05-using-structs-to-structure-related-data/listing-05-07/src/main.rs:here}} ``` -リスト5-7: 構造体更新記法を使用して、新しい`User`インスタンス用の値に新しい`email`と`username`をセットしつつ、 -残りの値は、`user1`変数のフィールド値を使う +リスト5-7: 構造体更新記法を使用して、新しい`User`インスタンス用の値に新しい`email`をセットしつつ、 +残りの値は`user1`を使う -リスト5-7のコードも、`email`と`username`については異なる値、`active`と`sign_in_count`フィールドについては、 +リスト5-7のコードも、`email`については`user1`とは異なる値、`username`、`active`と`sign_in_count`フィールドについては、 `user1`と同じ値になるインスタンスを`user2`に生成します。 +`..user1`は、残りのフィールドについては`user1`の対応するフィールドから値を取る、ということを示すために最後に来る必要がありますが、 +フィールドについては好きなだけ多く、構造体定義中のフィールドの順序とは無関係に好きな順で、値を指定してかまいません。 + + + +構造体更新記法は代入と同様に`=`を使います; これは、[「ムーブによる変数とデータの相互作用」][move]の節で見たのと同じように、 +データをムーブするからです。この例で言うと、`user2`を作成した後は、もう`user1`をそっくりそのまま使うことはできません。 +`user1`の`username`フィールド中の`String`が`user2`の中にムーブされてしまったからです。 +もし`user2`に、`email`と`username`のために新しい`String`値を与えていたなら、つまり、 +`user1`からは`active`と`sign_in_count`の値だけを使用していたなら、`user2`を作成した後も`user1`はまだ有効だったでしょう。 +`active`と`sign_in_count`はどちらも`Copy`トレイトを実装した型なので、[「スタックのみのデータ: コピー」][copy]節で議論した振る舞いが適用されるからです。 ### 異なる型を生成する名前付きフィールドのないタプル構造体を使用する -構造体名により追加の意味を含むものの、フィールドに紐づけられた名前がなく、むしろフィールドの型だけの*タプル構造体*と呼ばれる、 -タプルに似た構造体を定義することもできます。タプル構造体は、構造体名が提供する追加の意味は含むものの、 +Rustは、構造体名により追加の意味を含むものの、フィールドに紐づけられた名前がなく、むしろフィールドの型だけの*タプル構造体*と呼ばれる、 +タプルに似た構造体もサポートしています。タプル構造体は、構造体名が提供する追加の意味は含むものの、 フィールドに紐付けられた名前はありません; むしろ、フィールドの型だけが存在します。タプル構造体は、タプル全体に名前をつけ、 -そのタプルを他のタプルとは異なる型にしたい場合に有用ですが、普通の構造体のように各フィールド名を与えるのは、 -冗長、または余計になるでしょう。 +そのタプルを他のタプルとは異なる型にしたいが、普通の構造体のように各フィールド名を与えるのは、 +冗長、または余計という場合に有用です。 -タプル構造体を定義するには、`struct`キーワードの後に構造体名、さらにタプルに含まれる型を続けます。 -例えば、こちらは、`Color`と`Point`という2種類のタプル構造体の定義と使用法です: +タプル構造体を定義するには、`struct`キーワードの後に構造体名、さらにタプルに含まれる型を続けてください。 +例えば、ここでは、`Color`と`Point`という2種類のタプル構造体の定義して使用します: -```rust -struct Color(i32, i32, i32); -struct Point(i32, i32, i32); + + +ファイル名: src/main.rs -let black = Color(0, 0, 0); -let origin = Point(0, 0, 0); +```rust +{{#rustdoc_include ../listings/ch05-using-structs-to-structure-related-data/no-listing-01-tuple-structs/src/main.rs}} ``` `black`と`origin`の値は、違う型であることに注目してください。これらは、異なるタプル構造体のインスタンスだからですね。 定義された各構造体は、構造体内のフィールドが同じ型であっても、それ自身が独自の型になります。 例えば、`Color`型を引数に取る関数は、`Point`を引数に取ることはできません。たとえ、両者の型が、 3つの`i32`値からできていてもです。それ以外については、タプル構造体のインスタンスは、 -タプルと同じように振る舞います: 分配して個々の部品にしたり、`.`と添え字を使用して個々の値にアクセスするなどです。 +分配して個々の部品にしたり、`.`と添え字を使用して個々の値にアクセスできるという点で、タプルと似ています。 ### フィールドのないユニット(よう)構造体 -また、一切フィールドのない構造体を定義することもできます!これらは、`()`、ユニット型と似たような振る舞いをすることから、 +また、一切フィールドのない構造体を定義することもできます!これらは、`()`、 +[「タプル型」][tuples]の節で言及したユニット型と似たような振る舞いをすることから、 *ユニット様構造体*と呼ばれます。ユニット様構造体は、ある型にトレイトを実装するけれども、 型自体に保持させるデータは一切ない場面に有効になります。トレイトについては第10章で議論します。 +以下は、`AlwaysEqual`という名前のユニット様構造体を宣言し、インスタンス化する例です: - -error[E0106]: missing lifetime specifier +`AlwaysEqual`を定義するためには、`struct`キーワード、付けたい名前、そしてセミコロンを使います。 +波括弧や丸括弧は不要です! +次に、同じようにして、`subject`変数に`AlwaysEqual`のインスタンスを得られます: 波括弧や丸括弧を付けずに、定義した名前を使います。 +後でこの型の振る舞いを、おそらくはテスト目的で既知の結果を得るために、`AlwaysEqual`のすべてのインスタンスが常に他の任意の型と等価であるように実装することを想像してください。 +この挙動を実装するためにデータはまったく必要ないですね! +トレイトを定義して、ユニット様構造体も含めた任意の型にそれを実装する方法については10章で触れます。 -| -3 | email: &str, -| ^ expected lifetime parameter -``` + -In Chapter 10, we’ll discuss how to fix these errors so you can store -references in structs, but for now, we’ll fix errors like these using owned -types like `String` instead of references like `&str`. + > ### 構造体データの所有権 > > リスト5-1の`User`構造体定義において、`&str`文字列スライス型ではなく、所有権のある`String`型を使用しました。 -> これは意図的な選択です。というのも、この構造体のインスタンスには全データを所有してもらう必要があり、 +> これは意図的な選択です。というのも、この構造体の各インスタンスには自身の全データを所有してもらう必要があり、 > このデータは、構造体全体が有効な間はずっと有効である必要があるのです。 > > 構造体に、他の何かに所有されたデータへの参照を保持させることもできますが、 > そうするには*ライフタイム*という第10章で議論するRustの機能を使用しなければなりません。 > ライフタイムのおかげで構造体に参照されたデータが、構造体自体が有効な間、ずっと有効であることを保証してくれるのです。 -> ライフタイムを指定せずに構造体に参照を保持させようとしたとしましょう。以下の通りですが、これは動きません: +> 次のように、ライフタイムを指定せずに構造体に参照を保持させようとしたとしましょう。これは動きません: > > ファイル名: src/main.rs > -> ```rust,ignore +> ```rust,ignore,does_not_compile > struct User { +> active: bool, > username: &str, > email: &str, > sign_in_count: u64, -> active: bool, > } > > fn main() { > let user1 = User { -> email: "someone@example.com", -> username: "someusername123", > active: true, +> username: "someusername123", +> email: "someone@example.com", > sign_in_count: 1, > }; > } @@ -504,21 +542,58 @@ types like `String` instead of references like `&str`. > > コンパイラは、ライフタイム指定子が必要だと怒るでしょう: > -> ```text +> ```console +> $ cargo run +> Compiling structs v0.1.0 (file:///projects/structs) > error[E0106]: missing lifetime specifier > (エラー: ライフタイム指定子がありません) -> --> -> | -> 2 | username: &str, -> | ^ expected lifetime parameter -> (ライフタイム引数を予期しました) +> --> src/main.rs:3:15 +> | +> 3 | username: &str, +> | ^ expected named lifetime parameter +> | (ライフタイム引数を予期しました) +> | +> help: consider introducing a named lifetime parameter +> | +> 1 ~ struct User<'a> { +> 2 | active: bool, +> 3 ~ username: &'a str, +> | > > error[E0106]: missing lifetime specifier -> --> -> | -> 3 | email: &str, -> | ^ expected lifetime parameter +> --> src/main.rs:4:12 +> | +> 4 | email: &str, +> | ^ expected named lifetime parameter +> | +> help: consider introducing a named lifetime parameter +> | +> 1 ~ struct User<'a> { +> 2 | active: bool, +> 3 | username: &str, +> 4 ~ email: &'a str, +> | +> +> For more information about this error, try `rustc --explain E0106`. +> error: could not compile `structs` (bin "structs") due to 2 previous errors > ``` > > 第10章で、これらのエラーを解消して構造体に参照を保持する方法について議論しますが、 > 当面、今回のようなエラーは、`&str`のような参照の代わりに、`String`のような所有された型を使うことで修正します。 + + + + + +[tuples]: ch03-02-data-types.html#タプル型 +[move]: ch04-01-what-is-ownership.html#ムーブによる変数とデータの相互作用 +[copy]: ch04-01-what-is-ownership.html#スタックのみのデータ-コピー diff --git a/src/ch05-02-example-structs.md b/src/ch05-02-example-structs.md index 76cb30c15..cb2e7151f 100644 --- a/src/ch05-02-example-structs.md +++ b/src/ch05-02-example-structs.md @@ -6,8 +6,8 @@ 構造体を使用したくなる可能性のあるケースを理解するために、長方形の面積を求めるプログラムを書きましょう。 @@ -15,7 +15,7 @@ refactor the program until we’re using structs instead. @@ -31,20 +31,7 @@ Cargoで*rectangles*という新規バイナリプロジェクトを作成しま ファイル名: src/main.rs ```rust -fn main() { - let width1 = 30; - let height1 = 50; - - println!( - // 長方形の面積は、{}平方ピクセルです - "The area of the rectangle is {} square pixels.", - area(width1, height1) - ); -} - -fn area(width: u32, height: u32) -> u32 { - width * height -} +{{#rustdoc_include ../listings/ch05-using-structs-to-structure-related-data/listing-05-08/src/main.rs:all}} ``` - -### タプルでリファクタリングする - - -リスト5-8のコードはうまく動き、各寸法を与えて`area`関数を呼び出すことで長方形の面積を割り出しますが、 -改善点があります。幅と高さは、組み合わせると一つの長方形を表すので、相互に関係があるわけです。 +このコードは、各寸法を与えて`area`関数を呼び出すことで長方形の面積を割り出すことができますが、 +このコードはもっと簡潔で読みやすくすることができます。 -`area`関数は、1長方形の面積を求めるものと考えられますが、今書いた関数には、引数が2つあります。 -引数は関連性があるのに、このプログラム内のどこにもそのことは表現されていません。 +`area`関数は、1長方形の面積を求めるものと考えられますが、今書いた関数には引数が2つあり、 +そしてこのプログラム内のどこを見ても、これらの引数に関連性があることが明確になっていません。 幅と高さを一緒にグループ化する方が、より読みやすく、扱いやすくなるでしょう。 -それをする一つの方法については、第3章の「タプル型」節ですでに議論しました: タプルを使うのです。 +それをする一つの方法については、第3章の[「タプル型」][the-tuple-type]節ですでに議論しました: タプルを使うのです。 ある意味では、このプログラムはマシです。タプルのおかげで少し構造的になり、一引数を渡すだけになりました。 しかし別の意味では、このバージョンは明確性を失っています: タプルは要素に名前を付けないので、 -計算が不明瞭になったのです。なぜなら、タプルの一部に添え字アクセスする必要があるからです。 +タプルの要素に添え字でアクセスする必要があり、計算が不明瞭になったのです。 -面積計算で幅と高さを混在させるのなら問題はないのですが、長方形を画面に描画したいとなると、問題になるのです! +面積計算では幅と高さを混同しても問題ないですが、長方形を画面に描画したいとなると、これは問題になります! タプルの添え字`0`が`幅`で、添え字`1`が`高さ`であることを肝に銘じておかなければなりません。 -他人がこのコードをいじることになったら、このことを割り出し、同様に肝に銘じなければならないでしょう。 -容易く、このことを忘れたり、これらの値を混ぜこぜにしたりしてエラーを発生させてしまうでしょう。 -データの意味をコードに載せていないからです。 +もし他人がこのコードを使用することになったら、彼らがこのことを見つけ出して肝に銘じておくのはより難しくなるでしょう。 +データの意味をコードに載せていないことで、エラーを招きやすくなってしまいました。 -データのラベル付けで意味を付与するために構造体を使います。現在使用しているタプルを全体と一部に名前のあるデータ型に、 +データのラベル付けで意味を付与するために構造体を使います。現在使用しているタプルを全体と一部に名前のある構造体に、 変形することができます。そう、リスト5-10に示したように。 ここでは、構造体を定義し、`Rectangle`という名前にしています。波括弧の中で`width`と`height`というフィールドを定義し、 `u32`という型にしました。それから`main`内で`Rectangle`の特定のインスタンスを生成し、 -幅を30、高さを50にしました。 +幅を`30`、高さを`50`にしました。 `area`関数は、`Rectangle`インスタンスの`width`と`height`フィールドにアクセスしています。 +(借用された構造体インスタンスのフィールドにアクセスしても、そのフィールドの値はムーブされないことに注意してください。 +構造体の借用をよく使うのはこのためです) これで、`area`の関数シグニチャは、我々の意図をズバリ示すようになりました: `width`と`height`フィールドを使って、 `Rectangle`の面積を計算します。これにより、幅と高さが相互に関係していることが伝わり、 タプルの`0`や`1`という添え字を使うよりも、これらの値に説明的な名前を与えられるのです。プログラムの意図が明瞭になりました。 @@ -263,14 +218,15 @@ and `1`. This is a win for clarity. ### トレイトの導出で有用な機能を追加する -プログラムのデバッグをしている間に、`Rectangle`のインスタンスを出力し、フィールドの値を確認できると、 -素晴らしいわけです。リスト5-11では、以前の章のように、`println!`マクロを試しに使用しようとしていますが、動きません。 +プログラムのデバッグをしている間に、`Rectangle`のインスタンスを出力し、フィールドの値を確認できると便利でしょう。 +リスト5-11では、以前の章のように、[`println!`マクロ][println]を試しに使用しようとしています。 +ですが、これは動きません。 -このコードを走らせると、こんな感じのエラーが出ます: +このコードをコンパイルすると、こんな感じのエラーが出ます: + + ```text -error[E0277]: the trait bound `Rectangle: std::fmt::Display` is not satisfied -(エラー: トレイト境界`Rectangle: std::fmt::Display`が満たされていません) +{{#include ../listings/ch05-using-structs-to-structure-related-data/listing-05-11/output.txt:3:4}} ``` `println!`マクロには、様々な整形があり、標準では、波括弧は`Display`として知られる整形をするよう、 @@ -328,7 +275,7 @@ implementation of `Display`. 標準で`Display`を実装しています。というのも、`1`や他の基本型をユーザに見せる方法は一つしかないからです。 しかし構造体では、`println!`が出力を整形する方法は自明ではなくなります。出力方法がいくつもあるからです: カンマは必要なの?波かっこを出力する必要はある?全フィールドが見えるべき?この曖昧性のため、 -Rustは必要なものを推測しようとせず、構造体には`Display`実装が提供されないのです。 +Rustは必要なものを推測しようとせず、構造体は`println!`と`{}`プレースホルダで使用される`Display`実装を提供しないのです。 + ```text -`Rectangle` cannot be formatted with the default formatter; try using -`:?` instead if you are using a format string -(注釈: `Rectangle`は、デフォルト整形機では、整形できません; フォーマット文字列を使うのなら -代わりに`:?`を試してみてください) +{{#include ../listings/ch05-using-structs-to-structure-related-data/listing-05-11/output.txt:10:13}} ``` -変更してコードを走らせてください。なに!まだエラーが出ます: +変更してコードをコンパイルしてください。なに!まだエラーが出ます: + + ```text -error[E0277]: the trait bound `Rectangle: std::fmt::Debug` is not satisfied -(エラー: トレイト境界`Rectangle: std::fmt::Debug`が満たされていません) +{{#include ../listings/ch05-using-structs-to-structure-related-data/output-only-01-debug/output.txt:3:4}} ``` + ```text -`Rectangle` cannot be formatted using `:?`; if it is defined in your -crate, add `#[derive(Debug)]` or manually implement it -(注釈: `Rectangle`は`:?`を使って整形できません; 自分のクレートで定義しているのなら -`#[derive(Debug)]`を追加するか、手動で実装してください) +{{#include ../listings/ch05-using-structs-to-structure-related-data/output-only-01-debug/output.txt:10:13}} ``` *確かに*Rustにはデバッグ用の情報を出力する機能が備わっていますが、この機能を構造体で使えるようにするには、 -明示的な選択をしなければならないのです。そうするには、構造体定義の直前に`#[derive(Debug)]`という注釈を追加します。 +明示的な選択をしなければならないのです。そうするには、構造体定義の直前に`#[derive(Debug)]`という外部属性を追加します。 そう、リスト5-12で示されている通りです。 -リスト5-12: `Debug`トレイトを導出する注釈を追加し、 +リスト5-12: `Debug`トレイトを導出する属性を追加し、 `Rectangle`インスタンスをデバッグ用整形機で出力する 素晴らしい!最善の出力ではないものの、このインスタンスの全フィールドの値を出力しているので、 @@ -443,33 +379,116 @@ When we use the `{:#?}` style in the example, the output will look like this: そのような場合には、`println!`文字列中の`{:?}`の代わりに`{:#?}`を使うことができます。 この例で`{:#?}`というスタイルを使用したら、出力は以下のようになるでしょう: -```text -rect1 is Rectangle { - width: 30, - height: 50 -} +```console +{{#include ../listings/ch05-using-structs-to-structure-related-data/output-only-02-pretty-debug/output.txt}} ``` -Rustには、`derive`注釈で使えるトレイトが多く提供されており、独自の型に有用な振る舞いを追加することができます。 +`Debug`整形を使用して値を出力するためのもう一つの方法は、[`dbg!`マクロ][dbg]を使用することです。 +`dbg!`マクロは式の所有権を奪い(参照を取る`println!`とは対照的です)、その呼び出しが発生したコード内のファイル名と行番号とともに式を評価した結果を出力して、 +その値の所有権を返します。 + + + +> 注釈: 標準出力コンソールストリーム(`stdout`)に出力する`println!`とは異なり、`dbg!`マクロの呼び出しは標準エラーコンソールストリーム(`stderr`)に出力します。 +> `stderr`と`stdout`については[12章の「標準出力ではなく標準エラーにエラーメッセージを書き込む」節][err]でより詳しく触れます。 + + + +以下は、`width`フィールドに代入される値と、`rect1`の構造体全体の値に関心がある場合の例です: + +```rust +{{#rustdoc_include ../listings/ch05-using-structs-to-structure-related-data/no-listing-05-dbg-macro/src/main.rs}} +``` + + + +`dbg!`は式が評価された値の所有権を返すため、式`30 * scale`を囲うように`dbg!`を書くことで、`width`フィールドはここで`dbg!`の呼び出しをしなかった場合とまったく同じ値になります。 +`rect1`の所有権は奪ってほしくないので、次の`dbg!`呼び出しでは`rect1`への参照を使用しています。 +この例の出力は以下のようになります: + +```console +{{#include ../listings/ch05-using-structs-to-structure-related-data/no-listing-05-dbg-macro/output.txt}} +``` + + + +出力の前半は*src/main.rs*の10行目からの出力です。 +ここでは式`30 * scale`をデバッグ出力していて、その結果の値は`60`です(整数に実装されている`Debug`整形を使用して出力されています)。 +*src/main.rs*の14行目の`dbg!`呼び出しは`&rect1`の値を出力し、これは`Rectangle`構造体です。 +この出力は `Rectangle`型の pretty `Debug`整形を使用します。 +`dbg!`マクロは、コードが何をしているのか理解しようとするときには非常に有用です! + + + +`Debug`トレイトの他にも、Rustでは`derive`属性で使えるトレイトが多く提供されており、独自の型に有用な振る舞いを追加することができます。 そのようなトレイトとその振る舞いは、付録Cで一覧になっています。 これらのトレイトを独自の動作とともに実装する方法だけでなく、独自のトレイトを生成する方法については、第10章で解説します。 +また、`derive`の他にも多数の属性が存在します; さらなる情報については[Rust Referenceの“Attributes”節][attributes]を参照してください。 `area`関数は、非常に特殊です: 長方形の面積を算出するだけです。`Rectangle`構造体とこの動作をより緊密に結び付けられると、 役に立つでしょう。なぜなら、他のどんな型でもうまく動作しなくなるからです。 `area`関数を`Rectangle`型に定義された`area`*メソッド*に変形することで、 このコードをリファクタリングし続けられる方法について見ていきましょう。 + + + +[the-tuple-type]: ch03-02-data-types.html#タプル型 +[app-c]: appendix-03-derivable-traits.md +[println]: https://doc.rust-lang.org/std/macro.println.html +[dbg]: https://doc.rust-lang.org/std/macro.dbg.html +[err]: ch12-06-writing-to-stderr-instead-of-stdout.html +[attributes]: https://doc.rust-lang.org/reference/attributes.html diff --git a/src/ch05-03-method-syntax.md b/src/ch05-03-method-syntax.md index 9807a8656..5696d5243 100644 --- a/src/ch05-03-method-syntax.md +++ b/src/ch05-03-method-syntax.md @@ -5,19 +5,21 @@ ## メソッド記法 -*メソッド*は関数に似ています: `fn`キーワードと名前で宣言されるし、引数と返り値があるし、 -どこか別の場所で呼び出された時に実行されるコードを含みます。ところが、 -メソッドは構造体の文脈(あるいはenumかトレイトオブジェクトの。これらについては各々第6章と17章で解説します)で定義されるという点で、 -関数とは異なり、最初の引数は必ず`self`になり、これはメソッドが呼び出されている構造体インスタンスを表します。 +*メソッド*は関数に似ています: `fn`キーワードと名前を使って宣言され、引数と戻り値を持つことができ、 +メソッドがどこか別の場所で呼び出された時に実行されるコードを含みます。 +関数とは異なり、メソッドは構造体の文脈の中で定義されます(enumの文脈やトレイトオブジェクトの文脈の中でも定義されますが、これらについてはそれぞれ[6章][enums]と[17章][trait-objects]で解説します)。 +最初の引数は必ず`self`になり、これはメソッドが呼び出されている構造体インスタンスを表します。 - -`Rectangle`の文脈内で関数を定義するには、`impl`(implementation; 実装)ブロックを始めます。 +(implementation) block for `Rectangle`. Everything within this `impl` block +will be associated with the `Rectangle` type. Then we move the `area` function +within the `impl` curly brackets and change the first (and in this case, only) +parameter to be `self` in the signature and everywhere within the body. In +`main`, where we called the `area` function and passed `rect1` as an argument, +we can instead use *method syntax* to call the `area` method on our `Rectangle` +instance. The method syntax goes after an instance: we add a dot followed by +the method name, parentheses, and any arguments. +--> + +`Rectangle`の文脈内で関数を定義するには、`Rectangle`のための`impl`(implementation; 実装)ブロックを始めます。 +この`impl`ブロック内のあらゆる定義は`Rectangle`に関連付けられたものとなるでしょう。 それから`area`関数を`impl`の波かっこ内に移動させ、最初の(今回は唯一の)引数をシグニチャ内と本体内全てで`self`に変えます。 `area`関数を呼び出し、`rect1`を引数として渡す`main`では、代替としてメソッド記法を使用して、 `Rectangle`インスタンスの`area`メソッドを呼び出せます。メソッド記法は、インスタンスの後に続きます: ドット、メソッド名、かっこ、そして引数と続くわけです。 `area`のシグニチャでは、`rectangle: &Rectangle`の代わりに`&self`を使用しています。 -というのも、コンパイラは、このメソッドが`impl Rectangle`という文脈内に存在するために、 -`self`の型が`Rectangle`であると把握しているからです。`&Rectangle`と同様に、 -`self`の直前に`&`を使用していることに注意してください。メソッドは、`self`の所有権を奪ったり、 -ここでしているように不変で`self`を借用したり、可変で`self`を借用したりできるのです。 +`&self`は実際のところ`self: &Self`の省略記法です。 +`impl`ブロック内では、型`Self`はその`impl`ブロックの対象である型に対するエイリアスとして使えます。 +メソッドはその第1引数として`self`という名前の`Self`型引数を持たなくてはならないので、 +Rust処理系は第1引数の位置では`self`という名前のみに省略することを許可しているのです。 +ただし、`self`省略記法の前の`&`は依然として必要であることに注意してください。 +これは、`rectangle: &Rectangle`と書いたときと同様に、このメソッドが`Self`のインスタンスを借用することを示しています。 +メソッドは、`self`の所有権を奪ったり、ここでしているように不変で`self`を借用したり、可変で`self`を借用したりできるのです。 他の引数と全く同じですね。 ここで`&self`を選んでいるのは、関数バージョンで`&Rectangle`を使用していたのと同様の理由です: @@ -121,66 +113,118 @@ to prevent the caller from using the original instance after the transformation. メソッドが`self`を何か別のものに変形し、変形後に呼び出し元が元のインスタンスを使用できないようにしたい場合に使用されます。 -関数の代替としてメソッドを使う主な利点は、メソッド記法を使用して全メソッドのシグニチャで`self`の型を繰り返す必要がなくなる以外だと、 -体系化です。コードの将来的な利用者に`Rectangle`の機能を提供しているライブラリ内の各所でその機能を探させるのではなく、 +関数の代替としてメソッドを使う主な理由は、メソッド記法を使用できるようにすることと、 +すべてのメソッドのシグニチャでいちいち`self`の型を繰り返す必要がなくなることに加えて、体系化のためです。 +コードの将来的な利用者に、私たちが提供するライブラリ内のあらゆる箇所から`Rectangle`の機能を探させるのではなく、 この型のインスタンスでできることを一つの`impl`ブロックにまとめあげています。 - -Here’s how it works: when you call a method with `object.something()`, Rust -automatically adds in `&`, `&mut`, or `*` so `object` matches the signature of -the method. In other words, the following are the same: +ファイル名: src/main.rs ```rust -# #[derive(Debug,Copy,Clone)] -# struct Point { -# x: f64, -# y: f64, -# } -# -# impl Point { -# fn distance(&self, other: &Point) -> f64 { -# let x_squared = f64::powi(other.x - self.x, 2); -# let y_squared = f64::powi(other.y - self.y, 2); -# -# f64::sqrt(x_squared + y_squared) -# } -# } -# let p1 = Point { x: 0.0, y: 0.0 }; -# let p2 = Point { x: 5.0, y: 6.5 }; -p1.distance(&p2); -(&p1).distance(&p2); +{{#rustdoc_include ../listings/ch05-using-structs-to-structure-related-data/no-listing-06-method-field-interaction/src/main.rs:here}} ``` -The first one looks much cleaner. This automatic referencing behavior works -because methods have a clear receiver—the type of `self`. Given the receiver -and name of a method, Rust can figure out definitively whether the method is -reading (`&self`), mutating (`&mut self`), or consuming (`self`). The fact -that Rust makes borrowing implicit for method receivers is a big part of -making ownership ergonomic in practice. + + +ここで`width`メソッドは、インスタンスの`width`フィールドの値が`0`より大きい場合に`true`を返し、値が`0`の場合は`false`を返すようにしています: +同名のメソッド内でも、フィールドをあらゆる目的のために使用することができます。 +`main`では`rect1.width`の後に丸かっこを続けているので、処理系はメソッドの`width`を意図したものと認識します。 +丸かっこを使わなければ、処理系はフィールドの`width`を意図したものと認識します。 + + + +フィールドの値を返すだけで他に何もしないメソッドに、フィールドと同じ名前を与えることが、常にではありませんが、よくあります。 +このようなメソッドは*ゲッター*と呼ばれます。 +他のいくつかの言語で行われているような自動的なゲッターの実装を、Rustが構造体フィールドに対して行うことはありません。 +フィールドを非公開にしながらメソッドは公開するということができ、そうすることで、型の公開APIの一部としてフィールドへの読み込み専用アクセスを提供できるので、ゲッターは有用です。 +公開と非公開とはなにか、そしてフィールドやメソッドを公開または非公開として指定する方法については、[7章][public]で議論します。 + + + + > ### `->`演算子はどこに行ったの? @@ -198,6 +242,7 @@ making ownership ergonomic in practice. > コンパイラは`object`がメソッドのシグニチャと合致するように、自動で`&`か`&mut`、`*`を付与するのです。 > 要するに、以下のコードは同じものです: > +> > ```rust > # #[derive(Debug,Copy,Clone)] > # struct Point { @@ -232,17 +277,16 @@ making ownership ergonomic in practice. -`Rectangle`構造体に2番目のメソッドを実装して、メソッドを使う鍛錬をしましょう。今回は、`Rectangle`のインスタンスに、 -別の`Rectangle`のインスタンスを取らせ、2番目の`Rectangle`が`self`に完全にはめ込まれたら、`true`を返すようにしたいのです; -そうでなければ、`false`を返すべきです。つまり、一旦`can_hold`メソッドを定義したら、 -リスト5-14のようなプログラムを書けるようになりたいのです。 +`Rectangle`構造体に2番目のメソッドを実装して、メソッドを使う練習をしましょう。 +今回は`Rectangle`のインスタンスに別の`Rectangle`のインスタンスを受け取らせ、2番目の`Rectangle`が`self`(1番目の`Rectangle`)に完全に収まるなら、`true`を返すようにしたいとしましょう; +そうでなければ、`false`を返すべきです。つまり、一旦`can_hold`メソッドを定義したら、リスト5-14のようなプログラムを書けるようにしたいのです。 -そして、予期される出力は以下のようになります。なぜなら、`rect2`の各寸法は`rect1`よりも小さいものの、 +予期される出力は以下のようになります。なぜなら、`rect2`の各寸法は`rect1`よりも小さいものの、 `rect3`は`rect1`より幅が広いからです: ```text @@ -294,7 +330,7 @@ read `rect2` (rather than write, which would mean we’d need a mutable borrow), and we want `main` to retain ownership of `rect2` so we can use it again after calling the `can_hold` method. The return value of `can_hold` will be a Boolean, and the implementation will check whether the width and height of -`self` are both greater than the width and height of the other `Rectangle`, +`self` are greater than the width and height of the other `Rectangle`, respectively. Let’s add the new `can_hold` method to the `impl` block from Listing 5-13, shown in Listing 5-15. --> @@ -316,21 +352,7 @@ Listing 5-13, shown in Listing 5-15. ファイル名: src/main.rs ```rust -# #[derive(Debug)] -# struct Rectangle { -# width: u32, -# height: u32, -# } -# -impl Rectangle { - fn area(&self) -> u32 { - self.width * self.height - } - - fn can_hold(&self, other: &Rectangle) -> bool { - self.width > other.width && self.height > other.height - } -} +{{#rustdoc_include ../listings/ch05-using-structs-to-structure-related-data/listing-05-15/src/main.rs:here}} ``` -`impl`ブロックの別の有益な機能は、`impl`ブロック内に`self`を引数に取ら*ない*関数を定義できることです。 -これは、構造体に関連付けられているので、*関連関数*と呼ばれます。それでも、関連関数は関数であり、メソッドではありません。 -というのも、対象となる構造体のインスタンスが存在しないからです。もう`String::from`という関連関数を使用したことがありますね。 +`impl`ブロック内で定義されたすべての関数は、`impl`の後に書かれた型に関連付けられているので、*関連関数*と呼ばれます。 +対象の型のインスタンスを必要としないために、`self`を第1引数として持たない(つまりメソッドではない)関連関数を定義することもできます。 +このような関数は、すでにひとつ使用しています: `String::from`関数は`String`型の上に定義された関数です。 -関連関数は、構造体の新規インスタンスを返すコンストラクタによく使用されます。例えば、一つの寸法を引数に取り、 -長さと幅両方に使用する関連関数を提供することができ、その結果、同じ値を2回指定する必要なく、 -正方形の`Rectangle`を生成しやすくすることができます。 +メソッドでない関連関数は、構造体の新規インスタンスを返すコンストラクタによく使用されます。 +これらにはしばしば`new`という名前が付けられますが、`new`は特別な名前ではなく、言語に組み込まれたものでもありません。 +例えば、一つの寸法を引数に取り、それを高さと幅の両方として使用する関連関数`square`を提供してもよいでしょう。 +そうすれば同じ値を2回指定する必要なく、正方形の`Rectangle`を生成しやすくすることができます。 + +戻り値型と関数本体内のの`Self` キーワードは`impl` キーワードの後に現れる型に対するエイリアスで、今回の場合は`Rectangle`です。 + この関連関数を呼び出すために、構造体名と一緒に`::`記法を使用します; 一例は`let sq = Rectangle::square(3);`です。 この関数は、構造体によって名前空間分けされています: `::`という記法は、関連関数とモジュールによって作り出される名前空間両方に使用されます。 -モジュールについては第7章で議論します。 +モジュールについては[第7章][modules]で議論します。 各構造体には、複数の`impl`ブロックを存在させることができます。例えば、リスト5-15はリスト5-16に示したコードと等価で、 リスト5-16では、各メソッドごとに`impl`ブロックを用意しています。 ```rust -# #[derive(Debug)] -# struct Rectangle { -# width: u32, -# height: u32, -# } -# -impl Rectangle { - fn area(&self) -> u32 { - self.width * self.height - } -} - -impl Rectangle { - fn can_hold(&self, other: &Rectangle) -> bool { - self.width > other.width && self.height > other.height - } -} +{{#rustdoc_include ../listings/ch05-using-structs-to-structure-related-data/listing-05-16/src/main.rs:here}} ``` @@ -472,23 +480,34 @@ useful in Chapter 10, where we discuss generic types and traits. ## まとめ -構造体により、自分の領域で意味のある独自の型を作成することができます。構造体を使用することで、 +構造体により、ドメインにとって意味のある独自の型を作成することができます。構造体を使用することで、 関連のあるデータ片を相互に結合させたままにし、各部品に名前を付け、コードを明確にすることができます。 -メソッドにより、構造体のインスタンスが行う動作を指定することができ、関連関数により、 -構造体に特有の機能をインスタンスを利用することなく、名前空間分けすることができます。 +`impl`ブロック内では型に関連付けられた関数を定義することができ、メソッドは構造体のインスタンスが持つ振る舞いを規定することができる関連関数の一種です。 しかし、構造体だけが独自の型を作成する手段ではありません: Rustのenum機能に目を向けて、 別の道具を道具箱に追加しましょう。 + + + +[enums]: ch06-00-enums.html +[trait-objects]: ch17-02-trait-objects.md +[public]: ch07-03-paths-for-referring-to-an-item-in-the-module-tree.html#パスをpubキーワードで公開する +[modules]: ch07-02-defining-modules-to-control-scope-and-privacy.html From 0de9bcf18d3ea5bfae055a979c08ee6af66614e8 Mon Sep 17 00:00:00 2001 From: shinmili Date: Sun, 26 May 2024 12:58:03 +0900 Subject: [PATCH 07/10] =?UTF-8?q?ch06=20Enum=E3=81=A8=E3=83=91=E3=82=BF?= =?UTF-8?q?=E3=83=BC=E3=83=B3=E3=83=9E=E3=83=83=E3=83=81=E3=83=B3=E3=82=B0?= =?UTF-8?q?=E3=81=AE=E5=92=8C=E8=A8=B3=E3=82=92=E6=9C=80=E6=96=B0=E7=89=88?= =?UTF-8?q?=E3=81=AB=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit rust-lang/book@19c40bfd2d57641d962f3119a1c343355f1b3c5e --- .../listing-06-01/Cargo.toml | 3 +- .../listing-06-02/Cargo.toml | 3 +- .../listing-06-03/Cargo.toml | 3 +- .../listing-06-04/Cargo.toml | 3 +- .../listing-06-04/src/main.rs | 4 +- .../listing-06-05/Cargo.toml | 3 +- .../listing-06-06/Cargo.toml | 3 +- .../listing-06-06/src/main.rs | 6 +- .../no-listing-01-defining-enums/Cargo.toml | 3 +- .../no-listing-02-enum-with-data/Cargo.toml | 3 +- .../Cargo.toml | 3 +- .../Cargo.toml | 3 +- .../src/main.rs | 6 +- .../no-listing-05-methods-on-enums/Cargo.toml | 3 +- .../src/main.rs | 2 +- .../no-listing-06-option-examples/Cargo.toml | 3 +- .../no-listing-06-option-examples/src/main.rs | 2 +- .../Cargo.toml | 3 +- .../output.txt | 21 +- .../Cargo.toml | 3 +- .../Cargo.toml | 3 +- .../Cargo.toml | 3 +- .../output.txt | 21 +- .../src/main.rs | 12 - .../no-listing-12-if-let/Cargo.toml | 3 +- .../no-listing-12-if-let/src/main.rs | 6 +- .../Cargo.toml | 3 +- .../src/main.rs | 2 +- .../Cargo.toml | 3 +- .../src/main.rs | 2 +- .../Cargo.lock | 0 .../Cargo.toml | 3 +- .../src/main.rs | 14 + .../Cargo.lock | 6 + .../Cargo.toml | 6 + .../src/main.rs | 14 + .../no-listing-17-underscore-unit/Cargo.lock | 6 + .../no-listing-17-underscore-unit/Cargo.toml | 6 + .../no-listing-17-underscore-unit/src/main.rs | 13 + src/SUMMARY.md | 4 +- src/ch06-00-enums.md | 19 +- src/ch06-01-defining-an-enum.md | 398 +++++++---------- src/ch06-02-match.md | 411 +++++++++--------- src/ch06-03-if-let.md | 95 ++-- 44 files changed, 526 insertions(+), 610 deletions(-) delete mode 100644 listings/ch06-enums-and-pattern-matching/no-listing-11-underscore-placeholder/src/main.rs rename listings/ch06-enums-and-pattern-matching/{no-listing-11-underscore-placeholder => no-listing-15-binding-catchall}/Cargo.lock (100%) rename listings/ch06-enums-and-pattern-matching/{no-listing-11-underscore-placeholder => no-listing-15-binding-catchall}/Cargo.toml (50%) create mode 100644 listings/ch06-enums-and-pattern-matching/no-listing-15-binding-catchall/src/main.rs create mode 100644 listings/ch06-enums-and-pattern-matching/no-listing-16-underscore-catchall/Cargo.lock create mode 100644 listings/ch06-enums-and-pattern-matching/no-listing-16-underscore-catchall/Cargo.toml create mode 100644 listings/ch06-enums-and-pattern-matching/no-listing-16-underscore-catchall/src/main.rs create mode 100644 listings/ch06-enums-and-pattern-matching/no-listing-17-underscore-unit/Cargo.lock create mode 100644 listings/ch06-enums-and-pattern-matching/no-listing-17-underscore-unit/Cargo.toml create mode 100644 listings/ch06-enums-and-pattern-matching/no-listing-17-underscore-unit/src/main.rs diff --git a/listings/ch06-enums-and-pattern-matching/listing-06-01/Cargo.toml b/listings/ch06-enums-and-pattern-matching/listing-06-01/Cargo.toml index 04988d1ff..e959295f9 100644 --- a/listings/ch06-enums-and-pattern-matching/listing-06-01/Cargo.toml +++ b/listings/ch06-enums-and-pattern-matching/listing-06-01/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "enums" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch06-enums-and-pattern-matching/listing-06-02/Cargo.toml b/listings/ch06-enums-and-pattern-matching/listing-06-02/Cargo.toml index 04988d1ff..e959295f9 100644 --- a/listings/ch06-enums-and-pattern-matching/listing-06-02/Cargo.toml +++ b/listings/ch06-enums-and-pattern-matching/listing-06-02/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "enums" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch06-enums-and-pattern-matching/listing-06-03/Cargo.toml b/listings/ch06-enums-and-pattern-matching/listing-06-03/Cargo.toml index 04988d1ff..e959295f9 100644 --- a/listings/ch06-enums-and-pattern-matching/listing-06-03/Cargo.toml +++ b/listings/ch06-enums-and-pattern-matching/listing-06-03/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "enums" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch06-enums-and-pattern-matching/listing-06-04/Cargo.toml b/listings/ch06-enums-and-pattern-matching/listing-06-04/Cargo.toml index 04988d1ff..e959295f9 100644 --- a/listings/ch06-enums-and-pattern-matching/listing-06-04/Cargo.toml +++ b/listings/ch06-enums-and-pattern-matching/listing-06-04/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "enums" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch06-enums-and-pattern-matching/listing-06-04/src/main.rs b/listings/ch06-enums-and-pattern-matching/listing-06-04/src/main.rs index 3ba384fba..ac134534e 100644 --- a/listings/ch06-enums-and-pattern-matching/listing-06-04/src/main.rs +++ b/listings/ch06-enums-and-pattern-matching/listing-06-04/src/main.rs @@ -1,9 +1,9 @@ // ANCHOR: here -#[derive(Debug)] // so we can inspect the state in a minute +#[derive(Debug)] // すぐに州を検査できるように enum UsState { Alabama, Alaska, - // --snip-- + // --略-- } enum Coin { diff --git a/listings/ch06-enums-and-pattern-matching/listing-06-05/Cargo.toml b/listings/ch06-enums-and-pattern-matching/listing-06-05/Cargo.toml index 04988d1ff..e959295f9 100644 --- a/listings/ch06-enums-and-pattern-matching/listing-06-05/Cargo.toml +++ b/listings/ch06-enums-and-pattern-matching/listing-06-05/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "enums" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch06-enums-and-pattern-matching/listing-06-06/Cargo.toml b/listings/ch06-enums-and-pattern-matching/listing-06-06/Cargo.toml index 04988d1ff..e959295f9 100644 --- a/listings/ch06-enums-and-pattern-matching/listing-06-06/Cargo.toml +++ b/listings/ch06-enums-and-pattern-matching/listing-06-06/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "enums" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch06-enums-and-pattern-matching/listing-06-06/src/main.rs b/listings/ch06-enums-and-pattern-matching/listing-06-06/src/main.rs index 222d54552..dc2bffb91 100644 --- a/listings/ch06-enums-and-pattern-matching/listing-06-06/src/main.rs +++ b/listings/ch06-enums-and-pattern-matching/listing-06-06/src/main.rs @@ -1,8 +1,8 @@ fn main() { // ANCHOR: here - let some_u8_value = Some(0u8); - match some_u8_value { - Some(3) => println!("three"), + let config_max = Some(3u8); + match config_max { + Some(max) => println!("The maximum is configured to be {}", max), _ => (), } // ANCHOR_END: here diff --git a/listings/ch06-enums-and-pattern-matching/no-listing-01-defining-enums/Cargo.toml b/listings/ch06-enums-and-pattern-matching/no-listing-01-defining-enums/Cargo.toml index 04988d1ff..e959295f9 100644 --- a/listings/ch06-enums-and-pattern-matching/no-listing-01-defining-enums/Cargo.toml +++ b/listings/ch06-enums-and-pattern-matching/no-listing-01-defining-enums/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "enums" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch06-enums-and-pattern-matching/no-listing-02-enum-with-data/Cargo.toml b/listings/ch06-enums-and-pattern-matching/no-listing-02-enum-with-data/Cargo.toml index 04988d1ff..e959295f9 100644 --- a/listings/ch06-enums-and-pattern-matching/no-listing-02-enum-with-data/Cargo.toml +++ b/listings/ch06-enums-and-pattern-matching/no-listing-02-enum-with-data/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "enums" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch06-enums-and-pattern-matching/no-listing-03-variants-with-different-data/Cargo.toml b/listings/ch06-enums-and-pattern-matching/no-listing-03-variants-with-different-data/Cargo.toml index 04988d1ff..e959295f9 100644 --- a/listings/ch06-enums-and-pattern-matching/no-listing-03-variants-with-different-data/Cargo.toml +++ b/listings/ch06-enums-and-pattern-matching/no-listing-03-variants-with-different-data/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "enums" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch06-enums-and-pattern-matching/no-listing-04-structs-similar-to-message-enum/Cargo.toml b/listings/ch06-enums-and-pattern-matching/no-listing-04-structs-similar-to-message-enum/Cargo.toml index 04988d1ff..e959295f9 100644 --- a/listings/ch06-enums-and-pattern-matching/no-listing-04-structs-similar-to-message-enum/Cargo.toml +++ b/listings/ch06-enums-and-pattern-matching/no-listing-04-structs-similar-to-message-enum/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "enums" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch06-enums-and-pattern-matching/no-listing-04-structs-similar-to-message-enum/src/main.rs b/listings/ch06-enums-and-pattern-matching/no-listing-04-structs-similar-to-message-enum/src/main.rs index df451be8b..182221bf0 100644 --- a/listings/ch06-enums-and-pattern-matching/no-listing-04-structs-similar-to-message-enum/src/main.rs +++ b/listings/ch06-enums-and-pattern-matching/no-listing-04-structs-similar-to-message-enum/src/main.rs @@ -1,11 +1,11 @@ // ANCHOR: here -struct QuitMessage; // unit struct +struct QuitMessage; // ユニット構造体 struct MoveMessage { x: i32, y: i32, } -struct WriteMessage(String); // tuple struct -struct ChangeColorMessage(i32, i32, i32); // tuple struct +struct WriteMessage(String); // タプル構造体 +struct ChangeColorMessage(i32, i32, i32); // タプル構造体 // ANCHOR_END: here fn main() {} diff --git a/listings/ch06-enums-and-pattern-matching/no-listing-05-methods-on-enums/Cargo.toml b/listings/ch06-enums-and-pattern-matching/no-listing-05-methods-on-enums/Cargo.toml index 04988d1ff..e959295f9 100644 --- a/listings/ch06-enums-and-pattern-matching/no-listing-05-methods-on-enums/Cargo.toml +++ b/listings/ch06-enums-and-pattern-matching/no-listing-05-methods-on-enums/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "enums" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch06-enums-and-pattern-matching/no-listing-05-methods-on-enums/src/main.rs b/listings/ch06-enums-and-pattern-matching/no-listing-05-methods-on-enums/src/main.rs index 66e0b6da1..2395b0e6d 100644 --- a/listings/ch06-enums-and-pattern-matching/no-listing-05-methods-on-enums/src/main.rs +++ b/listings/ch06-enums-and-pattern-matching/no-listing-05-methods-on-enums/src/main.rs @@ -9,7 +9,7 @@ fn main() { // ANCHOR: here impl Message { fn call(&self) { - // method body would be defined here + // メソッド本体はここで定義されます } } diff --git a/listings/ch06-enums-and-pattern-matching/no-listing-06-option-examples/Cargo.toml b/listings/ch06-enums-and-pattern-matching/no-listing-06-option-examples/Cargo.toml index 04988d1ff..e959295f9 100644 --- a/listings/ch06-enums-and-pattern-matching/no-listing-06-option-examples/Cargo.toml +++ b/listings/ch06-enums-and-pattern-matching/no-listing-06-option-examples/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "enums" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch06-enums-and-pattern-matching/no-listing-06-option-examples/src/main.rs b/listings/ch06-enums-and-pattern-matching/no-listing-06-option-examples/src/main.rs index 9de5791b4..be552bfa5 100644 --- a/listings/ch06-enums-and-pattern-matching/no-listing-06-option-examples/src/main.rs +++ b/listings/ch06-enums-and-pattern-matching/no-listing-06-option-examples/src/main.rs @@ -1,7 +1,7 @@ fn main() { // ANCHOR: here let some_number = Some(5); - let some_string = Some("a string"); + let some_char = Some('e'); let absent_number: Option = None; // ANCHOR_END: here diff --git a/listings/ch06-enums-and-pattern-matching/no-listing-07-cant-use-option-directly/Cargo.toml b/listings/ch06-enums-and-pattern-matching/no-listing-07-cant-use-option-directly/Cargo.toml index 04988d1ff..e959295f9 100644 --- a/listings/ch06-enums-and-pattern-matching/no-listing-07-cant-use-option-directly/Cargo.toml +++ b/listings/ch06-enums-and-pattern-matching/no-listing-07-cant-use-option-directly/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "enums" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch06-enums-and-pattern-matching/no-listing-07-cant-use-option-directly/output.txt b/listings/ch06-enums-and-pattern-matching/no-listing-07-cant-use-option-directly/output.txt index d3092d9fb..2f0596aaf 100644 --- a/listings/ch06-enums-and-pattern-matching/no-listing-07-cant-use-option-directly/output.txt +++ b/listings/ch06-enums-and-pattern-matching/no-listing-07-cant-use-option-directly/output.txt @@ -1,16 +1,21 @@ $ cargo run Compiling enums v0.1.0 (file:///projects/enums) -error[E0277]: cannot add `std::option::Option` to `i8` +error[E0277]: cannot add `Option` to `i8` +(エラー: `Option`を`i8`に足すことはできません) --> src/main.rs:5:17 | 5 | let sum = x + y; - | ^ no implementation for `i8 + std::option::Option` + | ^ no implementation for `i8 + Option` + (`i8 + `Option`のための実装がありません) | - = help: the trait `std::ops::Add>` is not implemented for `i8` - -error: aborting due to previous error + = help: the trait `Add>` is not implemented for `i8` + (ヘルプ: トレイト`Add`が`i8`に対して実装されていません) + = help: the following other types implement trait `Add`: + (ヘルプ: 以下の型であればトレイト`Add`を実装しています:) + + > + <&'a i8 as Add> + <&i8 as Add<&i8>> For more information about this error, try `rustc --explain E0277`. -error: could not compile `enums`. - -To learn more, run the command again with --verbose. +error: could not compile `enums` (bin "enums") due to 1 previous error diff --git a/listings/ch06-enums-and-pattern-matching/no-listing-08-match-arm-multiple-lines/Cargo.toml b/listings/ch06-enums-and-pattern-matching/no-listing-08-match-arm-multiple-lines/Cargo.toml index 04988d1ff..e959295f9 100644 --- a/listings/ch06-enums-and-pattern-matching/no-listing-08-match-arm-multiple-lines/Cargo.toml +++ b/listings/ch06-enums-and-pattern-matching/no-listing-08-match-arm-multiple-lines/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "enums" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch06-enums-and-pattern-matching/no-listing-09-variable-in-pattern/Cargo.toml b/listings/ch06-enums-and-pattern-matching/no-listing-09-variable-in-pattern/Cargo.toml index 04988d1ff..e959295f9 100644 --- a/listings/ch06-enums-and-pattern-matching/no-listing-09-variable-in-pattern/Cargo.toml +++ b/listings/ch06-enums-and-pattern-matching/no-listing-09-variable-in-pattern/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "enums" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch06-enums-and-pattern-matching/no-listing-10-non-exhaustive-match/Cargo.toml b/listings/ch06-enums-and-pattern-matching/no-listing-10-non-exhaustive-match/Cargo.toml index 04988d1ff..e959295f9 100644 --- a/listings/ch06-enums-and-pattern-matching/no-listing-10-non-exhaustive-match/Cargo.toml +++ b/listings/ch06-enums-and-pattern-matching/no-listing-10-non-exhaustive-match/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "enums" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch06-enums-and-pattern-matching/no-listing-10-non-exhaustive-match/output.txt b/listings/ch06-enums-and-pattern-matching/no-listing-10-non-exhaustive-match/output.txt index da9e9d9bf..fa6e843fa 100644 --- a/listings/ch06-enums-and-pattern-matching/no-listing-10-non-exhaustive-match/output.txt +++ b/listings/ch06-enums-and-pattern-matching/no-listing-10-non-exhaustive-match/output.txt @@ -1,16 +1,25 @@ $ cargo run Compiling enums v0.1.0 (file:///projects/enums) error[E0004]: non-exhaustive patterns: `None` not covered +(エラー: 包括的でないパターン: `None`が網羅されていません) --> src/main.rs:3:15 | 3 | match x { | ^ pattern `None` not covered + (パターン`None`が網羅されていません) + | +note: `Option` defined here + --> /rustc/07dca489ac2d933c78d3c5158e3f43beefeb02ce/library/core/src/option.rs:570:1 + ::: /rustc/07dca489ac2d933c78d3c5158e3f43beefeb02ce/library/core/src/option.rs:574:5 + | + = note: not covered + = note: the matched value is of type `Option` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown +(ヘルプ: ワイルドカードパターンか、以下に示すように明示的なパターンを持つアームを追加することで、すべての可能な場合が確実に処理されるようにしてください) + | +4 ~ Some(i) => Some(i + 1), +5 ~ None => todo!(), | - = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms - -error: aborting due to previous error For more information about this error, try `rustc --explain E0004`. -error: could not compile `enums`. - -To learn more, run the command again with --verbose. +error: could not compile `enums` (bin "enums") due to 1 previous error diff --git a/listings/ch06-enums-and-pattern-matching/no-listing-11-underscore-placeholder/src/main.rs b/listings/ch06-enums-and-pattern-matching/no-listing-11-underscore-placeholder/src/main.rs deleted file mode 100644 index 6fc8ab058..000000000 --- a/listings/ch06-enums-and-pattern-matching/no-listing-11-underscore-placeholder/src/main.rs +++ /dev/null @@ -1,12 +0,0 @@ -fn main() { - // ANCHOR: here - let some_u8_value = 0u8; - match some_u8_value { - 1 => println!("one"), - 3 => println!("three"), - 5 => println!("five"), - 7 => println!("seven"), - _ => (), - } - // ANCHOR_END: here -} diff --git a/listings/ch06-enums-and-pattern-matching/no-listing-12-if-let/Cargo.toml b/listings/ch06-enums-and-pattern-matching/no-listing-12-if-let/Cargo.toml index 04988d1ff..e959295f9 100644 --- a/listings/ch06-enums-and-pattern-matching/no-listing-12-if-let/Cargo.toml +++ b/listings/ch06-enums-and-pattern-matching/no-listing-12-if-let/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "enums" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch06-enums-and-pattern-matching/no-listing-12-if-let/src/main.rs b/listings/ch06-enums-and-pattern-matching/no-listing-12-if-let/src/main.rs index fb6578cf6..735086d4e 100644 --- a/listings/ch06-enums-and-pattern-matching/no-listing-12-if-let/src/main.rs +++ b/listings/ch06-enums-and-pattern-matching/no-listing-12-if-let/src/main.rs @@ -1,8 +1,8 @@ fn main() { - let some_u8_value = Some(0u8); // ANCHOR: here - if let Some(3) = some_u8_value { - println!("three"); + let config_max = Some(3u8); + if let Some(max) = config_max { + println!("The maximum is configured to be {}", max); } // ANCHOR_END: here } diff --git a/listings/ch06-enums-and-pattern-matching/no-listing-13-count-and-announce-match/Cargo.toml b/listings/ch06-enums-and-pattern-matching/no-listing-13-count-and-announce-match/Cargo.toml index 04988d1ff..e959295f9 100644 --- a/listings/ch06-enums-and-pattern-matching/no-listing-13-count-and-announce-match/Cargo.toml +++ b/listings/ch06-enums-and-pattern-matching/no-listing-13-count-and-announce-match/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "enums" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch06-enums-and-pattern-matching/no-listing-13-count-and-announce-match/src/main.rs b/listings/ch06-enums-and-pattern-matching/no-listing-13-count-and-announce-match/src/main.rs index 12c4c0fec..ac721ba43 100644 --- a/listings/ch06-enums-and-pattern-matching/no-listing-13-count-and-announce-match/src/main.rs +++ b/listings/ch06-enums-and-pattern-matching/no-listing-13-count-and-announce-match/src/main.rs @@ -2,7 +2,7 @@ enum UsState { Alabama, Alaska, - // --snip-- + // --略-- } enum Coin { diff --git a/listings/ch06-enums-and-pattern-matching/no-listing-14-count-and-announce-if-let-else/Cargo.toml b/listings/ch06-enums-and-pattern-matching/no-listing-14-count-and-announce-if-let-else/Cargo.toml index 04988d1ff..e959295f9 100644 --- a/listings/ch06-enums-and-pattern-matching/no-listing-14-count-and-announce-if-let-else/Cargo.toml +++ b/listings/ch06-enums-and-pattern-matching/no-listing-14-count-and-announce-if-let-else/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "enums" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch06-enums-and-pattern-matching/no-listing-14-count-and-announce-if-let-else/src/main.rs b/listings/ch06-enums-and-pattern-matching/no-listing-14-count-and-announce-if-let-else/src/main.rs index ba7eda27b..1d145c272 100644 --- a/listings/ch06-enums-and-pattern-matching/no-listing-14-count-and-announce-if-let-else/src/main.rs +++ b/listings/ch06-enums-and-pattern-matching/no-listing-14-count-and-announce-if-let-else/src/main.rs @@ -2,7 +2,7 @@ enum UsState { Alabama, Alaska, - // --snip-- + // --略-- } enum Coin { diff --git a/listings/ch06-enums-and-pattern-matching/no-listing-11-underscore-placeholder/Cargo.lock b/listings/ch06-enums-and-pattern-matching/no-listing-15-binding-catchall/Cargo.lock similarity index 100% rename from listings/ch06-enums-and-pattern-matching/no-listing-11-underscore-placeholder/Cargo.lock rename to listings/ch06-enums-and-pattern-matching/no-listing-15-binding-catchall/Cargo.lock diff --git a/listings/ch06-enums-and-pattern-matching/no-listing-11-underscore-placeholder/Cargo.toml b/listings/ch06-enums-and-pattern-matching/no-listing-15-binding-catchall/Cargo.toml similarity index 50% rename from listings/ch06-enums-and-pattern-matching/no-listing-11-underscore-placeholder/Cargo.toml rename to listings/ch06-enums-and-pattern-matching/no-listing-15-binding-catchall/Cargo.toml index 04988d1ff..e959295f9 100644 --- a/listings/ch06-enums-and-pattern-matching/no-listing-11-underscore-placeholder/Cargo.toml +++ b/listings/ch06-enums-and-pattern-matching/no-listing-15-binding-catchall/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "enums" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch06-enums-and-pattern-matching/no-listing-15-binding-catchall/src/main.rs b/listings/ch06-enums-and-pattern-matching/no-listing-15-binding-catchall/src/main.rs new file mode 100644 index 000000000..6ce0b5998 --- /dev/null +++ b/listings/ch06-enums-and-pattern-matching/no-listing-15-binding-catchall/src/main.rs @@ -0,0 +1,14 @@ +fn main() { + // ANCHOR: here + let dice_roll = 9; + match dice_roll { + 3 => add_fancy_hat(), + 7 => remove_fancy_hat(), + other => move_player(other), + } + + fn add_fancy_hat() {} + fn remove_fancy_hat() {} + fn move_player(num_spaces: u8) {} + // ANCHOR_END: here +} diff --git a/listings/ch06-enums-and-pattern-matching/no-listing-16-underscore-catchall/Cargo.lock b/listings/ch06-enums-and-pattern-matching/no-listing-16-underscore-catchall/Cargo.lock new file mode 100644 index 000000000..f62e8ac45 --- /dev/null +++ b/listings/ch06-enums-and-pattern-matching/no-listing-16-underscore-catchall/Cargo.lock @@ -0,0 +1,6 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "enums" +version = "0.1.0" + diff --git a/listings/ch06-enums-and-pattern-matching/no-listing-16-underscore-catchall/Cargo.toml b/listings/ch06-enums-and-pattern-matching/no-listing-16-underscore-catchall/Cargo.toml new file mode 100644 index 000000000..e959295f9 --- /dev/null +++ b/listings/ch06-enums-and-pattern-matching/no-listing-16-underscore-catchall/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "enums" +version = "0.1.0" +edition = "2021" + +[dependencies] diff --git a/listings/ch06-enums-and-pattern-matching/no-listing-16-underscore-catchall/src/main.rs b/listings/ch06-enums-and-pattern-matching/no-listing-16-underscore-catchall/src/main.rs new file mode 100644 index 000000000..586e23751 --- /dev/null +++ b/listings/ch06-enums-and-pattern-matching/no-listing-16-underscore-catchall/src/main.rs @@ -0,0 +1,14 @@ +fn main() { + // ANCHOR: here + let dice_roll = 9; + match dice_roll { + 3 => add_fancy_hat(), + 7 => remove_fancy_hat(), + _ => reroll(), + } + + fn add_fancy_hat() {} + fn remove_fancy_hat() {} + fn reroll() {} + // ANCHOR_END: here +} diff --git a/listings/ch06-enums-and-pattern-matching/no-listing-17-underscore-unit/Cargo.lock b/listings/ch06-enums-and-pattern-matching/no-listing-17-underscore-unit/Cargo.lock new file mode 100644 index 000000000..f62e8ac45 --- /dev/null +++ b/listings/ch06-enums-and-pattern-matching/no-listing-17-underscore-unit/Cargo.lock @@ -0,0 +1,6 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "enums" +version = "0.1.0" + diff --git a/listings/ch06-enums-and-pattern-matching/no-listing-17-underscore-unit/Cargo.toml b/listings/ch06-enums-and-pattern-matching/no-listing-17-underscore-unit/Cargo.toml new file mode 100644 index 000000000..e959295f9 --- /dev/null +++ b/listings/ch06-enums-and-pattern-matching/no-listing-17-underscore-unit/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "enums" +version = "0.1.0" +edition = "2021" + +[dependencies] diff --git a/listings/ch06-enums-and-pattern-matching/no-listing-17-underscore-unit/src/main.rs b/listings/ch06-enums-and-pattern-matching/no-listing-17-underscore-unit/src/main.rs new file mode 100644 index 000000000..e791742ee --- /dev/null +++ b/listings/ch06-enums-and-pattern-matching/no-listing-17-underscore-unit/src/main.rs @@ -0,0 +1,13 @@ +fn main() { + // ANCHOR: here + let dice_roll = 9; + match dice_roll { + 3 => add_fancy_hat(), + 7 => remove_fancy_hat(), + _ => (), + } + + fn add_fancy_hat() {} + fn remove_fancy_hat() {} + // ANCHOR_END: here +} diff --git a/src/SUMMARY.md b/src/SUMMARY.md index 26386ca98..1a0898305 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -73,12 +73,12 @@ - [Enumとパターンマッチング](ch06-00-enums.md) - [Enumを定義する](ch06-01-defining-an-enum.md) - - [`match`制御フロー演算子](ch06-02-match.md) + - [`match`制御フロー構造](ch06-02-match.md) - [`if let`で簡潔な制御フロー](ch06-03-if-let.md) -この章では、*列挙型*について見ていきます。列挙型は、*enum*とも称されます。enumは、取りうる値を列挙することで、 +この章では、*列挙型*について見ていきます。列挙型は、*enum*とも称されます。enumは、取りうる*列挙子*を列挙することで、 型を定義させてくれます。最初に、enumを定義し、使用して、enumがデータとともに意味をコード化する方法を示します。 次に、特別に有用なenumである`Option`について掘り下げていきましょう。この型は、 値が何かかなんでもないかを表現します。それから、`match`式のパターンマッチングにより、 どうenumの色々な値に対して異なるコードを走らせやすくなるかを見ます。最後に、`if let`文法要素も、 如何(いか)にenumをコードで扱う際に使用可能な便利で簡潔な慣用句であるかを解説します。 - - - -enumは多くの言語に存在する機能ですが、その能力は言語ごとに異なります。Rustのenumは、F#、OCaml、Haskellなどの、 -関数型言語に存在する*代数的データ型*に最も酷似しています。 diff --git a/src/ch06-01-defining-an-enum.md b/src/ch06-01-defining-an-enum.md index ba7c87fdb..03d573975 100644 --- a/src/ch06-01-defining-an-enum.md +++ b/src/ch06-01-defining-an-enum.md @@ -4,24 +4,37 @@ ## Enumを定義する + + +構造体は、`width`と`height`を持つ`Rectangle`のように、関連するフィールドとデータをひとつにまとめる方法を提供してくれます。 +一方でenumは、ある値が、とりうる値の集合のうちのいずれかひとつであることを表現する方法を提供するものです。 +例えば、`Rectangle`は、`Circle`や`Triangle`も含めたとりうる形の集合のいずれかひとつである、と表現したいことがあります。 +これを達成するために、Rustではこれらの可能性をenumとしてエンコードすることができます。 + コードで表現したくなるかもしれない場面に目を向けて、enumが有用でこの場合、構造体よりも適切である理由を確認しましょう。 IPアドレスを扱う必要が出たとしましょう。現在、IPアドレスの規格は二つあります: バージョン4とバージョン6です。 -これらは、プログラムが遭遇するIPアドレスのすべての可能性です: 列挙型は、取りうる値をすべて*列挙*でき、 +これらはプログラムが遭遇するIPアドレスの可能性のすべてですので、取りうる列挙子をすべて*列挙*できます。 これが列挙型の名前の由来です。 この概念をコードでは、`IpAddrKind`列挙型を定義し、IPアドレスがなりうる種類、`V4`と`V6`を列挙することで、 -表現できます。これらは、enumの*列挙子*として知られています: +表現できます。これらがenumの列挙子です: ```rust -enum IpAddrKind { - V4, - V6, -} +{{#rustdoc_include ../listings/ch06-enums-and-pattern-matching/no-listing-01-defining-enums/src/main.rs:def}} ``` enumの列挙子は、その識別子の元に名前空間分けされていることと、 @@ -91,12 +94,7 @@ enumの列挙子は、その識別子の元に名前空間分けされている 同じ型`IpAddrKind`になったからです。そうしたら、例えば、どんな`IpAddrKind`を取る関数も定義できるようになります。 ```rust -# enum IpAddrKind { -# V4, -# V6, -# } -# -fn route(ip_type: IpAddrKind) { } +{{#rustdoc_include ../listings/ch06-enums-and-pattern-matching/no-listing-01-defining-enums/src/main.rs:fn}} ``` enumの利用には、さらなる利点さえもあります。このIPアドレス型についてもっと考えてみると、現状では、 実際のIPアドレスの*データ*を保持する方法がありません。つまり、どんな*種類*であるかを知っているだけです。 -構造体について第5章で学んだばっかりとすると、この問題に対して、あなたはリスト6-1のように対処するかもしれません。 +構造体について第5章で学んだばっかりとすると、この問題に対して、あなたはリスト6-1のように構造体を使って対処したくなるかもしれません。 ```rust -enum IpAddrKind { - V4, - V6, -} - -struct IpAddr { - kind: IpAddrKind, - address: String, -} - -let home = IpAddr { - kind: IpAddrKind::V4, - address: String::from("127.0.0.1"), -}; - -let loopback = IpAddr { - kind: IpAddrKind::V6, - address: String::from("::1"), -}; +{{#rustdoc_include ../listings/ch06-enums-and-pattern-matching/listing-06-01/src/main.rs:here}} ``` ここでは、二つのフィールドを持つ`IpAddr`という構造体を定義しています: `IpAddrKind`型(先ほど定義したenumですね)の`kind`フィールドと、 -`String`型の`address`フィールドです。この構造体のインスタンスが2つあります。最初のインスタンス、 -`home`には`kind`として`IpAddrKind::V4`があり、紐付けられたアドレスデータは`127.0.0.1`です。 -2番目のインスタンス、`loopback`には、`kind`の値として、`IpAddrKind`のもう一つの列挙子、`V6`があり、 +`String`型の`address`フィールドです。この構造体のインスタンスが2つあります。最初のインスタンスは`home`で、 +これには`kind`として`IpAddrKind::V4`があり、紐付けられたアドレスデータは`127.0.0.1`です。 +2番目のインスタンスは`loopback`です。これには`kind`の値として、`IpAddrKind`のもう一つの列挙子、`V6`があり、 アドレス`::1`が紐付いています。構造体を使って`kind`と`address`値を一緒に包んだので、 もう列挙子は値と紐付けられています。 -各enumの列挙子に直接データを格納して、enumを構造体内に使うというよりもenumだけを使って、 -同じ概念をもっと簡潔な方法で表現することができます。この新しい`IpAddr`の定義は、 -`V4`と`V6`列挙子両方に`String`値が紐付けられていることを述べています。 +しかしながら、enumだけを使って同じ概念を表現するほうがより簡潔です: +構造体の中にenumを持たせるのではなく、enumの各列挙子に直接データを格納することができるのです。 +この新しい`IpAddr`の定義は、`V4`と`V6`列挙子両方に`String`値が紐付けられていることを述べています。 ```rust -enum IpAddr { - V4(String), - V6(String), -} - -let home = IpAddr::V4(String::from("127.0.0.1")); - -let loopback = IpAddr::V6(String::from("::1")); +{{#rustdoc_include ../listings/ch06-enums-and-pattern-matching/no-listing-02-enum-with-data/src/main.rs:here}} ``` enumの各列挙子にデータを直接添付できるので、余計な構造体を作る必要は全くありません。 +またここでは、enumがどう機能するかについての別の詳細も確認することができます: +ここで定義したenumの各列挙子の名前は、そのenumを構築する関数にもなるのです。 +つまり、`IpAddr::V4()`は`String`引数を受け取り`IpAddr`型のインスタンスを返す関数の呼び出しになるのです。 +enumを定義した結果として、自動でこのコンストラクタ関数が定義されます。 - - ```rust struct Ipv4Addr { - // 省略 + // --略-- } struct Ipv6Addr { - // 省略 + // --略-- } enum IpAddr { @@ -314,12 +276,7 @@ variety of types embedded in its variants. リスト6-2でenumの別の例を見てみましょう: 今回のコードは、幅広い種類の型が列挙子に埋め込まれています。 ```rust -enum Message { - Quit, - Move { x: i32, y: i32 }, - Write(String), - ChangeColor(i32, i32, i32), -} +{{#rustdoc_include ../listings/ch06-enums-and-pattern-matching/listing-06-02/src/main.rs:here}} ``` -* `Quit`には紐付けられたデータは全くなし。 -* `Move`は、中に匿名構造体を含む。 -* `Write`は、単独の`String`オブジェクトを含む。 -* `ChangeColor`は、3つの`i32`値を含む。 +* `Quit`は関連付けられたデータをまったく持ちません。 +* `Move`は構造体のように名前付きのフィールドを持っています。 +* `Write`は`String`オブジェクトを1個だけ含んでいます。 +* `ChangeColor`は3個の`i32`値を含んでいます。 - ```rust -struct QuitMessage; // ユニット構造体 -struct MoveMessage { - x: i32, - y: i32, -} -struct WriteMessage(String); // タプル構造体 -struct ChangeColorMessage(i32, i32, i32); // タプル構造体 +{{#rustdoc_include ../listings/ch06-enums-and-pattern-matching/no-listing-04-structs-similar-to-message-enum/src/main.rs:here}} ``` - - -ですが、異なる構造体を使っていたら、各々、それ自身の型があるので、単独の型になるリスト6-2で定義した`Message` enumほど、 -これらの種のメッセージいずれもとる関数を簡単に定義することはできないでしょう。 +ですがそれぞれ独自の型を持つ異なる構造体を使ってしまうと、リスト6-2で定義した単一の型である`Message` enumを使う場合と比較して、 +これらの任意の種類のメッセージを取る関数を簡単には定義できません。 -前節で、`IpAddr` enumがRustの型システムを使用して、プログラムにデータ以上の情報をコード化できる方法を目撃しました。 この節では、`Option`のケーススタディを掘り下げていきます。この型も標準ライブラリにより定義されているenumです。 -この`Option`型はいろんな箇所で使用されます。なぜなら、値が何かかそうでないかという非常に一般的な筋書きをコード化するからです。 -この概念を型システムの観点で表現することは、コンパイラが、プログラマが処理すべき場面全てを処理していることをチェックできることを意味します; +この`Option`型は、値が何かかそうでないかという非常に一般的な筋書きをコード化します。 + + + +例えば、空でないリストの最初のアイテムをリクエストすると、値が得られるでしょう。 +空リストの最初のアイテムをリクエストすると、何も得られないでしょう。 +この概念を型システムの観点で表現することは、コンパイラが、プログラマが処理すべき場面全てを処理しているかどうかチェックできることを意味します; この機能は、他の言語において、究極的にありふれたバグを阻止することができます。 -`Option`は有益すぎて、初期化処理(prelude)にさえ含まれています。つまり、明示的にスコープに導入する必要がないのです。 -さらに、列挙子もそうなっています: `Some`と`None`を`Option::`の接頭辞なしに直接使えるわけです。 -ただ、`Option`はそうは言っても、普通のenumであり、`Some(T)`と`None`も`Option`型のただの列挙子です。 +`Option`は有益すぎて、preludeにさえ含まれています; 明示的にスコープに導入する必要がないのです。 +そしてその列挙子もまたpreludeに含まれています: `Some`と`None`を`Option::`の接頭辞なしに直接使えるわけです。 +ただ、`Option` enumはそうは言っても、普通のenumであり、`Some(T)`と`None`も`Option`型のただの列挙子です。 -``という記法は、まだ語っていないRustの機能です。これは、ジェネリック型引数であり、ジェネリクスについて詳しくは、 -第10章で解説します。とりあえず、知っておく必要があることは、``は、`Option` enumの`Some`列挙子が、 -あらゆる型のデータを1つだけ持つことができることを意味していることだけです。こちらは、 -`Option`値を使って、数値型や文字列型を保持する例です。 +``という記法は、まだ語っていないRustの機能です。 +これはジェネリック型引数で、ジェネリクスについて詳しくは第10章で解説します。 +とりあえず``の意味に関して知っておく必要があることは、`Option` enumの`Some`列挙子はあらゆる型のデータを1つだけ持つことができ、 +`T`の代わりに使用される具体的な型に応じて、`Option`型はそれぞれ異なる型になるということだけです。 +以下は`Option`値を使って数値型や文字列型を保持する例です。 ```rust -let some_number = Some(5); -let some_string = Some("a string"); - -let absent_number: Option = None; +{{#rustdoc_include ../listings/ch06-enums-and-pattern-matching/no-listing-06-option-examples/src/main.rs:here}} ``` -`Some`ではなく、`None`を使ったら、コンパイラに`Option`の型が何になるかを教えなければいけません。 -というのも、`None`値を見ただけでは、`Some`列挙子が保持する型をコンパイラが推論できないからです。 +`some_number`の型は`Option`です。`some_char`の型は`Option`で、これは先ほどとは異なる型です。 +`Some`列挙子の中で値を指定しているので、コンパイラはこれらの型を推論することができます。 +`absent_number`に関しては、コンパイラはジェネリクス適用後の`Option`型を注釈することを要求します: +`None`値を見ただけでは、それに対応する`Some`列挙子が保持する型をコンパイラは推論できないからです。 +ここでは、`absent_number`が`Option`型を持つことをコンパイラに伝えています。 `Some`値がある時、値が存在するとわかり、その値は、`Some`に保持されています。`None`値がある場合、 @@ -594,8 +524,8 @@ nullよりも少しでも好ましいのでしょうか? @@ -603,28 +533,18 @@ trying to add an `i8` to an `Option`: コンパイラが`Option`値を確実に有効な値かのようには使用させてくれません。 例えば、このコードは`i8`を`Option`に足そうとしているので、コンパイルできません。 -```rust,ignore -let x: i8 = 5; -let y: Option = Some(5); - -let sum = x + y; +```rust,ignore,does_not_compile +{{#rustdoc_include ../listings/ch06-enums-and-pattern-matching/no-listing-07-cant-use-option-directly/src/main.rs:here}} ``` このコードを動かしたら、以下のようなエラーメッセージが出ます。 -```text -error[E0277]: the trait bound `i8: std::ops::Add>` is -not satisfied -(エラー: `i8: std::ops::Add>`というトレイト境界が満たされていません) - --> - | -5 | let sum = x + y; - | ^ no implementation for `i8 + std::option::Option` - | +```console +{{#include ../listings/ch06-enums-and-pattern-matching/no-listing-07-cant-use-option-directly/output.txt}} ``` 言い換えると、`T`型の処理を行う前には、`Option`を`T`に変換する必要があるわけです。一般的に、 @@ -657,7 +576,7 @@ is. そうでないかのように想定することです。 -不正確にnullでない値を想定する心配をしなくてもよいということは、コード内でより自信を持てることになります。 +値がnullでないと誤って想定するリスクを削減することは、コードに確信を持つための助けになります。 nullになる可能性のある値を保持するには、その値の型を`Option`にすることで明示的に同意しなければなりません。 それからその値を使用する際には、値がnullである場合を明示的に処理する必要があります。 値が`Option`以外の型であるところ全てにおいて、値がnullでないと安全に想定することが*できます*。 これは、Rustにとって、意図的な設計上の決定であり、nullの普遍性を制限し、Rustコードの安全性を向上させます。 では、`Option`型の値がある時、その値を使えるようにするには、どのように`Some`列挙子から`T`型の値を取り出せばいいのでしょうか? @@ -686,21 +606,29 @@ the methods on `Option` will be extremely useful in your journey with Rust. [ドキュメント][docs]でそれらを確認できます。`Option`のメソッドに馴染むと、 Rustの旅が極めて有益になるでしょう。 -[docs]: https://doc.rust-lang.org/std/option/enum.Option.html - 一般的に、`Option`値を使うには、各列挙子を処理するコードが欲しくなります。 -`Some(T)`値がある時だけ走る何らかのコードが欲しくなり、このコードが内部の`T`を使用できます。 -`None`値があった場合に走る別のコードが欲しくなり、そちらのコードは`T`値は使用できない状態になります。 +`Some(T)`値がある場合だけ走る何らかのコードが欲しくなり、このコードが内部の`T`を使用できます。 +`None`値がある場合だけ走る別のコードが欲しくなり、そちらのコードは`T`を使用できない状態になります。 `match`式が、enumとともに使用した時にこれだけの動作をする制御フロー文法要素になります: enumの列挙子によって、違うコードが走り、そのコードがマッチした値の中のデータを使用できるのです。 + + + +[IpAddr]: https://doc.rust-lang.org/std/net/enum.IpAddr.html +[option]: https://doc.rust-lang.org/std/option/enum.Option.html +[docs]: https://doc.rust-lang.org/std/option/enum.Option.html diff --git a/src/ch06-02-match.md b/src/ch06-02-match.md index f0fe802b4..968bedb2f 100644 --- a/src/ch06-02-match.md +++ b/src/ch06-02-match.md @@ -1,26 +1,32 @@ + -## `match`制御フロー演算子 + + +## `match`制御フロー構造 Rustには、一連のパターンに対して値を比較し、マッチしたパターンに応じてコードを実行させてくれる`match`と呼ばれる、 -非常に強力な制御フロー演算子があります。パターンは、リテラル値、変数名、ワイルドカードやその他多数のもので構成することができます; -第18章で、全ての種類のパターンと、その目的については解説します。`match`のパワーは、 +非常に強力な制御フロー構造があります。パターンは、リテラル値、変数名、ワイルドカードやその他多数のもので構成することができます; +[第18章][ch18-00-patterns]で、全ての種類のパターンと、その目的については解説します。`match`のパワーは、 パターンの表現力とコンパイラが全てのありうるパターンを処理しているかを確認してくれるという事実に由来します。 -コインについて話したので、それを`match`を使用する例にとってみましょう!数え上げ装置と同じ要領で未知のアメリカコインを一枚取り、 +せっかくコインについて話したので、それを`match`を使用する例にとってみましょう!数え上げ装置と同じ要領で未知のアメリカコインを一枚取り、 どの種類のコインなのか決定し、その価値をセントで返す関数をリスト6-3で示したように記述することができます。 ```rust -enum Coin { - Penny, - Nickel, - Dime, - Quarter, -} - -fn value_in_cents(coin: Coin) -> u32 { - match coin { - Coin::Penny => 1, - Coin::Nickel => 5, - Coin::Dime => 10, - Coin::Quarter => 25, - } -} +{{#rustdoc_include ../listings/ch06-enums-and-pattern-matching/listing-06-03/src/main.rs:here}} ``` リスト6-3: enumとそのenumの列挙子をパターンにした`match`式 `value_in_cents`関数内の`match`を噛み砕きましょう。まず、`match`キーワードに続けて式を並べています。 -この式は今回の場合、値`coin`です。`if`で使用した式と非常に酷似しているみたいですね。しかし、大きな違いがあります: -`if`では、式は論理値を返す必要がありますが、ここでは、どんな型でも構いません。この例における`coin`の型は、 +この式は今回の場合、値`coin`です。`if`で使用した条件式と非常に酷似しているみたいですね。しかし、大きな違いがあります: +`if`では、条件は論理値に評価される必要がありますが、ここでは、どんな型でも構いません。この例における`coin`の型は、 1行目で定義した`Coin` enumです。 @@ -112,47 +104,32 @@ entire `match` expression. 各アームに紐付けられるコードは式であり、マッチしたアームの式の結果が`match`式全体の戻り値になります。 -典型的に、アームのコードが短い場合、波かっこは使用されません。リスト6-3では、各アームが値を返すだけなので、 -これに倣っています。マッチのアームで複数行のコードを走らせたいのなら、波かっこを使用することができます。 +典型的に、アームのコードが短い場合、波かっこは使用しません。リスト6-3では、各アームが値を返すだけなので、 +これに倣っています。マッチのアームで複数行のコードを走らせたいのなら、波かっこを使わなくてはなりませんが、 +この場合アームの後のカンマは省略することができます。 例えば、以下のコードは、メソッドが`Coin::Penny`とともに呼び出されるたびに「Lucky penny!」と表示しつつ、 -ブロックの最後の値、`1`を返すでしょう。 +ブロックの最後の値、`1`を返します。 ```rust -# enum Coin { -# Penny, -# Nickel, -# Dime, -# Quarter, -# } -# -fn value_in_cents(coin: Coin) -> u32 { - match coin { - Coin::Penny => { - println!("Lucky penny!"); - 1 - }, - Coin::Nickel => 5, - Coin::Dime => 10, - Coin::Quarter => 25, - } -} +{{#rustdoc_include ../listings/ch06-enums-and-pattern-matching/no-listing-08-match-arm-multiple-lines/src/main.rs:here}} ``` ### 値に束縛されるパターン @@ -165,8 +142,8 @@ As an example, let’s change one of our enum variants to hold data inside it. From 1999 through 2008, the United States minted quarters with different designs for each of the 50 states on one side. No other coins got state designs, so only quarters have this extra value. We can add this information to -our `enum` by changing the `Quarter` variant to include a `UsState` value stored -inside it, which we've done here in Listing 6-4. +our `enum` by changing the `Quarter` variant to include a `UsState` value +stored inside it, which we’ve done in Listing 6-4. --> 例として、enumの列挙子の一つを中にデータを保持するように変えましょう。1999年から2008年まで、 @@ -175,40 +152,8 @@ inside it, which we've done here in Listing 6-4. `Quarter`列挙子を変更して、`UsState`値が中に保持されるようにすることで`enum`にこの情報を追加でき、 それをしたのがリスト6-4のコードになります。 - - - - -```rust -#[derive(Debug)] // すぐに州を点検できるように -enum UsState { - Alabama, - Alaska, - // ... などなど -} - -enum Coin { - Penny, - Nickel, - Dime, - Quarter(UsState), -} +{{#rustdoc_include ../listings/ch06-enums-and-pattern-matching/listing-06-04/src/main.rs:here}} ``` @@ -240,30 +185,7 @@ quarter’s state. Then we can use `state` in the code for that arm, like so: `state`をそのアームのコードで使用できます。以下のようにですね: ```rust -# #[derive(Debug)] -# enum UsState { -# Alabama, -# Alaska, -# } -# -# enum Coin { -# Penny, -# Nickel, -# Dime, -# Quarter(UsState), -# } -# -fn value_in_cents(coin: Coin) -> u32 { - match coin { - Coin::Penny => 1, - Coin::Nickel => 5, - Coin::Dime => 10, - Coin::Quarter(state) => { - println!("State quarter from {:?}!", state); - 25 - }, - } -} +{{#rustdoc_include ../listings/ch06-enums-and-pattern-matching/no-listing-09-variable-in-pattern/src/main.rs:here}} ``` 前節では、`Option`を使用する際に、`Some`ケースから中身の`T`の値を取得したくなりました。要するに、 @@ -317,16 +239,7 @@ Listing 6-5. `match`のおかげで、この関数は大変書きやすく、リスト6-5のような見た目になります。 ```rust -fn plus_one(x: Option) -> Option { - match x { - None => None, - Some(i) => Some(i + 1), - } -} - -let five = Some(5); -let six = plus_one(five); -let none = plus_one(None); +{{#rustdoc_include ../listings/ch06-enums-and-pattern-matching/listing-06-05/src/main.rs:here}} ``` `plus_one`の最初の実行についてもっと詳しく検証しましょう。`plus_one(five)`と呼び出した時、 -`plus_one`の本体の変数`x`は`Some(5)`になります。そして、これをマッチの各アームと比較します。 +`plus_one`の本体の変数`x`は`Some(5)`になります。そして、これをマッチの各アームと比較します: ```rust,ignore -None => None, +{{#rustdoc_include ../listings/ch06-enums-and-pattern-matching/listing-06-05/src/main.rs:first_arm}} ``` -`Some(5)`という値は、`None`というパターンにはマッチしませんので、次のアームに処理が移ります。 +`Some(5)`という値は、`None`というパターンにはマッチしませんので、次のアームに処理が移ります: ```rust,ignore -Some(i) => Some(i + 1), +{{#rustdoc_include ../listings/ch06-enums-and-pattern-matching/listing-06-05/src/main.rs:second_arm}} ``` - -`Some(5)`は`Some(i)`にマッチしますか?なんと、します!列挙子が同じです。`i`は`Some`に含まれる値に束縛されるので、 +`Some(5)`は`Some(i)`にマッチしますか?しますね!列挙子が同じです。`i`は`Some`に含まれる値に束縛されるので、 `i`は値`5`になります。それから、このマッチのアームのコードが実行されるので、`i`の値に1を足し、 合計の`6`を中身にした新しい`Some`値を生成します。 さて、`x`が`None`になるリスト6-5の2回目の`plus_one`の呼び出しを考えましょう。`match`に入り、 -最初のアームと比較します。 +最初のアームと比較します: ```rust,ignore -None => None, +{{#rustdoc_include ../listings/ch06-enums-and-pattern-matching/listing-06-05/src/main.rs:first_arm}} ``` -もう一つ議論する必要のある`match`の観点があります。一点バグがありコンパイルできないこんなバージョンの`plus_one`関数を考えてください: +もう一つ議論する必要のある`match`の観点があります: アームのパターンはすべての可能性を網羅しなくてはなりません。 +こんなバージョンの`plus_one`関数を考えてください、これにはバグがありコンパイルできないでしょう: -```rust,ignore -fn plus_one(x: Option) -> Option { - match x { - Some(i) => Some(i + 1), - } -} +```rust,ignore,does_not_compile +{{#rustdoc_include ../listings/ch06-enums-and-pattern-matching/no-listing-10-non-exhaustive-match/src/main.rs:here}} ``` - | -6 | match x { - | ^ pattern `None` not covered +```console +{{#include ../listings/ch06-enums-and-pattern-matching/no-listing-10-non-exhaustive-match/output.txt}} ``` 全可能性を網羅していないことをコンパイラは検知しています。もっと言えば、どのパターンを忘れているかさえ知っているのです。 Rustにおけるマッチは、*包括的*です: 全てのあらゆる可能性を網羅し尽くさなければ、コードは有効にならないのです。 特に`Option`の場合には、私達が明示的に`None`の場合を処理するのを忘れないようにしてくれます。 -nullになるかもしれないのに値があると思い込まないよう、すなわち前に議論した10億ドルの失敗を犯さないよう、 +nullになるかもしれないのに値があると思い込まないよう、すなわち前に議論した10億ドルの失敗を犯すことができないよう、 コンパイラが保護してくれるわけです。 -### `_`というプレースホルダー +### catch-allパターンとプレースホルダー(`_`) -Rustには、全ての可能性を列挙したくない時に使用できるパターンもあります。例えば、`u8`は、有効な値として、 -0から255までを取ります。1、3、5、7の値にだけ興味があったら、0、2、4、6、8、9と255までの数値を列挙する必要に迫られたくはないです。 -幸運なことに、する必要はありません: 代わりに特別なパターンの`_`を使用できます: +enumを使用することで、いくつかの特定の値に対して特別な操作を行うが、他のすべての値に対してはデフォルトの操作を行う、ということができます。 +ゲームを実装しているところを想像してください。 +サイコロを振って3の目が出たら、そのプレイヤーは移動できませんが、代わりにおしゃれな帽子をもらえます。 +サイコロを振って7の目が出たら、そのプレイヤーはおしゃれな帽子を失います。 +他のすべての値については、そのプレイヤーはゲーム盤上で同じ数だけマスを移動します。 +以下はこのロジックを実装する`match`です。 +ただしサイコロを振った結果はランダム値ではなくハードコードされており、また他のすべてのロジックは、それを実際に実装するのは本題ではないので、本体の無い関数によって表現されています: ```rust -let some_u8_value = 0u8; -match some_u8_value { - 1 => println!("one"), - 3 => println!("three"), - 5 => println!("five"), - 7 => println!("seven"), - _ => (), -} +{{#rustdoc_include ../listings/ch06-enums-and-pattern-matching/no-listing-15-binding-catchall/src/main.rs:here}} ``` + +最初の2つのアームについては、パターンはリテラル値`3`および`7`です。 +他のあらゆる可能な値を網羅する最後のアームについては、パターンは変数で、この変数には`other`と名付けることを選びました。 +`other`アームで実行されるコードは、`move_player`関数にこの変数を渡すことで、この変数を使用しています。 + + + +`u8`が取りうるすべての値を列挙していないにも関わらず、このコードはコンパイルできます。 +最後のパターンが、個別に列挙していないすべての値にマッチするからです。 +このcatch-allパターンのおかげで、`match`は包括的でなくてはならないという必要条件が満たされます。 +パターンは順に評価されるので、catch-allアームは最後に書く必要があることに注意してください。 +catch-allアームを先に書いてしまうと他のアームは絶対に実行されなくなってしまうため、 +catch-allの後にアームを追加するとコンパイラが警告を発するでしょう! + + + +Rustには、catch-allしたいが、catch-allパターン内で値を*使用*したくない時に使用できるパターンもあります: +`_`は任意の値にマッチし、その値を束縛しない特別なパターンです。 +これはコンパイラにその値を使用しないということを伝えるので、コンパイラは未使用の変数についての警告を発しなくなるしょう。 + + + +ゲームのルールを変更しましょう: これからは、3または7以外の目を出したら、もう一度サイコロを振らなくてはなりません。 +catch-allの値を使用する必要がなくなるので、`other`変数の代わりに`_`を使用するようにコードを変更します: + + +```rust +{{#rustdoc_include ../listings/ch06-enums-and-pattern-matching/no-listing-16-underscore-catchall/src/main.rs:here}} +``` + + + +この例もまた、最後のアームで明示的にすべての他の値を無視しているので、網羅性要件を満たしています; +見落としている場合分けはありません。 + + + +最後に、もう一度だけゲームのルールを変更することにします。 +3または7以外の目を出したら、プレイヤーの番には何も起きません。 +以下の`_`アームのコードのように、ユニット値([「タプル型」][tuples]節で説明した空タプル型)を使用することでこれを表現できます: + +```rust +{{#rustdoc_include ../listings/ch06-enums-and-pattern-matching/no-listing-17-underscore-unit/src/main.rs:here}} +``` + + + +このコードでは、先の方のアームのパターンにマッチしないあらゆる値は使用せず、 +この場合にはいかなるコードも実行したくないということを、コンパイラに明示的に伝えています。 + + -`_`というパターンは、どんな値にもマッチします。他のアームの後に記述することで、`_`は、 -それまでに指定されていない全ての可能性にマッチします。`()`は、ただのユニット値なので、`_`の場合には、 -何も起こりません。結果として、`_`プレースホルダーの前に列挙していない可能性全てに対しては、 -何もしたくないと言えるわけです。 +パターンとマッチングについては[第18章][ch18-00-patterns]でさらに深く取り扱います。 +ひとまず、`match`式ではちょっと長ったらしいという状況で便利かもしれない、`if let`構文に進むことにましょう。 -ですが、*一つ*のケースにしか興味がないような場面では、`match`式はちょっと長ったらしすぎます。 -このような場面用に、Rustには、`if let`が用意されています。 +[tuples]: ch03-02-data-types.html#タプル型 +[ch18-00-patterns]: ch18-00-patterns.html diff --git a/src/ch06-03-if-let.md b/src/ch06-03-if-let.md index e946ce219..057123639 100644 --- a/src/ch06-03-if-let.md +++ b/src/ch06-03-if-let.md @@ -7,38 +7,36 @@ `if let`記法で`if`と`let`をより冗長性の少ない方法で組み合わせ、残りを無視しつつ、一つのパターンにマッチする値を扱うことができます。 -`Option`にマッチするけれど、値が3の時にだけコードを実行したい、リスト6-6のプログラムを考えてください。 +`config_max`変数の`Option`値にマッチするけれど、値が`Some`列挙子の時にだけコードを実行したい、リスト6-6のプログラムを考えてください。 ```rust -let some_u8_value = Some(0u8); -match some_u8_value { - Some(3) => println!("three"), - _ => (), -} +{{#rustdoc_include ../listings/ch06-enums-and-pattern-matching/listing-06-06/src/main.rs:here}} ``` -リスト6-6: 値が`Some(3)`の時だけコードを実行する`match` +リスト6-6: 値が`Some`の時だけコードを実行する`match` -`Some(3)`にマッチした時だけ何かをし、他の`Some`値や`None`値の時には何もしたくありません。 -`match`式を満たすためには、列挙子を一つだけ処理した後に`_ => ()`を追加しなければなりません。 -これでは、追加すべき定型コードが多すぎます。 +値が`Some`の場合は、その`Some`列挙子の値をパターン内の変数`max`に束縛することで、それを出力します。 +`None`値に対しては何もしたくありません。 +`match`式の要件を満たすためには、列挙子を一つだけ処理した後に`_ => ()`を追加しなければなりませんが、これは煩わしい定型コードです。 -`if let`という記法は等号記号で区切られたパターンと式を取り、式が`match`に与えられ、パターンが最初のアームになった`match`と、 -同じ動作をします。 +`if let`という記法は等号記号で区切られたパターンと式を取り、式が`match`に与えられ、パターンが最初のアームになった`match`と同じ動作をします。 +この場合は、パターンは`Some(max)`で`max`は`Some`内の値に束縛されます。 +そうすると、対応する`match`アームの中で`max`を使用したのと全く同じように、`if let`ブロックの本体の中で`max`を使用することができます。 +値がパターンにマッチしない場合は、`if let`ブロック内のコードは実行されません。 `if let`では、`else`を含むこともできます。`else`に入るコードブロックは、 @@ -101,53 +102,17 @@ expression like this: 見かけたクォーター以外のコインの枚数を数えたいなら、以下のように`match`式で実現することができるでしょう: ```rust -# #[derive(Debug)] -# enum UsState { -# Alabama, -# Alaska, -# } -# -# enum Coin { -# Penny, -# Nickel, -# Dime, -# Quarter(UsState), -# } -# let coin = Coin::Penny; -let mut count = 0; -match coin { - // {:?}州のクォーターコイン - Coin::Quarter(state) => println!("State quarter from {:?}!", state), - _ => count += 1, -} +{{#rustdoc_include ../listings/ch06-enums-and-pattern-matching/no-listing-13-count-and-announce-match/src/main.rs:here}} ``` または、以下のように`if let`と`else`を使うこともできるでしょう: ```rust -# #[derive(Debug)] -# enum UsState { -# Alabama, -# Alaska, -# } -# -# enum Coin { -# Penny, -# Nickel, -# Dime, -# Quarter(UsState), -# } -# let coin = Coin::Penny; -let mut count = 0; -if let Coin::Quarter(state) = coin { - println!("State quarter from {:?}!", state); -} else { - count += 1; -} +{{#rustdoc_include ../listings/ch06-enums-and-pattern-matching/no-listing-14-count-and-announce-if-let-else/src/main.rs:here}} ``` From 20bed516851c17f4963e4d9d60cbb194ce86ff0c Mon Sep 17 00:00:00 2001 From: shinmili Date: Sun, 26 May 2024 12:58:03 +0900 Subject: [PATCH 08/10] =?UTF-8?q?ch07=20=E8=82=A5=E5=A4=A7=E5=8C=96?= =?UTF-8?q?=E3=81=97=E3=81=A6=E3=81=84=E3=81=8F=E3=83=97=E3=83=AD=E3=82=B8?= =?UTF-8?q?=E3=82=A7=E3=82=AF=E3=83=88=E3=82=92=E3=83=91=E3=83=83=E3=82=B1?= =?UTF-8?q?=E3=83=BC=E3=82=B8=E3=80=81=E3=82=AF=E3=83=AC=E3=83=BC=E3=83=88?= =?UTF-8?q?=E3=80=81=E3=83=A2=E3=82=B8=E3=83=A5=E3=83=BC=E3=83=AB=E3=82=92?= =?UTF-8?q?=E5=88=A9=E7=94=A8=E3=81=97=E3=81=A6=E7=AE=A1=E7=90=86=E3=81=99?= =?UTF-8?q?=E3=82=8B=E3=81=AE=E5=92=8C=E8=A8=B3=E3=82=92=E6=9C=80=E6=96=B0?= =?UTF-8?q?=E7=89=88=E3=81=AB=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit rust-lang/book@19c40bfd2d57641d962f3119a1c343355f1b3c5e --- .../listing-07-01/Cargo.toml | 3 +- .../listing-07-01/src/lib.rs | 4 - .../listing-07-03/Cargo.toml | 3 +- .../listing-07-03/output.txt | 26 +- .../listing-07-05/Cargo.toml | 3 +- .../listing-07-05/output.txt | 22 +- .../listing-07-07/Cargo.toml | 3 +- .../listing-07-07/src/lib.rs | 4 - .../listing-07-08/Cargo.toml | 3 +- .../listing-07-08/src/lib.rs | 8 +- .../listing-07-09/Cargo.toml | 3 +- .../listing-07-10/Cargo.toml | 3 +- .../listing-07-11/Cargo.toml | 3 +- .../listing-07-11/src/lib.rs | 6 - .../listing-07-12/Cargo.toml | 3 +- .../listing-07-12/output.txt | 28 ++ .../listing-07-12/src/lib.rs | 14 +- .../listing-07-13/Cargo.toml | 3 +- .../listing-07-13/src/lib.rs | 6 - .../listing-07-14/Cargo.toml | 3 +- .../listing-07-15/Cargo.toml | 3 +- .../listing-07-16/Cargo.toml | 3 +- .../listing-07-17/Cargo.toml | 3 +- .../listing-07-17/src/lib.rs | 6 - .../listing-07-18/Cargo.lock | 84 ++--- .../listing-07-18/Cargo.toml | 5 +- .../listing-07-18/src/main.rs | 6 +- .../listing-07-19/Cargo.toml | 3 +- .../listing-07-20/Cargo.toml | 3 +- .../listing-07-21-and-22/Cargo.toml | 3 +- .../listing-07-21-and-22/src/lib.rs | 2 - .../no-listing-01-use-std-unnested/Cargo.lock | 84 ++--- .../no-listing-01-use-std-unnested/Cargo.toml | 5 +- .../src/main.rs | 6 +- .../Cargo.toml | 3 +- .../src/lib.rs | 2 - .../quick-reference-example/Cargo.lock | 7 + .../quick-reference-example/Cargo.toml | 6 + .../quick-reference-example/output.txt | 5 + .../quick-reference-example/src/garden.rs | 1 + .../src/garden/vegetables.rs | 2 + .../quick-reference-example/src/main.rs | 8 + ...ojects-with-packages-crates-and-modules.md | 43 ++- src/ch07-01-packages-and-crates.md | 149 ++++---- ...ng-modules-to-control-scope-and-privacy.md | 253 ++++++++++--- ...referring-to-an-item-in-the-module-tree.md | 357 +++++++++++------- ...g-paths-into-scope-with-the-use-keyword.md | 174 +++++---- ...separating-modules-into-different-files.md | 150 ++++++-- 48 files changed, 950 insertions(+), 577 deletions(-) create mode 100644 listings/ch07-managing-growing-projects/listing-07-12/output.txt create mode 100644 listings/ch07-managing-growing-projects/quick-reference-example/Cargo.lock create mode 100644 listings/ch07-managing-growing-projects/quick-reference-example/Cargo.toml create mode 100644 listings/ch07-managing-growing-projects/quick-reference-example/output.txt create mode 100644 listings/ch07-managing-growing-projects/quick-reference-example/src/garden.rs create mode 100644 listings/ch07-managing-growing-projects/quick-reference-example/src/garden/vegetables.rs create mode 100644 listings/ch07-managing-growing-projects/quick-reference-example/src/main.rs diff --git a/listings/ch07-managing-growing-projects/listing-07-01/Cargo.toml b/listings/ch07-managing-growing-projects/listing-07-01/Cargo.toml index 8bdd0a418..60cec7cb0 100644 --- a/listings/ch07-managing-growing-projects/listing-07-01/Cargo.toml +++ b/listings/ch07-managing-growing-projects/listing-07-01/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "restaurant" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch07-managing-growing-projects/listing-07-01/src/lib.rs b/listings/ch07-managing-growing-projects/listing-07-01/src/lib.rs index 0e40be70d..591e24557 100644 --- a/listings/ch07-managing-growing-projects/listing-07-01/src/lib.rs +++ b/listings/ch07-managing-growing-projects/listing-07-01/src/lib.rs @@ -1,4 +1,3 @@ -// ANCHOR: here mod front_of_house { mod hosting { fn add_to_waitlist() {} @@ -14,6 +13,3 @@ mod front_of_house { fn take_payment() {} } } -// ANCHOR_END: here - -fn main() {} diff --git a/listings/ch07-managing-growing-projects/listing-07-03/Cargo.toml b/listings/ch07-managing-growing-projects/listing-07-03/Cargo.toml index 8bdd0a418..60cec7cb0 100644 --- a/listings/ch07-managing-growing-projects/listing-07-03/Cargo.toml +++ b/listings/ch07-managing-growing-projects/listing-07-03/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "restaurant" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch07-managing-growing-projects/listing-07-03/output.txt b/listings/ch07-managing-growing-projects/listing-07-03/output.txt index 2a494c29e..2d06c7fd1 100644 --- a/listings/ch07-managing-growing-projects/listing-07-03/output.txt +++ b/listings/ch07-managing-growing-projects/listing-07-03/output.txt @@ -4,17 +4,29 @@ error[E0603]: module `hosting` is private --> src/lib.rs:9:28 | 9 | crate::front_of_house::hosting::add_to_waitlist(); - | ^^^^^^^ + | ^^^^^^^ --------------- function `add_to_waitlist` is not publicly re-exported + | | + | private module + | +note: the module `hosting` is defined here + --> src/lib.rs:2:5 + | +2 | mod hosting { + | ^^^^^^^^^^^ error[E0603]: module `hosting` is private --> src/lib.rs:12:21 | 12 | front_of_house::hosting::add_to_waitlist(); - | ^^^^^^^ - -error: aborting due to 2 previous errors + | ^^^^^^^ --------------- function `add_to_waitlist` is not publicly re-exported + | | + | private module + | +note: the module `hosting` is defined here + --> src/lib.rs:2:5 + | +2 | mod hosting { + | ^^^^^^^^^^^ For more information about this error, try `rustc --explain E0603`. -error: could not compile `restaurant`. - -To learn more, run the command again with --verbose. +error: could not compile `restaurant` (lib) due to 2 previous errors diff --git a/listings/ch07-managing-growing-projects/listing-07-05/Cargo.toml b/listings/ch07-managing-growing-projects/listing-07-05/Cargo.toml index 8bdd0a418..60cec7cb0 100644 --- a/listings/ch07-managing-growing-projects/listing-07-05/Cargo.toml +++ b/listings/ch07-managing-growing-projects/listing-07-05/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "restaurant" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch07-managing-growing-projects/listing-07-05/output.txt b/listings/ch07-managing-growing-projects/listing-07-05/output.txt index 664c6a480..98d8d6e2a 100644 --- a/listings/ch07-managing-growing-projects/listing-07-05/output.txt +++ b/listings/ch07-managing-growing-projects/listing-07-05/output.txt @@ -4,17 +4,25 @@ error[E0603]: function `add_to_waitlist` is private --> src/lib.rs:9:37 | 9 | crate::front_of_house::hosting::add_to_waitlist(); - | ^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ private function + | +note: the function `add_to_waitlist` is defined here + --> src/lib.rs:3:9 + | +3 | fn add_to_waitlist() {} + | ^^^^^^^^^^^^^^^^^^^^ error[E0603]: function `add_to_waitlist` is private --> src/lib.rs:12:30 | 12 | front_of_house::hosting::add_to_waitlist(); - | ^^^^^^^^^^^^^^^ - -error: aborting due to 2 previous errors + | ^^^^^^^^^^^^^^^ private function + | +note: the function `add_to_waitlist` is defined here + --> src/lib.rs:3:9 + | +3 | fn add_to_waitlist() {} + | ^^^^^^^^^^^^^^^^^^^^ For more information about this error, try `rustc --explain E0603`. -error: could not compile `restaurant`. - -To learn more, run the command again with --verbose. +error: could not compile `restaurant` (lib) due to 2 previous errors diff --git a/listings/ch07-managing-growing-projects/listing-07-07/Cargo.toml b/listings/ch07-managing-growing-projects/listing-07-07/Cargo.toml index 8bdd0a418..60cec7cb0 100644 --- a/listings/ch07-managing-growing-projects/listing-07-07/Cargo.toml +++ b/listings/ch07-managing-growing-projects/listing-07-07/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "restaurant" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch07-managing-growing-projects/listing-07-07/src/lib.rs b/listings/ch07-managing-growing-projects/listing-07-07/src/lib.rs index 74788f6cf..1e7c8b03c 100644 --- a/listings/ch07-managing-growing-projects/listing-07-07/src/lib.rs +++ b/listings/ch07-managing-growing-projects/listing-07-07/src/lib.rs @@ -1,4 +1,3 @@ -// ANCHOR: here mod front_of_house { pub mod hosting { pub fn add_to_waitlist() {} @@ -14,6 +13,3 @@ pub fn eat_at_restaurant() { // 相対パス front_of_house::hosting::add_to_waitlist(); } -// ANCHOR_END: here - -fn main() {} diff --git a/listings/ch07-managing-growing-projects/listing-07-08/Cargo.toml b/listings/ch07-managing-growing-projects/listing-07-08/Cargo.toml index 8bdd0a418..60cec7cb0 100644 --- a/listings/ch07-managing-growing-projects/listing-07-08/Cargo.toml +++ b/listings/ch07-managing-growing-projects/listing-07-08/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "restaurant" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch07-managing-growing-projects/listing-07-08/src/lib.rs b/listings/ch07-managing-growing-projects/listing-07-08/src/lib.rs index a789379ae..b3ddb4f0f 100644 --- a/listings/ch07-managing-growing-projects/listing-07-08/src/lib.rs +++ b/listings/ch07-managing-growing-projects/listing-07-08/src/lib.rs @@ -1,14 +1,10 @@ -// ANCHOR: here -fn serve_order() {} +fn deliver_order() {} mod back_of_house { fn fix_incorrect_order() { cook_order(); - super::serve_order(); + super::deliver_order(); } fn cook_order() {} } -// ANCHOR_END: here - -fn main() {} diff --git a/listings/ch07-managing-growing-projects/listing-07-09/Cargo.toml b/listings/ch07-managing-growing-projects/listing-07-09/Cargo.toml index 8bdd0a418..60cec7cb0 100644 --- a/listings/ch07-managing-growing-projects/listing-07-09/Cargo.toml +++ b/listings/ch07-managing-growing-projects/listing-07-09/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "restaurant" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch07-managing-growing-projects/listing-07-10/Cargo.toml b/listings/ch07-managing-growing-projects/listing-07-10/Cargo.toml index 8bdd0a418..60cec7cb0 100644 --- a/listings/ch07-managing-growing-projects/listing-07-10/Cargo.toml +++ b/listings/ch07-managing-growing-projects/listing-07-10/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "restaurant" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch07-managing-growing-projects/listing-07-11/Cargo.toml b/listings/ch07-managing-growing-projects/listing-07-11/Cargo.toml index 8bdd0a418..60cec7cb0 100644 --- a/listings/ch07-managing-growing-projects/listing-07-11/Cargo.toml +++ b/listings/ch07-managing-growing-projects/listing-07-11/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "restaurant" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch07-managing-growing-projects/listing-07-11/src/lib.rs b/listings/ch07-managing-growing-projects/listing-07-11/src/lib.rs index 3a7568375..cf31a9c97 100644 --- a/listings/ch07-managing-growing-projects/listing-07-11/src/lib.rs +++ b/listings/ch07-managing-growing-projects/listing-07-11/src/lib.rs @@ -1,4 +1,3 @@ -// ANCHOR: here mod front_of_house { pub mod hosting { pub fn add_to_waitlist() {} @@ -9,9 +8,4 @@ use crate::front_of_house::hosting; pub fn eat_at_restaurant() { hosting::add_to_waitlist(); - hosting::add_to_waitlist(); - hosting::add_to_waitlist(); } -// ANCHOR_END: here - -fn main() {} diff --git a/listings/ch07-managing-growing-projects/listing-07-12/Cargo.toml b/listings/ch07-managing-growing-projects/listing-07-12/Cargo.toml index 8bdd0a418..60cec7cb0 100644 --- a/listings/ch07-managing-growing-projects/listing-07-12/Cargo.toml +++ b/listings/ch07-managing-growing-projects/listing-07-12/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "restaurant" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch07-managing-growing-projects/listing-07-12/output.txt b/listings/ch07-managing-growing-projects/listing-07-12/output.txt new file mode 100644 index 000000000..ae7425abc --- /dev/null +++ b/listings/ch07-managing-growing-projects/listing-07-12/output.txt @@ -0,0 +1,28 @@ +$ cargo build + Compiling restaurant v0.1.0 (file:///projects/restaurant) +error[E0433]: failed to resolve: use of undeclared crate or module `hosting` +(エラー: 名前解決に失敗しました: 宣言されていないクレートまたはモジュール`hosting`の使用) + --> src/lib.rs:11:9 + | +11 | hosting::add_to_waitlist(); + | ^^^^^^^ use of undeclared crate or module `hosting` + | (宣言されていないクレートまたはモジュール`hosting`の使用) + | +help: consider importing this module through its public re-export +(ヘルプ: 公開再エクスポートからこのモジュールをインポートすることを検討してください) + | +10 + use crate::hosting; + | + +warning: unused import: `crate::front_of_house::hosting` +(警告: 未使用のインポート: `crate::front_of_house::hosting`) + --> src/lib.rs:7:5 + | +7 | use crate::front_of_house::hosting; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(unused_imports)]` on by default + +For more information about this error, try `rustc --explain E0433`. +warning: `restaurant` (lib) generated 1 warning +error: could not compile `restaurant` (lib) due to 1 previous error; 1 warning emitted diff --git a/listings/ch07-managing-growing-projects/listing-07-12/src/lib.rs b/listings/ch07-managing-growing-projects/listing-07-12/src/lib.rs index 6b0101b7d..afc759423 100644 --- a/listings/ch07-managing-growing-projects/listing-07-12/src/lib.rs +++ b/listings/ch07-managing-growing-projects/listing-07-12/src/lib.rs @@ -1,17 +1,13 @@ -// ANCHOR: here mod front_of_house { pub mod hosting { pub fn add_to_waitlist() {} } } -use self::front_of_house::hosting; +use crate::front_of_house::hosting; -pub fn eat_at_restaurant() { - hosting::add_to_waitlist(); - hosting::add_to_waitlist(); - hosting::add_to_waitlist(); +mod customer { + pub fn eat_at_restaurant() { + hosting::add_to_waitlist(); + } } -// ANCHOR_END: here - -fn main() {} diff --git a/listings/ch07-managing-growing-projects/listing-07-13/Cargo.toml b/listings/ch07-managing-growing-projects/listing-07-13/Cargo.toml index 8bdd0a418..60cec7cb0 100644 --- a/listings/ch07-managing-growing-projects/listing-07-13/Cargo.toml +++ b/listings/ch07-managing-growing-projects/listing-07-13/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "restaurant" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch07-managing-growing-projects/listing-07-13/src/lib.rs b/listings/ch07-managing-growing-projects/listing-07-13/src/lib.rs index 98414aac9..c72994efe 100644 --- a/listings/ch07-managing-growing-projects/listing-07-13/src/lib.rs +++ b/listings/ch07-managing-growing-projects/listing-07-13/src/lib.rs @@ -1,4 +1,3 @@ -// ANCHOR: here mod front_of_house { pub mod hosting { pub fn add_to_waitlist() {} @@ -9,9 +8,4 @@ use crate::front_of_house::hosting::add_to_waitlist; pub fn eat_at_restaurant() { add_to_waitlist(); - add_to_waitlist(); - add_to_waitlist(); } -// ANCHOR_END: here - -fn main() {} diff --git a/listings/ch07-managing-growing-projects/listing-07-14/Cargo.toml b/listings/ch07-managing-growing-projects/listing-07-14/Cargo.toml index 8bdd0a418..60cec7cb0 100644 --- a/listings/ch07-managing-growing-projects/listing-07-14/Cargo.toml +++ b/listings/ch07-managing-growing-projects/listing-07-14/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "restaurant" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch07-managing-growing-projects/listing-07-15/Cargo.toml b/listings/ch07-managing-growing-projects/listing-07-15/Cargo.toml index 8bdd0a418..60cec7cb0 100644 --- a/listings/ch07-managing-growing-projects/listing-07-15/Cargo.toml +++ b/listings/ch07-managing-growing-projects/listing-07-15/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "restaurant" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch07-managing-growing-projects/listing-07-16/Cargo.toml b/listings/ch07-managing-growing-projects/listing-07-16/Cargo.toml index 8bdd0a418..60cec7cb0 100644 --- a/listings/ch07-managing-growing-projects/listing-07-16/Cargo.toml +++ b/listings/ch07-managing-growing-projects/listing-07-16/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "restaurant" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch07-managing-growing-projects/listing-07-17/Cargo.toml b/listings/ch07-managing-growing-projects/listing-07-17/Cargo.toml index 8bdd0a418..60cec7cb0 100644 --- a/listings/ch07-managing-growing-projects/listing-07-17/Cargo.toml +++ b/listings/ch07-managing-growing-projects/listing-07-17/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "restaurant" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch07-managing-growing-projects/listing-07-17/src/lib.rs b/listings/ch07-managing-growing-projects/listing-07-17/src/lib.rs index e948d7c38..45cf1bac9 100644 --- a/listings/ch07-managing-growing-projects/listing-07-17/src/lib.rs +++ b/listings/ch07-managing-growing-projects/listing-07-17/src/lib.rs @@ -1,4 +1,3 @@ -// ANCHOR: here mod front_of_house { pub mod hosting { pub fn add_to_waitlist() {} @@ -9,9 +8,4 @@ pub use crate::front_of_house::hosting; pub fn eat_at_restaurant() { hosting::add_to_waitlist(); - hosting::add_to_waitlist(); - hosting::add_to_waitlist(); } -// ANCHOR_END: here - -fn main() {} diff --git a/listings/ch07-managing-growing-projects/listing-07-18/Cargo.lock b/listings/ch07-managing-growing-projects/listing-07-18/Cargo.lock index c346748e5..2ae9e459e 100644 --- a/listings/ch07-managing-growing-projects/listing-07-18/Cargo.lock +++ b/listings/ch07-managing-growing-projects/listing-07-18/Cargo.lock @@ -1,87 +1,75 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] -name = "bitflags" -version = "1.2.1" +name = "cfg-if" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] -name = "cloudabi" -version = "0.0.3" +name = "getrandom" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8" dependencies = [ - "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "libc", + "wasi", ] -[[package]] -name = "fuchsia-cprng" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "guessing_game" version = "0.1.0" dependencies = [ - "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rand", ] [[package]] name = "libc" -version = "0.2.53" +version = "0.2.86" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7282d924be3275cec7f6756ff4121987bc6481325397dde6ba3e7802b1a8b1c" + +[[package]] +name = "ppv-lite86" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" [[package]] name = "rand" -version = "0.5.6" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ - "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.53 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libc", + "rand_chacha", + "rand_core", ] [[package]] -name = "rand_core" -version = "0.3.1" +name = "rand_chacha" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e12735cf05c9e10bf21534da50a147b924d555dc7a547c42e6bb2d5b6017ae0d" dependencies = [ - "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ppv-lite86", + "rand_core", ] [[package]] name = "rand_core" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "winapi" -version = "0.3.7" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34cf66eb183df1c5876e2dcf6b13d57340741e8dc255b48e40a26de954d06ae7" dependencies = [ - "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "getrandom", ] [[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" +name = "wasi" +version = "0.10.2+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[metadata] -"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" -"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" -"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" -"checksum libc 0.2.53 (registry+https://github.com/rust-lang/crates.io-index)" = "ec350a9417dfd244dc9a6c4a71e13895a4db6b92f0b106f07ebbc3f3bc580cee" -"checksum rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c618c47cd3ebd209790115ab837de41425723956ad3ce2e6a7f09890947cacb9" -"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" -"checksum rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0e7a549d590831370895ab7ba4ea0c1b6b011d106b5ff2da6eee112615e6dc0" -"checksum winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f10e386af2b13e47c89e7236a7a14a086791a2b88ebad6df9bf42040195cf770" -"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" -"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" diff --git a/listings/ch07-managing-growing-projects/listing-07-18/Cargo.toml b/listings/ch07-managing-growing-projects/listing-07-18/Cargo.toml index ad5ca696d..d508e9578 100644 --- a/listings/ch07-managing-growing-projects/listing-07-18/Cargo.toml +++ b/listings/ch07-managing-growing-projects/listing-07-18/Cargo.toml @@ -1,8 +1,7 @@ [package] name = "guessing_game" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] -rand = "0.5.5" +rand = "0.8.5" diff --git a/listings/ch07-managing-growing-projects/listing-07-18/src/main.rs b/listings/ch07-managing-growing-projects/listing-07-18/src/main.rs index 233198a58..7eda7322f 100644 --- a/listings/ch07-managing-growing-projects/listing-07-18/src/main.rs +++ b/listings/ch07-managing-growing-projects/listing-07-18/src/main.rs @@ -10,9 +10,9 @@ use std::{cmp::Ordering, io}; fn main() { println!("Guess the number!"); - let secret_number = rand::thread_rng().gen_range(1, 101); + let secret_number = rand::thread_rng().gen_range(1..=100); - println!("The secret number is: {}", secret_number); + println!("The secret number is: {secret_number}"); println!("Please input your guess."); @@ -24,7 +24,7 @@ fn main() { let guess: u32 = guess.trim().parse().expect("Please type a number!"); - println!("You guessed: {}", guess); + println!("You guessed: {guess}"); match guess.cmp(&secret_number) { Ordering::Less => println!("Too small!"), diff --git a/listings/ch07-managing-growing-projects/listing-07-19/Cargo.toml b/listings/ch07-managing-growing-projects/listing-07-19/Cargo.toml index 8bdd0a418..60cec7cb0 100644 --- a/listings/ch07-managing-growing-projects/listing-07-19/Cargo.toml +++ b/listings/ch07-managing-growing-projects/listing-07-19/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "restaurant" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch07-managing-growing-projects/listing-07-20/Cargo.toml b/listings/ch07-managing-growing-projects/listing-07-20/Cargo.toml index 8bdd0a418..60cec7cb0 100644 --- a/listings/ch07-managing-growing-projects/listing-07-20/Cargo.toml +++ b/listings/ch07-managing-growing-projects/listing-07-20/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "restaurant" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch07-managing-growing-projects/listing-07-21-and-22/Cargo.toml b/listings/ch07-managing-growing-projects/listing-07-21-and-22/Cargo.toml index 8bdd0a418..60cec7cb0 100644 --- a/listings/ch07-managing-growing-projects/listing-07-21-and-22/Cargo.toml +++ b/listings/ch07-managing-growing-projects/listing-07-21-and-22/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "restaurant" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch07-managing-growing-projects/listing-07-21-and-22/src/lib.rs b/listings/ch07-managing-growing-projects/listing-07-21-and-22/src/lib.rs index 065b1b804..d6769556a 100644 --- a/listings/ch07-managing-growing-projects/listing-07-21-and-22/src/lib.rs +++ b/listings/ch07-managing-growing-projects/listing-07-21-and-22/src/lib.rs @@ -4,6 +4,4 @@ pub use crate::front_of_house::hosting; pub fn eat_at_restaurant() { hosting::add_to_waitlist(); - hosting::add_to_waitlist(); - hosting::add_to_waitlist(); } diff --git a/listings/ch07-managing-growing-projects/no-listing-01-use-std-unnested/Cargo.lock b/listings/ch07-managing-growing-projects/no-listing-01-use-std-unnested/Cargo.lock index 2b3d41ad6..2ae9e459e 100644 --- a/listings/ch07-managing-growing-projects/no-listing-01-use-std-unnested/Cargo.lock +++ b/listings/ch07-managing-growing-projects/no-listing-01-use-std-unnested/Cargo.lock @@ -1,87 +1,75 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] -name = "bitflags" -version = "1.2.0" +name = "cfg-if" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] -name = "cloudabi" -version = "0.0.3" +name = "getrandom" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8" dependencies = [ - "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "libc", + "wasi", ] -[[package]] -name = "fuchsia-cprng" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "guessing_game" version = "0.1.0" dependencies = [ - "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rand", ] [[package]] name = "libc" -version = "0.2.51" +version = "0.2.86" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7282d924be3275cec7f6756ff4121987bc6481325397dde6ba3e7802b1a8b1c" + +[[package]] +name = "ppv-lite86" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" [[package]] name = "rand" -version = "0.5.6" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ - "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libc", + "rand_chacha", + "rand_core", ] [[package]] -name = "rand_core" -version = "0.3.1" +name = "rand_chacha" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e12735cf05c9e10bf21534da50a147b924d555dc7a547c42e6bb2d5b6017ae0d" dependencies = [ - "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ppv-lite86", + "rand_core", ] [[package]] name = "rand_core" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "winapi" -version = "0.3.7" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34cf66eb183df1c5876e2dcf6b13d57340741e8dc255b48e40a26de954d06ae7" dependencies = [ - "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "getrandom", ] [[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" +name = "wasi" +version = "0.10.2+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[metadata] -"checksum bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8a606a02debe2813760609f57a64a2ffd27d9fdf5b2f133eaca0b248dd92cdd2" -"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" -"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" -"checksum libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)" = "bedcc7a809076656486ffe045abeeac163da1b558e963a31e29fbfbeba916917" -"checksum rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c618c47cd3ebd209790115ab837de41425723956ad3ce2e6a7f09890947cacb9" -"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" -"checksum rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0e7a549d590831370895ab7ba4ea0c1b6b011d106b5ff2da6eee112615e6dc0" -"checksum winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f10e386af2b13e47c89e7236a7a14a086791a2b88ebad6df9bf42040195cf770" -"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" -"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" diff --git a/listings/ch07-managing-growing-projects/no-listing-01-use-std-unnested/Cargo.toml b/listings/ch07-managing-growing-projects/no-listing-01-use-std-unnested/Cargo.toml index 10932024b..7eda67aea 100644 --- a/listings/ch07-managing-growing-projects/no-listing-01-use-std-unnested/Cargo.toml +++ b/listings/ch07-managing-growing-projects/no-listing-01-use-std-unnested/Cargo.toml @@ -1,10 +1,9 @@ [package] name = "guessing_game" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -rand = "0.5.5" +rand = "0.8.5" diff --git a/listings/ch07-managing-growing-projects/no-listing-01-use-std-unnested/src/main.rs b/listings/ch07-managing-growing-projects/no-listing-01-use-std-unnested/src/main.rs index c46464ec2..ecea756fa 100644 --- a/listings/ch07-managing-growing-projects/no-listing-01-use-std-unnested/src/main.rs +++ b/listings/ch07-managing-growing-projects/no-listing-01-use-std-unnested/src/main.rs @@ -11,9 +11,9 @@ use std::io; fn main() { println!("Guess the number!"); - let secret_number = rand::thread_rng().gen_range(1, 101); + let secret_number = rand::thread_rng().gen_range(1..=100); - println!("The secret number is: {}", secret_number); + println!("The secret number is: {secret_number}"); println!("Please input your guess."); @@ -23,7 +23,7 @@ fn main() { .read_line(&mut guess) .expect("Failed to read line"); - println!("You guessed: {}", guess); + println!("You guessed: {guess}"); match guess.cmp(&secret_number) { Ordering::Less => println!("Too small!"), diff --git a/listings/ch07-managing-growing-projects/no-listing-02-extracting-hosting/Cargo.toml b/listings/ch07-managing-growing-projects/no-listing-02-extracting-hosting/Cargo.toml index 8bdd0a418..60cec7cb0 100644 --- a/listings/ch07-managing-growing-projects/no-listing-02-extracting-hosting/Cargo.toml +++ b/listings/ch07-managing-growing-projects/no-listing-02-extracting-hosting/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "restaurant" version = "0.1.0" -authors = ["Your Name "] -edition = "2018" +edition = "2021" [dependencies] diff --git a/listings/ch07-managing-growing-projects/no-listing-02-extracting-hosting/src/lib.rs b/listings/ch07-managing-growing-projects/no-listing-02-extracting-hosting/src/lib.rs index 065b1b804..d6769556a 100644 --- a/listings/ch07-managing-growing-projects/no-listing-02-extracting-hosting/src/lib.rs +++ b/listings/ch07-managing-growing-projects/no-listing-02-extracting-hosting/src/lib.rs @@ -4,6 +4,4 @@ pub use crate::front_of_house::hosting; pub fn eat_at_restaurant() { hosting::add_to_waitlist(); - hosting::add_to_waitlist(); - hosting::add_to_waitlist(); } diff --git a/listings/ch07-managing-growing-projects/quick-reference-example/Cargo.lock b/listings/ch07-managing-growing-projects/quick-reference-example/Cargo.lock new file mode 100644 index 000000000..4773c201d --- /dev/null +++ b/listings/ch07-managing-growing-projects/quick-reference-example/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "backyard" +version = "0.1.0" diff --git a/listings/ch07-managing-growing-projects/quick-reference-example/Cargo.toml b/listings/ch07-managing-growing-projects/quick-reference-example/Cargo.toml new file mode 100644 index 000000000..6e904abbe --- /dev/null +++ b/listings/ch07-managing-growing-projects/quick-reference-example/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "backyard" +version = "0.1.0" +edition = "2021" + +[dependencies] diff --git a/listings/ch07-managing-growing-projects/quick-reference-example/output.txt b/listings/ch07-managing-growing-projects/quick-reference-example/output.txt new file mode 100644 index 000000000..e36a45eb0 --- /dev/null +++ b/listings/ch07-managing-growing-projects/quick-reference-example/output.txt @@ -0,0 +1,5 @@ +$ cargo run + Compiling backyard v0.1.0 (file:///projects/backyard) + Finished dev [unoptimized + debuginfo] target(s) in 0.36s + Running `target/debug/backyard` +I'm growing Asparagus! diff --git a/listings/ch07-managing-growing-projects/quick-reference-example/src/garden.rs b/listings/ch07-managing-growing-projects/quick-reference-example/src/garden.rs new file mode 100644 index 000000000..6c7f9b1cb --- /dev/null +++ b/listings/ch07-managing-growing-projects/quick-reference-example/src/garden.rs @@ -0,0 +1 @@ +pub mod vegetables; diff --git a/listings/ch07-managing-growing-projects/quick-reference-example/src/garden/vegetables.rs b/listings/ch07-managing-growing-projects/quick-reference-example/src/garden/vegetables.rs new file mode 100644 index 000000000..b00f785ef --- /dev/null +++ b/listings/ch07-managing-growing-projects/quick-reference-example/src/garden/vegetables.rs @@ -0,0 +1,2 @@ +#[derive(Debug)] +pub struct Asparagus {} diff --git a/listings/ch07-managing-growing-projects/quick-reference-example/src/main.rs b/listings/ch07-managing-growing-projects/quick-reference-example/src/main.rs new file mode 100644 index 000000000..7a024a9a0 --- /dev/null +++ b/listings/ch07-managing-growing-projects/quick-reference-example/src/main.rs @@ -0,0 +1,8 @@ +use crate::garden::vegetables::Asparagus; + +pub mod garden; + +fn main() { + let plant = Asparagus {}; + println!("I'm growing {:?}!", plant); +} diff --git a/src/ch07-00-managing-growing-projects-with-packages-crates-and-modules.md b/src/ch07-00-managing-growing-projects-with-packages-crates-and-modules.md index 77ed82d97..415f39404 100644 --- a/src/ch07-00-managing-growing-projects-with-packages-crates-and-modules.md +++ b/src/ch07-00-managing-growing-projects-with-packages-crates-and-modules.md @@ -4,44 +4,43 @@ # 肥大化していくプロジェクトをパッケージ、クレート、モジュールを利用して管理する -大きなプログラムを書く時、そのすべてを頭の中に入れておくのは不可能になるため、コードのまとまりを良くすることが重要になります。 +書いているプログラムが大きいときほど、コードを整理しておくことはますます重要になります。 関係した機能をまとめ、異なる特徴を持つコードを分割することにより、特定の機能を実装しているコードを見つけたり、機能を変更したりするためにどこを探せば良いのかを明確にできます。 私達がこれまでに書いてきたプログラムは、一つのファイル内の一つのモジュール内にありました。 -プロジェクトが大きくなるにつれて、これを複数のモジュールに、ついで複数のファイルに分割することで、プログラムを整理することができます。 +プロジェクトが大きくなるにつれて、これを複数のモジュールに、ついで複数のファイルに分割することで、プログラムを整理するべきです。 パッケージは複数のバイナリクレートからなり、またライブラリクレートを1つもつこともできます。 パッケージが大きくなるにつれて、その一部を抜き出して分離したクレートにし、外部依存とするのもよいでしょう。 この章ではそれらのテクニックすべてを学びます。 相互に関係し合い、同時に成長するパッケージの集まりからなる巨大なプロジェクトには、 -Cargoがワークスペースという機能を提供します。これは14章の[Cargoワークスペース][workspaces]で解説します。 +Cargoが*ワークスペース*という機能を提供します。これは14章の[Cargoワークスペース][workspaces]で解説します。 -機能をグループにまとめられることに加え、実装の詳細がカプセル化されることにより、コードをより高いレベルで再利用できるようになります: -手続きを実装し終えてしまえば、他のコードはそのコードの公開されたインターフェースを通じて、実装の詳細を知ることなくそのコードを呼び出すことができるのです。 +実装の詳細をカプセル化することについても議論します。カプセル化によって、コードをより高いレベルで再利用できるようになります: +手続きを実装し終えてしまえば、他のコードはその公開されたインターフェースを通じて、実装の詳細を知る必要なくそのコードを呼び出すことができるのです。 コードをどう書くかによって、どの部分が他のコードにも使える公開のものになるのか、それとも自分だけが変更できる非公開のものになるのかが決定されます。 これもまた、記憶しておくべき細部を制限してくれる方法のひとつです。 diff --git a/src/ch07-01-packages-and-crates.md b/src/ch07-01-packages-and-crates.md index 05320c41e..fd5417e1d 100644 --- a/src/ch07-01-packages-and-crates.md +++ b/src/ch07-01-packages-and-crates.md @@ -4,29 +4,80 @@ ## パッケージとクレート 最初に学ぶモジュールシステムの要素は、パッケージとクレートです。 -クレートはバイナリかライブラリのどちらかです。 -*クレートルート (crate root)* とは、Rustコンパイラの開始点となり、クレートのルートモジュールを作るソースファイルのことです(モジュールについて詳しくは[「モジュールを定義して、スコープとプライバシーを制御する」][modules]のセクションで説明します)。 -*パッケージ* はある機能群を提供する1つ以上のクレートです。 + + +*クレート (crate)* は、Rustコンパイラが一度に考慮する最小限のコードです。 +`cargo`を実行するのではなく、(ちょうど第1章の「Rustプログラムを書いて走らせる」節でやったように)単一のソースコードファイルを渡して`rustc`を実行した場合でも、 +コンパイラはそのファイルをクレートとしてみなします。 +クレートはモジュールを含むことができ、モジュールは、クレートとともにコンパイルされる他のファイル内で定義することができます。 +このことについてはこれからの節で見ていきます。 + + +クレートは2種類の形態のうちいずれかです: バイナリクレートか、ライブラリクレートです。 +*バイナリクレート (binary crate)* は、コマンドラインプログラムやサーバなどの実行可能形式にコンパイルされ、実行することができるプログラムです。 +どのバイナリクレートも、その実行可能形式が実行されたときに何が起きるかを定義する`main`と呼ばれる関数を持たなくてはなりません。 +今まで作ってきたクレートはすべてバイナリクレートでした。 + + +*ライブラリクレート (library crate)* は`main`関数を持たず、実行可能形式へとコンパイルされません。 +代わりに、複数のプロジェクトで共有されることを想定した機能を定義するものです。 +例えば、[第2章][rand]で使用した`rand`クレートは乱数を生成する機能を提供します。 +Rustaceanが「クレート」と言うときの、ほとんどの場合それはライブラリクレートのことであり、 +Rustaceanは「クレート」を一般的なプログラミング概念の「ライブラリ」と同じ意味で使用します。 + + +*クレートルート (crate root)* とは、Rustコンパイラの開始点となり、クレートのルートモジュールを作るソースファイルのことです(モジュールについて詳しくは[「モジュールを定義して、スコープとプライバシーを制御する」][modules]のセクションで説明します)。 + + +*パッケージ (package)* はある機能群を提供する1つ以上のクレートのまとまりです。 パッケージは *Cargo.toml* という、それらのクレートをどのようにビルドするかを説明するファイルを持っています。 +Cargoは実のところパッケージで、今までコードをビルドするために使ってきたコマンドラインツールのためのバイナリクレートを含んでいます。 +Cargoパッケージは、このバイナリクレートが依存するライブラリクレートも含んでいます。 +他のプロジェクトはCargoライブラリクレートに依存することで、Cargoコマンドラインツールが使用するのと同じロジックを使用することもできます。 -パッケージが何を持ってよいかはいくつかのルールで決まっています。 -パッケージは0個か1個のライブラリクレートを持っていないといけません。それ以上は駄目です。 -バイナリクレートはいくらでも持って良いですが、少なくとも(ライブラリでもバイナリでも良いですが)1つのクレートを持っていないといけません。 +パッケージは好きなだけバイナリクレートを持つことができますが、ライブラリクレートは最大で1個しか持つことができません。 +パッケージはライブラリクレートかバイナリクレートを問わず、少なくとも1個のクレートを持っていないといけません。 -このコマンドを入力したとき、Cargoは *Cargo.toml* ファイルを作り、パッケージを作ってくれました。 -*Cargo.toml* の中身を見ても、*src/main.rs* については何も書いてありません。これは、Cargoは *src/main.rs* が、パッケージと同じ名前を持つバイナリクレートのクレートルートであるという慣習に従っているためです。 +`cargo new`を実行した後、Cargoが作成したものを確認するために`ls`を使っています。 +プロジェクトディレクトリ内には *Cargo.toml* ファイルがあり、これがパッケージを構成します。 +また、*main.rs* を含む *src* ディレクトリもあります。 +*Cargo.toml* をテキストエディタで開くと、*src/main.rs* については何も書いていないことに気づくでしょう。 +Cargoは *src/main.rs* が、パッケージと同じ名前を持つバイナリクレートのクレートルートであるという慣習に従っています。 同じように、Cargoはパッケージディレクトリに *src/lib.rs* が含まれていたら、パッケージにはパッケージと同じ名前のライブラリクレートが含まれており、*src/lib.rs* がそのクレートルートなのだと判断します。 Cargoはクレートルートファイルを `rustc`に渡し、ライブラリやバイナリをビルドします。 今、このパッケージには *src/main.rs* しか含まれておらず、つまりこのパッケージは`my-project`という名前のバイナリクレートのみを持っているということです。 -もしパッケージが *src/main.rs* と *src/lib.rs* を持っていたら、クレートは2つになります:どちらもパッケージと同じ名前を持つ、ライブラリクレートとバイナリクレートです。 +もしパッケージが *src/main.rs* と *src/lib.rs* を持っていたら、クレートは2つになります:どちらもパッケージと同じ名前を持つ、バイナリクレートとライブラリクレートです。 ファイルを *src/bin* ディレクトリに置くことで、パッケージは複数のバイナリクレートを持つことができます。それぞれのファイルが別々のバイナリクレートになります。 - - -クレートは、関連した機能を一つのスコープにまとめることで、その機能が複数のプロジェクト間で共有しやすいようにします。 -例えば、[2章][rand]で使った`rand`クレートは、乱数を生成する機能を提供します。 -`rand`クレートを私達のプロジェクトのスコープに持ち込むことで、この機能を私達のプロジェクトで使うことができます。 -`rand`クレートが提供する機能にはすべて、クレートの名前`rand`を使ってアクセスできます。 - - -クレートの機能をそれ自身のスコープの中に入れたままにしておくことは、ある機能が私達のクレートで定義されたのか`rand`クレートで定義されたのかを明確にし、名前の衝突を予防してくれます。 -例えば、`rand`クレートは`Rng`という名前のトレイトを提供しています。 -更に、私達のクレートで`Rng`という名前の`struct`を定義することもできます。 -クレートの機能はそのスコープ内の名前空間に位置づけられているので、`rand`を依存先として追加しても、コンパイラは`Rng`という名前が何を意味するのかについて混乱することはないのです。 -私達のクレートでは、私達の定義した`struct Rng`のことであり、`rand`クレートの`Rng`トレイトには`rand::Rng`でアクセスするというわけです。 - -では、モジュールシステムの話に移りましょう! - [modules]: ch07-02-defining-modules-to-control-scope-and-privacy.html [rand]: ch02-00-guessing-game-tutorial.html#乱数を生成する diff --git a/src/ch07-02-defining-modules-to-control-scope-and-privacy.md b/src/ch07-02-defining-modules-to-control-scope-and-privacy.md index 87c77098d..4ced90bcc 100644 --- a/src/ch07-02-defining-modules-to-control-scope-and-privacy.md +++ b/src/ch07-02-defining-modules-to-control-scope-and-privacy.md @@ -7,86 +7,238 @@ In this section, we’ll talk about modules and other parts of the module system, namely *paths* that allow you to name items; the `use` keyword that brings a path into scope; and the `pub` keyword to make items public. We’ll also discuss -the `as` keyword, external packages, and the glob operator. For now, let’s -focus on modules! +the `as` keyword, external packages, and the glob operator. --> この節では、モジュールと、その他のモジュールシステムの要素 ――すなわち、要素に名前をつけるための *パス* 、パスをスコープに持ち込む`use`キーワード、要素を公開する`pub`キーワード―― について学びます。 また、`as`キーワード、外部パッケージ、glob演算子についても話します。 -とりあえず、今はモジュールに集中しましょう! -*モジュール* はクレート内のコードをグループ化し、可読性と再利用性を上げるのに役に立ちます。 -モジュールは要素の *プライバシー* も制御できます。プライバシーとは、要素がコードの外側で使える *(公開 public)* のか、内部の実装の詳細であり外部では使えない *(非公開 private)* のかです。 +まずは、将来コードを整理するときの簡単なリファレンスとして、規則の一覧を示します。 +その後で各規則を詳細に説明します。 + + +### モジュールのチートシート + + +以下に、モジュール、パス、`use`キーワード、そして`pub`キーワードがコンパイラ内でどう機能するか、そして多くの開発者はどのようにコードを整理するかについての、クイックリファレンスを提供します。 +この章ではこれらの各規則の実例を見ていきますが、ここはモジュールがどう機能するか思い出すために見直すのに良い場所となるでしょう。 + + +- **クレートルートから始める**: クレートをコンパイルするとき、 + コンパイラはまずコンパイル対象のコードとしてクレートルートファイル(通常は、ライブラリクレートでは *src/lib.rs*、バイナリクレートでは *src/main.rs*)の中を探します。 +- **モジュールを宣言する**: クレートルートファイルの中で、新しいモジュールを宣言することができます; + 例えば、`mod garden;`として“garden”モジュールを宣言したとします。コンパイラは以下の場所からモジュールのコードを探します: + - インライン。`mod garden`の後のセミコロンが波かっこで置き換えられているとき、その中 + - *src/garden.rs* ファイルの中 + - *src/garden/mod.rs* ファイルの中 +- **サブモジュールを宣言する**: クレートルート以外のすべてのファイルの中で、サブモジュールを宣言することができます。 + 例えば、*src/garden.rs* 内で`mod vegetables;`と宣言することができます。コンパイラはサブモジュールのコードを、親モジュールに対応するディレクトリ内の以下の場所から探します: + - インライン。`mod vegetables`のすぐ後にセミコロンの代わりに波かっこがあるとき、その中 + - *src/garden/vegetables.rs* ファイルの中 + - *src/garden/vegetables/mod.rs* ファイルの中 +- **モジュール内のコードへのパス**: モジュールがクレートの一部となったら、プライバシー規則が許す限り同じクレート内のどこからでも、そのモジュール内のコードをコードへのパスを使用して参照できます。 + 例えば、garden vegetablesモジュール内の`Asparagus`型は`crate::garden::vegetables::Asparagus`で参照できます。 +- **非公開と公開**: モジュール内のコードはデフォルトでは非公開で、親モジュールからアクセスすることができません。 + モジュールを公開にするには、`mod`ではなく`pub mod`で宣言してください。 + 公開モジュール内の要素も公開にするには、それらの宣言の前に`pub`を付けてください。 +- **`use`キーワード**: `use`キーワードは、長いパスの繰り返しを減らすために、要素へのショートカットをスコープ内に作成します。 + `crate::garden::vegetables::Asparagus`を参照できるスコープ内であれば、`use crate::garden::vegetables::Asparagus;`でショートカットを作成でき、 + 以降はそのスコープ内ではその型を使用するためには`Asparagus`とだけ書けばよくなります。 + + +これらの規則を説明するための例として、ここに`backyard`という名前のバイナリクレートを作成します。 +クレートのディレクトリは、同じく`backyard`と名付けられ、以下のファイルとディレクトリを含んでいます: + +```text +backyard +├── Cargo.lock +├── Cargo.toml +└── src + ├── garden + │   └── vegetables.rs + ├── garden.rs + └── main.rs +``` + + +この場合のクレートルートファイルは *src/main.rs* であり、以下の内容を含んでいます: + + +ファイル名: src/main.rs + +```rust,noplayground,ignore +{{#rustdoc_include ../listings/ch07-managing-growing-projects/quick-reference-example/src/main.rs}} +``` + + +`pub mod garden;`の行は、コンパイラに*src/garden.rs*で見つかるコードを含めるように指示します。 +その内容は: + + +ファイル名: src/garden.rs + +```rust,noplayground,ignore +{{#rustdoc_include ../listings/ch07-managing-growing-projects/quick-reference-example/src/garden.rs}} +``` + + +この`pub mod vegetables;`は *src/garden/vegetables.rs* のコードも含めると言う意味です。 +そのコードは: + +```rust,noplayground,ignore +{{#rustdoc_include ../listings/ch07-managing-growing-projects/quick-reference-example/src/garden/vegetables.rs}} +``` + + +それでは、これらのルールの詳細を知り、実際に試してみましょう! + + +### 関連するコードをモジュールにまとめる + + +*モジュール (module)* はクレート内のコードを整理し、可読性と再利用性を上げるのに役に立ちます。 +モジュール内のコードはデフォルトでは非公開なので、モジュールは要素の*プライバシー (priavacy)* の制御も可能にします。 +非公開の要素は、外部からの使用ができない内部的な実装の詳細です。 +モジュールとそれらの中の要素は公開にするかどうかを選ぶことができ、公開にすると、外部のコードがそれを使用し、それに依存できるようになります。 + 例えば、レストランの機能を提供するライブラリクレートを書いてみましょう。 -実際にレストランを実装することではなく、コードの関係性に注目したいので、関数にシグネチャをつけますが中身は空白のままにします。 +レストランの実装ではなくコードの関係性に注目したいので、関数にシグネチャをつけますが中身は空白のままにします。 -レストラン業界では、レストランの一部を *接客部門 (front of house)* といい、その他を *後方部門 (back of house)* といいます。 +レストラン業界では、レストランの一部を*接客部門 (front of house)* といい、その他を*後方部門 (back of house)* といいます。 接客部門とはお客さんがいるところです。接客係がお客様を席に案内し、給仕係が注文と支払いを受け付け、バーテンダーが飲み物を作ります。 後方部門とはシェフや料理人がキッチンで働き、皿洗い係が食器を片付け、マネージャが管理業務をする場所です。 -私達のクレートを現実のレストランと同じような構造にするために、関数をネストしたモジュールにまとめましょう。 -`restaurant`という名前の新しいライブラリを`cargo new --lib restaurant`と実行することで作成し、Listing 7-1 のコードを *src/lib.rs* に書き込み、モジュールと関数のシグネチャを定義してください。 +私達のクレートをこのような構造にするために、関数をネストしたモジュールにまとめましょう。 +`restaurant`という名前の新しいライブラリを`cargo new --lib restaurant`と実行することで作成し、リスト7-1のコードを *src/lib.rs* に書き込み、モジュールと関数のシグネチャを定義してください。 +以下が接客部門です: ファイル名: src/lib.rs -```rust -{{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-01/src/lib.rs:here}} +```rust,noplayground +{{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-01/src/lib.rs}} ``` -Listing 7-1: `front_of_house`モジュールにその他のモジュールが含まれ、さらにそれらが関数を含んでいる +リスト7-1: `front_of_house`モジュールにその他のモジュールが含まれ、さらにそれらが関数を含んでいる -モジュールは、`mod`キーワードを書き、次にモジュールの名前(今回の場合、`front_of_house`)を指定することで定義されます。 +モジュールは、`mod`キーワードと、それに続くモジュールの名前(今回の場合、`front_of_house`)によって定義されます。 +次にモジュールの本体が波かっこの中に入ります。 モジュールの中には、今回だと`hosting`と`serving`のように、他のモジュールをおくこともできます。 -モジュールにはその他の要素の定義も置くことができます。例えば、構造体、enum、定数、トレイト、そして(Listing 7-1のように)関数です。 +モジュールにはその他の要素の定義も置くことができます。例えば、構造体、enum、定数、トレイト、そして(リスト7-1のように)関数です。 モジュールを使うことで、関連する定義を一つにまとめ、関連する理由を名前で示せます。 このコードを使うプログラマーは、定義を全部読むことなく、グループ単位でコードを読み進められるので、欲しい定義を見つけ出すのが簡単になるでしょう。 @@ -104,7 +256,7 @@ known as the *module tree*. -Listing 7-2は、Listing 7-1の構造のモジュールツリーを示しています。 +リスト7-2は、リスト7-1の構造のモジュールツリーを示しています。 ```text crate @@ -122,21 +274,20 @@ crate Listing 7-2: The module tree for the code in Listing 7-1 --> -Listing 7-2: Listing 7-1 のコードのモジュールツリー +リスト7-2: リスト7-1 のコードのモジュールツリー -このツリーを見ると、どのモジュールがどのモジュールの中にネストしているのかがわかります(例えば、`hosting`は`front_of_house`の中にネストしています)。 -また、いくつかのモジュールはお互いに *兄弟* の関係にある、つまり、同じモジュール内で定義されていることもわかります(例えば`hosting`と`serving`は`front_of_house`で定義されています)。 -他にも、家族関係の比喩を使って、モジュールAがモジュールBの中に入っている時、AはBの *子* であるといい、BはAの *親* であるといいます。 +このツリーを見ると、どのモジュールがどのモジュールの中にネストしているのかがわかります; 例えば、`hosting`は`front_of_house`の中にネストしています。 +また、いくつかのモジュールはお互いに*兄弟 (siblings)* の関係にある、つまり、同じモジュール内で定義されていることもわかります; 例えば`hosting`と`serving`は`front_of_house`で定義されている兄弟同士です。 +他にも、モジュールAがモジュールBの中に入っている時、AはBの*子 (child)* であるといい、BはAの*親 (parent)* であるといいます。 モジュールツリー全体が、暗黙のうちに作られた`crate`というモジュールの下にあることにも注目してください。 ファイルシステムの中を移動する時と同じように、Rustにモジュールツリー内の要素を見つけるためにはどこを探せばいいのか教えるためにパスを使います。 -関数を呼び出したいなら、そのパスを知っていなければなりません。 +関数を呼び出すためには、そのパスを知っていなければなりません。 -* *絶対パス* は、クレートの名前か`crate`という文字列を使うことで、クレートルートからスタートします。 -* *相対パス* は、`self`、`super`または今のモジュール内の識別子を使うことで、現在のモジュールからスタートします。 +* *絶対パス* は、クレートルートを起点とするフルパスです; + 絶対パスは、外部のクレートに属するコードに関してはそのクレート名で始まり、現在のクレートに属するコードに関してはリテラル`crate`で始まります。 +* *相対パス* は、現在のモジュールを起点とし、`self`、`super`、または今のモジュール内の識別子を使います。 -Listing 7-1の例に戻ってみましょう。 -`add_to_waitlist`関数をどうやって呼べばいいでしょうか? -すなわち、`add_to_waitlist`のパスは何でしょうか? -Listing 7-3 は、モジュールと関数をいくつか取り除いてコードをやや簡潔にしています。 -これを使って、クレートルートに定義された新しい`eat_at_restaurant`という関数から、`add_to_waitlist`関数を呼びだす2つの方法を示しましょう。 +Returning to Listing 7-1, say we want to call the `add_to_waitlist` function. +This is the same as asking: what’s the path of the `add_to_waitlist` function? +Listing 7-3 contains Listing 7-1 with some of the modules and functions +removed. +--> +リスト7-1に戻ってみて、例えば`add_to_waitlist`関数を呼びたいとしましょう。 +これはこう聞くのと同じです: `add_to_waitlist`のパスは何でしょうか? +リスト7-3は、リスト7-1からいくつかのモジュールと関数を削除したものを含んでいます。 + + +これを使って、クレートルートに定義された新しい`eat_at_restaurant`という関数から、`add_to_waitlist`関数を呼び出す2つの方法を示しましょう。 +これらのパスは正しいものですが、この例をこのままではコンパイルできなくしている問題が他に残っています。 +理由はすぐに説明します。 + + `eat_at_restaurant`関数はこのライブラリクレートの公開 (public) APIの1つなので、`pub`キーワードをつけておきます。 -`pub`については、[パスを`pub`キーワードで公開する][pub]の節でより詳しく学びます。 -この例はまだコンパイルできないことに注意してください。理由はすぐに説明します。 +`pub`については、[「パスを`pub`キーワードで公開する」][pub]の節でより詳しく学びます。 -Listing 7-3: `add_to_waitlist` 関数を絶対パスと相対パスで呼び出す +リスト7-3: `add_to_waitlist` 関数を絶対パスと相対パスで呼び出す `eat_at_restaurant`で最初に`add_to_waitlist`関数を呼び出す時、絶対パスを使っています。 `add_to_waitlist`関数は`eat_at_restaurant`と同じクレートで定義されているので、`crate`キーワードで絶対パスを始めることができます。 - - -`crate`の後は、`add_to_waitlist`にたどり着くまで、後に続くモジュールを書き込んでいます。 -同じ構造のファイルシステムを想像すれば、`/front_of_house/hosting/add_to_waitlist`とパスを指定して`add_to_waitlist`を実行していることに相当します。 +続けて、`add_to_waitlist`にたどり着くまで、後に続くモジュールを書き込んでいます。 +同じ構造のファイルシステムを想像してもよいでしょう: `/front_of_house/hosting/add_to_waitlist`とパスを指定して`add_to_waitlist`を実行していることに相当します。 `crate`という名前を使ってクレートルートからスタートするというのは、`/`を使ってファイルシステムのルートからスタートするようなものです。 `eat_at_restaurant`で2回目に`add_to_waitlist`関数を呼び出す時、相対パスを使っています。 パスは、モジュールツリーにおいて`eat_at_restaurant`と同じ階層で定義されているモジュールである`front_of_house`からスタートします。 これはファイルシステムで`front_of_house/hosting/add_to_waitlist`というパスを使っているのに相当します。 -名前から始めるのは、パスが相対パスであることを意味します。 +モジュール名から始めるのは、パスが相対パスであることを意味します。 相対パスを使うか絶対パスを使うかは、プロジェクトによって決めましょう。 要素を定義するコードを、その要素を使うコードと別々に動かすか一緒に動かすか、どちらが起こりそうかによって決めるのが良いです。 例えば、`front_of_house`モジュールと`eat_at_restaurant`関数を`customer_experience`というモジュールに移動させると、`add_to_waitlist`への絶対パスを更新しないといけませんが、相対パスは有効なままです。 しかし、`eat_at_restaurant`関数だけを`dining`というモジュールに移動させると、`add_to_waitlist`への絶対パスは同じままですが、相対パスは更新しないといけないでしょう。 -コードの定義と、その要素の呼び出しは独立に動かしそうなので、絶対パスのほうが好ましいです。 +一般論としては、コードの定義と、その要素の呼び出しは独立に動かしたいことが多いと思われるので、絶対パスのほうが好ましいです。 -では、Listing 7-3 をコンパイルしてみて、どうしてこれはまだコンパイルできないのか考えてみましょう! -エラーをListing 7-4 に示しています。 +では、リスト7-3をコンパイルしてみて、どうしてこれはまだコンパイルできないのか考えてみましょう! +エラーをリスト7-4に示しています。 ```console {{#include ../listings/ch07-managing-growing-projects/listing-07-03/output.txt}} @@ -134,16 +139,21 @@ error we get is shown in Listing 7-4. Listing 7-4: Compiler errors from building the code in Listing 7-3 --> -Listing 7-4: Listing 7-3のコードをビルドしたときのコンパイルエラー +リスト7-4: リスト7-3のコードをビルドしたときのコンパイルエラー エラーメッセージは、`hosting`は非公開 (private) だ、と言っています。 言い換えるなら、`hosting`モジュールと`add_to_waitlist`関数へのパスは正しいが、非公開な部分へのアクセスは許可されていないので、Rustがそれを使わせてくれないということです。 +Rustでは、すべての要素(関数、メソッド、構造体、enum、モジュール、そして定数)はデフォルトでは親モジュールに対して非公開です。 +関数や構造体などの要素を非公開にしたければ、モジュールの中に置いてください。 -Rustにおけるプライバシーは、「あらゆる要素(関数、メソッド、構造体、enum、モジュールおよび定数)は標準では非公開」というやり方で動いています。 親モジュールの要素は子モジュールの非公開要素を使えませんが、子モジュールの要素はその祖先モジュールの要素を使えます。 これは、子モジュールは実装の詳細を覆い隠しますが、子モジュールは自分の定義された文脈を見ることができるためです。 -レストランの喩えを続けるなら、レストランの後方部門になったつもりでプライバシーのルールを考えてみてください。レストランの顧客にはそこで何が起こっているのかは非公開ですが、そこで働くオフィスマネージャには、レストランのことは何でも見えるし何でもできるのです。 +レストランの喩えを続けるなら、レストランの後方部門になったつもりでプライバシーのルールを考えてみてください。レストランの顧客にはそこで何が起こっているのかは非公開ですが、そこを運営するオフィスマネージャには、レストランのことは何でも見えるし何でもできるのです。 Rustは、内部実装の詳細を隠すことが標準であるようにモジュールシステムを機能させることを選択しました。 こうすることで、内部のコードのどの部分が、外部のコードを壊すことなく変更できるのかを知ることができます。 -しかし、`pub`キーワードを使って要素を公開することで、子モジュールの内部部品を外部の祖先モジュールに見せることができます。 +しかし、Rustは`pub`キーワードを使って要素を公開することで、子モジュールの内部部品を外部の祖先モジュールに見せるという選択肢も与えています。 -Listing 7-4の、`hosting`モジュールが非公開だと言ってきていたエラーに戻りましょう。 -親モジュールの`eat_at_restaurant`関数が子モジュールの`add_to_waitlist`関数にアクセスできるようにしたいので、`hosting`モジュールに`pub`キーワードをつけます。Listing 7-5のようになります。 +リスト7-4の、`hosting`モジュールが非公開だと言ってきていたエラーに戻りましょう。 +親モジュールの`eat_at_restaurant`関数が子モジュールの`add_to_waitlist`関数にアクセスできるようにしたいので、`hosting`モジュールに`pub`キーワードをつけます。リスト7-5のようになります。 -Listing 7-5: `hosting` モジュールを `pub` として宣言することで`eat_at_restaurant`から使う +リスト7-5: `hosting` モジュールを `pub` として宣言することで`eat_at_restaurant`から使う -残念ながら、Listing 7-5 のコードもListing 7-6 に示されるようにエラーとなります。 +残念ながら、リスト7-5のコードもリスト7-6に示されるようにエラーとなります。 ```console {{#include ../listings/ch07-managing-growing-projects/listing-07-05/output.txt}} @@ -226,27 +233,31 @@ Listing 7-6. Listing 7-6: Compiler errors from building the code in Listing 7-5 --> -Listing 7-6: Listing 7-5 のコードをビルドしたときのコンパイルエラー +リスト7-6: リスト7-5のコードをビルドしたときのコンパイルエラー 何が起きたのでしょう?`pub`キーワードを`mod hosting`の前に追加したことで、このモジュールは公開されました。 この変更によって、`front_of_house`にアクセスできるなら、`hosting`にもアクセスできるようになりました。 しかし`hosting`の *中身* はまだ非公開です。モジュールを公開してもその中身は公開されないのです。 -モジュールに`pub`キーワードがついていても、祖先モジュールのコードはモジュールを参照できるようになるだけです。 - +モジュールに`pub`キーワードがついていても、祖先モジュールのコードはモジュールを参照できるようになるだけで、その内部のコードへのアクセスは許可されません。 +モジュールはコンテナなので、モジュールを公開しただけでは、できることはあまりありません; +さらに先へ進み、モジュール内のひとつまたは複数の要素も公開することを選択する必要があります。 -Listing 7-6 のエラーは`add_to_waitlist`関数が非公開だと言っています。 +リスト7-6のエラーは`add_to_waitlist`関数が非公開だと言っています。 プライバシーのルールは、モジュール同様、構造体、enum、関数、メソッドにも適用されるのです。 ファイル名: src/lib.rs -```rust -{{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-07/src/lib.rs:here}} +```rust,noplayground,test_harness +{{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-07/src/lib.rs}} ``` -Listing 7-7: `pub`キーワードを`mod hosting`と`fn add_to_waitlist`に追加することで、`eat_at_restaurant`からこの関数を呼べるようになる +リスト7-7: `pub`キーワードを`mod hosting`と`fn add_to_waitlist`に追加することで、`eat_at_restaurant`からこの関数を呼べるようになる これでこのコードはコンパイルできます! -絶対パスと相対パスをもう一度確認して、どうして`pub`キーワードを追加することで`add_to_waitlist`のそれらのパスを使えるようになるのか、プライバシールールの観点からもう一度確認してみてみましょう。 +どうして`pub`キーワードを追加することで`add_to_waitlist`のそれらのパスを使えるようになるのか、 +プライバシールールの観点から確認するために、絶対パスと相対パスを見てみましょう。 絶対パスは、クレートのモジュールツリーのルートである`crate`から始まります。 クレートルートの中に`front_of_house`が定義されています。 @@ -310,59 +322,119 @@ function call is valid! `front_of_house`モジュールは`eat_at_restaurant`と同じモジュールで定義されているので、`eat_at_restaurant`が定義されている場所からの相対パスが使えます。 そして、`hosting`と`add_to_waitlist`は`pub`が付いていますから、残りのパスについても問題はなく、この関数呼び出しは有効というわけです。 + +他のプロジェクトからあなたのコードを利用できるようにライブラリクレートを共有するつもりなら、 +公開APIは、クレート利用者があなたのコードとどう相互作用できるかを決定する、クレート利用者との契約となります。 +人々があなたのクレートに依存しやすくするためには、公開APIへの変更の管理に関する多数の考慮事項があります。 +これらの考慮事項はこの本のスコープ外です; このトピックに興味がある場合は、[The Rust API Guidelines][api-guidelines]を参照してください。 + + + +> #### バイナリとライブラリの両方を持つパッケージでのベストプラクティス +> +> パッケージは*src/main.rs*バイナリクレートルートと*src/lib.rs*ライブラリクレートルートの両方を含むことができ、 +> デフォルトでは両方のクレートがパッケージ名を持つことを説明しました。 +> 典型的には、ライブラリとバイナリのクレート両方を含むこのパターンのパッケージでは、バイナリクレートには +> ライブラリクレートのコードを呼び出して、実行可能形式を開始するために必要な最低限のコードを持たせます。 +> こうすることで、ライブラリクレートのコードは共有できるので、 +> 他のプロジェクトはこのパッケージが提供するほとんどの機能を活用することができます。 +> +> モジュールツリーは*src/lib.rs*内に定義してください。 +> その場合、バイナリクレートからは、パッケージ名でから始まるパスを使って公開された要素を使用することができます。 +> バイナリクレートは、そのライブラリクレートを利用する完全に外部のクレートとまったく同じように、 +> ライブラリクレートの利用者になります: 公開APIしか使用することができません。 +> これは良いAPIを設計する助けになります; あなたは作者であるだけでなく、利用者にもなるのです! +> +> [第12章][ch12]では、バイナリクレートとライブラリクレートの両方を含むコマンドラインプログラムを使って、 +> この整理法の実践を示します。 + ### 相対パスを`super`で始める -親モジュールから始まる相対パスなら、`super`を最初につけることで構成できます。 +現在のモジュールやクレートルートではなく、親モジュールから始まる相対パスなら、`super`を最初につけることで構成できます。 ファイルシステムパスを`..`構文で始めるのに似ています。 -どのようなときにこの機能が使いたくなるのでしょう? +`super`を使用することで、親モジュールにあることを知っている要素を参照することができます。 +これにより、そのモジュールが親と密接に関連しているが、いつか親がモジュールツリー内のどこかに移動されるかもしれないという場合に、モジュールツリーを再編成するのがより簡単になるかもしれません。 -シェフが間違った注文を修正し、自分でお客さんに持っていくという状況をモデル化している、Listing 7-8 を考えてみてください。 -`fix_incorrect_order`関数は`serve_order`関数を呼び出すために、`super`から始まる`serve_order`関数へのパスを使っています。 +シェフが間違った注文を修正し、自分でお客さんに持っていくという状況をモデル化している、リスト7-8を考えてみてください。 +`back_of_house`モジュールで定義されている`fix_incorrect_order`関数は、親モジュールで定義されている`deliver_order`関数を呼び出すために、`super`から始まる`deliver_order`関数へのパスを使っています。 ファイル名: src/lib.rs -```rust -{{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-08/src/lib.rs:here}} +```rust,noplayground,test_harness +{{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-08/src/lib.rs}} ``` -Listing 7-8: `super` で始まる相対パスを使って関数を呼び出す +リスト7-8: `super` で始まる相対パスを使って関数を呼び出す `fix_incorrect_order`関数は`back_of_house`モジュールの中にあるので、`super`を使って`back_of_house`の親モジュールにいけます。親モジュールは、今回の場合ルートである`crate`です。 -そこから、`serve_order`を探し、見つけ出します。 +そこから、`deliver_order`を探し、見つけ出します。 成功! -もしクレートのモジュールツリーを再編成することにした場合でも、`back_of_house`モジュールと`serve_order`関数は同じ関係性で有り続け、一緒に動くように思われます。 +もしクレートのモジュールツリーを再編成することにした場合でも、`back_of_house`モジュールと`deliver_order`関数は同じ関係性で有り続け、一緒に動くように思われます。 そのため、`super`を使うことで、将来このコードが別のモジュールに移動するとしても、更新する場所が少なくて済むようにしました。 -構造体やenumも`pub`を使って公開するよう指定できますが、追加の細目がいくつかあります。 +few details extra to the usage of `pub` with structs and enums. If we use `pub` +before a struct definition, we make the struct public, but the struct’s fields +will still be private. We can make each field public or not on a case-by-case +basis. In Listing 7-9, we’ve defined a public `back_of_house::Breakfast` struct +with a public `toast` field but a private `seasonal_fruit` field. This models +the case in a restaurant where the customer can pick the type of bread that +comes with a meal, but the chef decides which fruit accompanies the meal based +on what’s in season and in stock. The available fruit changes quickly, so +customers can’t choose the fruit or even see which fruit they’ll get. +--> +構造体やenumも`pub`を使って公開するよう指定できますが、構造体とenumでの`pub`の使用に関しては追加の細目がいくつかあります。 構造体定義の前に`pub`を使うと、構造体は公開されますが、構造体のフィールドは非公開のままなのです。 それぞれのフィールドを公開するか否かを個々に決められます。 -Listing 7-9 では、公開の`toast`フィールドと、非公開の`seasonal_fruit`フィールドをもつ公開の`back_of_house::Breakfast`構造体を定義しました。 +リスト7-9では、公開の`toast`フィールドと、非公開の`seasonal_fruit`フィールドをもつ公開の`back_of_house::Breakfast`構造体を定義しました。 これは、例えば、レストランで、お客さんが食事についてくるパンの種類は選べるけれど、食事についてくるフルーツは季節と在庫に合わせてシェフが決める、という状況をモデル化しています。 提供できるフルーツはすぐに変わるので、お客さんはフルーツを選ぶどころかどんなフルーツが提供されるのか知ることもできません。 @@ -394,7 +466,7 @@ Listing 7-9 では、公開の`toast`フィールドと、非公開の`seasonal_ --> ファイル名: src/lib.rs -```rust +```rust,noplayground {{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-09/src/lib.rs}} ``` @@ -402,7 +474,7 @@ Listing 7-9 では、公開の`toast`フィールドと、非公開の`seasonal_ Listing 7-9: A struct with some public fields and some private fields --> -Listing 7-9: 公開のフィールドと非公開のフィールドとを持つ構造体 +リスト7-9: 公開のフィールドと非公開のフィールドとを持つ構造体 一方で、enumを公開すると、そのヴァリアントはすべて公開されます。 -Listing 7-10 に示されているように、`pub`は`enum`キーワードの前にだけおけばよいのです。 +リスト7-10に示されているように、`pub`は`enum`キーワードの前にだけおけばよいのです。 ファイル名: src/lib.rs -```rust +```rust,noplayground {{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-10/src/lib.rs}} ``` @@ -446,17 +518,21 @@ Listing 7-10 に示されているように、`pub`は`enum`キーワードの Listing 7-10: Designating an enum as public makes all its variants public --> -Listing 7-10: enumを公開に指定することはそのヴァリアントをすべて公開にする +リスト7-10: enumを公開に指定することはそのヴァリアントをすべて公開にする `Appetizer`というenumを公開したので、`Soup`と`Salad`というヴァリアントも`eat_at_restaurant`で使えます。 + + enumはヴァリアントが公開されてないとあまり便利ではないのですが、毎回enumのすべてのヴァリアントに`pub`をつけるのは面倒なので、enumのヴァリアントは標準で公開されるようになっているのです。 構造体はフィールドが公開されていなくても便利なことが多いので、構造体のフィールドは、`pub`がついてない限り標準で非公開という通常のルールに従うわけです。 @@ -468,4 +544,11 @@ first, and then we’ll show how to combine `pub` and `use`. まだ勉強していない、`pub`の関わるシチュエーションがもう一つあります。モジュールシステムの最後の機能、`use`キーワードです。 `use`自体の勉強をした後、`pub`と`use`を組み合わせる方法についてお見せします。 -[pub]: ch07-03-paths-for-referring-to-an-item-in-the-module-tree.html#%E3%83%91%E3%82%B9%E3%82%92pub%E3%82%AD%E3%83%BC%E3%83%AF%E3%83%BC%E3%83%89%E3%81%A7%E5%85%AC%E9%96%8B%E3%81%99%E3%82%8B + +[pub]: ch07-03-paths-for-referring-to-an-item-in-the-module-tree.html#パスをpubキーワードで公開する +[api-guidelines]: https://rust-lang.github.io/api-guidelines/ +[ch12]: ch12-00-an-io-project.html diff --git a/src/ch07-04-bringing-paths-into-scope-with-the-use-keyword.md b/src/ch07-04-bringing-paths-into-scope-with-the-use-keyword.md index 3048b18a5..c18f17263 100644 --- a/src/ch07-04-bringing-paths-into-scope-with-the-use-keyword.md +++ b/src/ch07-04-bringing-paths-into-scope-with-the-use-keyword.md @@ -4,18 +4,17 @@ ## `use`キーワードでパスをスコープに持ち込む -これまで関数呼び出しのために書いてきたパスは、長く、繰り返しも多くて不便なものでした。 -例えば、Listing 7-7 においては、絶対パスを使うか相対パスを使うかにかかわらず、`add_to_waitlist`関数を呼ぼうと思うたびに`front_of_house`と`hosting`も指定しないといけませんでした。 -ありがたいことに、この手続きを簡単化する方法があります。 -`use`キーワードを使うことで、パスを一度スコープに持ち込んでしまえば、それ以降はパス内の要素がローカルにあるかのように呼び出すことができるのです。 +関数を呼び出すためにパスを略さずに書かなくてはならないのは、繰り返しも多くて不便に感じられるでしょう。 +リスト7-7においては、絶対パスを使うか相対パスを使うかにかかわらず、`add_to_waitlist`関数を呼ぼうと思うたびに`front_of_house`と`hosting`も指定しないといけませんでした。 +ありがたいことに、この手続きを簡単化する方法があります: +一度`use`キーワードを使ってショートカットを作成すれば、そのスコープ内であればどこでも、より短い名前を使用できます。 -Listing 7-11 では、`crate::front_of_house::hosting`モジュールを`eat_at_restaurant`関数のスコープに持ち込むことで、`eat_at_restaurant`において、`hosting::add_to_waitlist`と指定するだけで`add_to_waitlist`関数を呼び出せるようにしています。 +リスト7-11では、`crate::front_of_house::hosting`モジュールを`eat_at_restaurant`関数のスコープに持ち込むことで、`eat_at_restaurant`において、`hosting::add_to_waitlist`と指定するだけで`add_to_waitlist`関数を呼び出せるようにしています。 ファイル名: src/lib.rs -```rust -{{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-11/src/lib.rs:here}} +```rust,noplayground,test_harness +{{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-11/src/lib.rs}} ``` -Listing 7-11: `use` でモジュールをスコープに持ち込む +リスト7-11: `use` でモジュールをスコープに持ち込む -`use`と相対パスで要素をスコープに持ち込むこともできます。 -Listing 7-12 はListing 7-11 と同じふるまいを得るためにどう相対パスを書けば良いかを示しています。 +`use`は、`use`が出現した特定のスコープでのみ使えるショートカットを作成することに注意してください。 +リスト7-12は`eat_at_restaurant`関数を新しい子モジュール`customer`の中に移動していますが、このモジュールは`use`文とは異なるスコープなので、この関数本体はコンパイルできないでしょう: ファイル名: src/lib.rs -```rust -{{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-12/src/lib.rs:here}} +```rust,noplayground,test_harness,does_not_compile,ignore +{{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-12/src/lib.rs}} +``` + + +リスト7-12: `use`文はそれが属するスコープ内にのみ適用される + + +コンパイルエラーは`customer`モジュール内ではショートカットが適用されないことを示しています: + +```console +{{#include ../listings/ch07-managing-growing-projects/listing-07-12/output.txt}} ``` -Listing 7-12: モジュールを`use`と相対パスを使ってスコープに持ち込む +`use`がそのスコープ内で使用されていないという警告も出ていることに気づくでしょう! +この問題を修正するには、`use`も`customer`モジュールの中に移動するか、`customer`子モジュールの中で`super::hosting`によって親モジュールにあるショートカットを参照してください。 -Listing 7-11 を見て、なぜ`use crate::front_of_house::hosting`と書いて`eat_at_restaurant`内で`hosting::add_to_waitlist`と呼び出したのか不思議に思っているかもしれません。Listing 7-13 のように、`use`で`add_to_waitlist`までのパスをすべて指定しても同じ結果が得られるのに、と。 +リスト7-11を見て、なぜ`use crate::front_of_house::hosting`と書いて`eat_at_restaurant`内で`hosting::add_to_waitlist`と呼び出したのか不思議に思っているかもしれません。リスト7-13のように、`use`で`add_to_waitlist`までのパスをすべて指定しても同じ結果が得られるのに、と。 ファイル名: src/lib.rs -```rust -{{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-13/src/lib.rs:here}} +```rust,noplayground,test_harness +{{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-13/src/lib.rs}} ``` -Listing 7-13: `add_to_waitlist` 関数を`use` でスコープに持ち込む。このやりかたは慣例的ではない +リスト7-13: `add_to_waitlist` 関数を`use` でスコープに持ち込む。このやりかたは慣例的ではない -Listing 7-11 も 7-13 もおなじ仕事をしてくれますが、関数をスコープに`use`で持ち込む場合、Listing 7-11 のほうが慣例的なやり方です。 -関数の親モジュールを`use`で持ち込むことで、関数を呼び出す際、毎回親モジュールを指定しなければならないようにすれば、フルパスを繰り返して書くことを抑えつつ、関数がローカルで定義されていないことを明らかにできます。 -Listing 7-13 のコードではどこで`add_to_waitlist`が定義されたのかが不明瞭です。 +リスト7-11も7-13もおなじ仕事をしてくれますが、関数をスコープに`use`で持ち込む場合、リスト7-11のほうが慣例的なやり方です。 +関数の親モジュールを`use`で持ち込むということは、関数を呼び出す際、毎回親モジュールを指定しなければならないということです。 +関数を呼び出すときに親モジュールを指定することで、フルパスを繰り返して書くことを抑えつつ、関数がローカルで定義されていないことを明らかにできます。 +リスト7-13のコードではどこで`add_to_waitlist`が定義されたのかが不明瞭です。 一方で、構造体やenumその他の要素を`use`で持ち込むときは、フルパスを書くのが慣例的です。 -Listing 7-14 は標準ライブラリの`HashMap`構造体をバイナリクレートのスコープに持ち込む慣例的なやり方を示しています。 +リスト7-14は標準ライブラリの`HashMap`構造体をバイナリクレートのスコープに持ち込む慣例的なやり方を示しています。 -Listing 7-14: `HashMap`を慣例的なやり方でスコープに持ち込む +リスト7-14: `HashMap`を慣例的なやり方でスコープに持ち込む 同じ名前の2つの要素を`use`でスコープに持ち込むのはRustでは許されないので、そのときこの慣例は例外的に不可能です。 -Listing 7-15は、同じ名前を持つけれど異なる親モジュールを持つ2つの`Result`型をスコープに持ち込み、それらを参照するやり方を示しています。 +リスト7-15は、同じ名前を持つけれど異なる親モジュールを持つ2つの`Result`型をスコープに持ち込み、それらを参照するやり方を示しています。 ファイル名: src/lib.rs -```rust +```rust,noplayground {{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-15/src/lib.rs:here}} ``` @@ -167,7 +188,7 @@ Listing 7-15は、同じ名前を持つけれど異なる親モジュールを Listing 7-15: Bringing two types with the same name into the same scope requires using their parent modules. --> -Listing 7-15: 同じ名前を持つ2つの型を同じスコープに持ち込むには親モジュールを使わないといけない。 +リスト7-15: 同じ名前を持つ2つの型を同じスコープに持ち込むには親モジュールを使わないといけない。 -同じ名前の2つの型を`use`を使って同じスコープに持ち込むという問題には、もう一つ解決策があります。パスの後に、`as`と型の新しいローカル名、即ちエイリアスを指定すればよいのです。 -Listing 7-16 は、Listing 7-15 のコードを、2つの`Result`型のうち一つを`as`を使ってリネームするという別のやり方で書いたものを表しています。 +同じ名前の2つの型を`use`を使って同じスコープに持ち込むという問題には、もう一つ解決策があります。パスの後に、`as`と型の新しいローカル名、即ち*エイリアス*を指定すればよいのです。 +リスト7-16は、リスト7-15のコードを、2つの`Result`型のうち一つを`as`を使ってリネームするという別のやり方で書いたものを表しています。 ファイル名: src/lib.rs -```rust +```rust,noplayground {{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-16/src/lib.rs:here}} ``` @@ -205,7 +226,7 @@ Listing 7-16 は、Listing 7-15 のコードを、2つの`Result`型のうち一 Listing 7-16: Renaming a type when it’s brought into scope with the `as` keyword --> -Listing 7-16: 型がスコープに持ち込まれた時、`as`キーワードを使ってその名前を変えている +リスト7-16: 型がスコープに持ち込まれた時、`as`キーワードを使ってその名前を変えている 2つめの`use`文では、`std::io::Result`に、`IoResult`という新たな名前を選んでやります。`std::fmt`の`Result`もスコープに持ち込んでいますが、この名前はこれとは衝突しません。 -Listing 7-15もListing 7-16も慣例的とみなされているので、どちらを使っても構いませんよ! +リスト7-15もリスト7-16も慣例的とみなされているので、どちらを使っても構いませんよ! -Listing 7-17 は Listing 7-11 のコードのルートモジュールでの`use`を`pub use`に変更したものを示しています。 +リスト7-17はリスト7-11のコードのルートモジュールでの`use`を`pub use`に変更したものを示しています。 ファイル名: src/lib.rs -```rust -{{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-17/src/lib.rs:here}} +```rust,noplayground,test_harness +{{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-17/src/lib.rs}} ``` -Listing 7-17: `pub use`で、新たなスコープのコードがその名前を使えるようにする +リスト7-17: `pub use`で、新たなスコープのコードがその名前を使えるようにする -`pub use`を使うことで、外部のコードが`hosting::add_to_waitlist`を使って`add_to_waitlist`関数を呼び出せるようになりました。 -`pub use`を使っていなければ、`eat_at_restaurant`関数は`hosting::add_to_waitlist`を自らのスコープ内で使えるものの、外部のコードはこの新しいパスを利用することはできないでしょう。 +この変更を行う前の状態では、外部のコードはパス`restaurant::front_of_house::hosting::add_to_waitlist()`を使用して`add_to_wishlist`関数を呼ばなくてはなりませんでした。 +この`pub use`によってルートモジュールから`hosting`モジュールを再公開された今、外部のコードはパス`restaurant::hosting::add_to_waitlist()`を使用できるようになりました。 再公開は、あなたのコードの内部構造と、あなたのコードを呼び出すプログラマーたちのその領域に関しての見方が異なるときに有用です。 例えば、レストランの比喩では、レストランを経営している人は「接客部門 (front of house)」と「後方部門 (back of house)」のことについて考えるでしょう。 しかし、レストランを訪れるお客さんは、そのような観点からレストランの部門について考えることはありません。 `pub use`を使うことで、ある構造でコードを書きつつも、別の構造で公開するということが可能になります。 こうすることで、私達のライブラリを、ライブラリを開発するプログラマにとっても、ライブラリを呼び出すプログラマにとっても、よく整理されたものとすることができます。 +第14章の[「`pub use`で便利な公開APIをエクスポートする」][ch14-pub-use]の節で、`pub use`の別の例と、それがクレートのドキュメンテーションにどう影響するかを見ることにしましょう。 -標準ライブラリ (`std`) も、私達のパッケージの外部にあるクレートだということに注意してください。 +標準`std`ライブラリも、私達のパッケージの外部にあるクレートだということに注意してください。 標準ライブラリはRust言語に同梱されているので、 *Cargo.toml* を `std`を含むように変更する必要はありません。 しかし、その要素をそこから私達のパッケージのスコープに持ち込むためには、`use`を使って参照する必要はあります。 例えば、`HashMap`には次の行を使います。 @@ -370,7 +396,7 @@ files. For example, these two `use` statements we had in the Guessing Game in Listing 2-4 bring items from `std` into scope: --> 同じクレートか同じモジュールで定義された複数の要素を使おうとする時、それぞれの要素を一行一行並べると、縦に大量のスペースを取ってしまいます。 -例えば、Listing 2-4の数当てゲームで使った次の2つの`use`文が`std`からスコープへ要素を持ち込みました。 +例えば、リスト2-4の数当てゲームで使った次の2つの`use`文が`std`からスコープへ要素を持ち込みました。 代わりに、ネストしたパスを使うことで、同じ一連の要素を1行でスコープに持ち込めます。 -これをするには、Listing 7-18 に示されるように、パスの共通部分を書き、2つのコロンを続け、そこで波括弧で互いに異なる部分のパスのリストを囲みます。 +これをするには、リスト7-18に示されるように、パスの共通部分を書き、2つのコロンを続け、そこで波括弧で互いに異なる部分のパスのリストを囲みます。 -Listing 7-18: 同じプレフィックスをもつ複数の要素をスコープに持ち込むためにネストしたパスを指定する +リスト7-18: 同じプレフィックスをもつ複数の要素をスコープに持ち込むためにネストしたパスを指定する ネストしたパスはパスのどの階層においても使うことができます。これはサブパスを共有する2つの`use`文を合体させるときに有用です。 -例えば、Listing 7-19 は2つの`use`文を示しています:1つは`std::io`をスコープに持ち込み、もう一つは`std::io::Write`をスコープに持ち込んでいます。 +例えば、リスト7-19は2つの`use`文を示しています:1つは`std::io`をスコープに持ち込み、もう一つは`std::io::Write`をスコープに持ち込んでいます。 ファイル名: src/lib.rs -```rust +```rust,noplayground {{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-19/src/lib.rs}} ``` @@ -434,21 +460,21 @@ two `use` statements that share a subpath. For example, Listing 7-19 shows two Listing 7-19: Two `use` statements where one is a subpath of the other --> -Listing 7-19: 片方がもう片方のサブパスである2つの`use`文 +リスト7-19: 片方がもう片方のサブパスである2つの`use`文 -これらの2つのパスの共通部分は`std::io`であり、そしてこれは最初のパスにほかなりません。これらの2つのパスを1つの`use`文へと合体させるには、Listing 7-20 に示されるように、ネストしたパスに`self`を使いましょう。 +これらの2つのパスの共通部分は`std::io`であり、そしてこれは最初のパスにほかなりません。これらの2つのパスを1つの`use`文へと合体させるには、リスト7-20に示されるように、ネストしたパスに`self`を使いましょう。 ファイル名: src/lib.rs -```rust +```rust,noplayground {{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-20/src/lib.rs}} ``` @@ -456,7 +482,7 @@ the nested path, as shown in Listing 7-20. Listing 7-20: Combining the paths in Listing 7-19 into one `use` statement --> -Listing 7-20: Listing 7-19 のパスを一つの `use` 文に合体させる +リスト7-20: リスト7-19のパスを一つの `use` 文に合体させる パスにおいて定義されているすべての公開要素をスコープに持ち込みたいときは、glob演算子 `*` をそのパスの後ろに続けて書きましょう: @@ -499,5 +525,11 @@ for more information on that pattern. glob演算子はしばしば、テストの際、テストされるあらゆるものを`tests`モジュールに持ち込むために使われます。これについては11章[テストの書き方][writing-tests]の節で話します。 glob演算子はプレリュードパターンの一部としても使われることがあります:そのようなパターンについて、より詳しくは[標準ライブラリのドキュメント](https://doc.rust-lang.org/std/prelude/index.html#other-preludes)をご覧ください。 + +[ch14-pub-use]: ch14-02-publishing-to-crates-io.html#pub-useで便利な公開apiをエクスポートする [rand]: ch02-00-guessing-game-tutorial.html#乱数を生成する [writing-tests]: ch11-01-writing-tests.html#テストの記述法 diff --git a/src/ch07-05-separating-modules-into-different-files.md b/src/ch07-05-separating-modules-into-different-files.md index 2c45efc91..099d05888 100644 --- a/src/ch07-05-separating-modules-into-different-files.md +++ b/src/ch07-05-separating-modules-into-different-files.md @@ -12,21 +12,33 @@ file to make the code easier to navigate. モジュールが大きくなる時、コードを読み進めやすくするため、それらの定義を別のファイルへ移動させたくなるかもしれません。 -例えば、Listing 7-17 のコードからはじめましょう。クレートルートのファイルをListing 7-21 のコードを持つように変更して、`front_of_house`モジュールをそれ専用のファイル`src/front_of_house.rs`に動かしましょう。 +For example, let’s start from the code in Listing 7-17 that had multiple +restaurant modules. We’ll extract modules into files instead of having all the +modules defined in the crate root file. In this case, the crate root file is +*src/lib.rs*, but this procedure also works with binary crates whose crate root +file is *src/main.rs*. +--> +例として、複数のレストランモジュールを持つリスト7-17のコードからはじめましょう。 +すべてのモジュールをクレートルートファイルで定義するのをやめて、複数のファイルにモジュールを抽出することにします。 今回、クレートルートファイルは`src/lib.rs`ですが、この手続きはクレートルートファイルが`src/main.rs`であるバイナリクレートでもうまく行きます。 + +まず、`front_of_house`モジュールをそれ専用のファイルに抽出しましょう。 +`front_of_house`モジュールの波かっこの中のコードを削除し、`mod front_of_house;`宣言だけを残して、 *src/lib.rs* がリスト7-21に示すコードを含むようにしてください。 +リスト7-22で *src/front_of_house.rs* ファイルを作成するまで、このコードはコンパイルできないことに注意してください。 + ファイル名: src/lib.rs -```rust,ignore +```rust,ignore,does_not_compile {{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-21-and-22/src/lib.rs}} ``` @@ -34,13 +46,16 @@ crates whose crate root file is *src/main.rs*. Listing 7-21: Declaring the `front_of_house` module whose body will be in *src/front_of_house.rs* --> -Listing 7-21: `front_of_house`モジュールを宣言する。その中身は`src/front_of_house.rs`内にある +リスト7-21: `front_of_house`モジュールを宣言する。その中身は`src/front_of_house.rs`内にある -そして、 Listing 7-22 のように、*src/front_of_house.rs* には`front_of_house` モジュールの中身の定義を与えます。 +次に リスト7-22に示すように、*src/front_of_house.rs* という名前の新しいファイルに、波かっこの中にあったコードを配置してください。 +コンパイラは、クレートルートで`front_of_house`という名前のモジュール宣言を見つけたときは、このファイルを探せばいいということを知っています。 -Listing 7-22: *src/front_of_house.rs*における、`front_of_house`モジュール内部の定義 +リスト7-22: *src/front_of_house.rs*における、`front_of_house`モジュール内部の定義 + + +`mod`宣言を使用したファイルのロードは、モジュールツリー内で*一回*のみ行う必要があることに注意してください。 +一度コンパイラが、そのファイルがプロジェクトの一部であることを認識したら(そして、`mod`文を書いた場所に応じてモジュールツリー内のどこにコードがあることになるかを認識したら)、[「モジュールツリーの要素を示すためのパス」][paths]節で扱ったように、プロジェクト内の他のファイルは、モジュールが宣言された場所へのパスを使用してロードされたファイルのコードを参照するべきです。 +別の言い方をすれば、`mod`は他のプログラミング言語で見られるような“include”操作では*ありません*。 + + +つづけて`hosting`モジュールをそれ専用のファイルに抽出します。 +`hosting`はルートモジュールの子ではなく`front_of_house`の子モジュールなので、このプロセスは少し異なります。 +`hosting`のためのファイルを、モジュールツリー上での祖先に対応して名付けられた新しいディレクトリ(今回の場合は *src/front_of_house/*)内に配置しましょう。 -`mod front_of_house`の後にブロックではなくセミコロンを使うと、Rustにモジュールの中身をモジュールと同じ名前をした別のファイルから読み込むように命令します。 -私達の例で、つづけて`hosting`モジュールをそれ専用のファイルに抽出するには、`src/front_of_house.rs`が`hosting`モジュールの宣言のみを含むように変更します: +`hosting`の移動を開始するために、`src/front_of_house.rs`が`hosting`モジュールの宣言のみを含むように変更します: -さらに*src/front_of_house* ディレクトリと*src/front_of_house/hosting.rs* ファイルを作って、`hosting`モジュール内でなされていた定義を持つようにします。 +さらに*src/front_of_house* ディレクトリと*hosting.rs* ファイルを作って、`hosting`モジュール内でなされていた定義を持つようにします。 ファイル名: src/front_of_house/hosting.rs -```rust +```rust,ignore {{#rustdoc_include ../listings/ch07-managing-growing-projects/no-listing-02-extracting-hosting/src/front_of_house/hosting.rs}} ``` -定義は別のファイルにあるにもかかわらず、モジュールツリーは同じままであり、`eat_at_restaurant`内での関数呼び出しもなんの変更もなくうまく行きます。 +If we instead put *hosting.rs* in the *src* directory, the compiler would +expect the *hosting.rs* code to be in a `hosting` module declared in the crate +root, and not declared as a child of the `front_of_house` module. The +compiler’s rules for which files to check for which modules’ code means the +directories and files more closely match the module tree. +--> +もし*src*ディレクトリ内に*hosting.rs*を置いた場合は、コンパイラは*hosting.rs*のコードは`front_of_house`モジュールの子としてではなく、クレートルート内で宣言された`hosting`モジュールにあると期待するでしょう。 +コンパイラがどのモジュールのコードのためにどのファイルをチェックするかの規則は、ディレクトリとファイルがモジュールツリーと密接に一致することを意味します。 + + +> ### 別のファイルパス +> +> ここまでRustコンパイラが使用するもっとも慣例的なファイルパスについて扱ってきましたが、Rustは古いスタイルのファイルパスもサポートしています。 +> クレートルート内で宣言された`front_of_house`という名前のモジュールに対して、コンパイラは以下の場所からコードを探します: +> +> * *src/front_of_house.rs* (ここまで扱ってきたもの) +> * *src/front_of_house/mod.rs* (古いスタイルの、今もサポートされているパス) +> +> `front_of_house`のサブモジュールである、`hosting`という名前のモジュールに対しては、コンパイラは以下の場所からコードを探します: +> +> * *src/front_of_house/hosting.rs* (ここまで扱ってきたもの) +> * *src/front_of_house/hosting/mod.rs* (古いスタイルの、今もサポートされているパス) +> +> 同一のモジュールに対して両方のスタイルを使用するとコンパイルエラーになります。 +> 異なるモジュールに対して両方のスタイルを混ぜて使用することは許可されていますが、プロジェクトを見て回る人たちにとって混乱を招くかもしれません。 +> +> *mod.rs* という名前のファイルを使用するスタイルの主な欠点は、プロジェクト内に *mod.rs* という名前のファイルが大量にできることになり、エディタで同時に開いたときに混乱を招きやすいことです。 + + +各モジュールのコードを独立したファイルに移動しましたが、モジュールツリーは同じままです。 +定義が別のファイルにあるにもかかわらず、`eat_at_restaurant`内での関数呼び出しもなんの変更もなくうまく行きます。 このテクニックのおかげで、モジュールが大きくなってきた段階で新しいファイルへ動かす、ということができます。 次の章では、きちんと整理されたあなたのコードで使うことができる、標準ライブラリのいくつかのコレクションデータ構造を見ていきます。 + +[paths]: ch07-03-paths-for-referring-to-an-item-in-the-module-tree.html From 29afdf4545b9495a40579e5476f60f9fe31d25dd Mon Sep 17 00:00:00 2001 From: shinmili Date: Fri, 29 Nov 2024 16:42:20 +0900 Subject: [PATCH 09/10] =?UTF-8?q?=E6=B6=88=E3=81=97=E5=BF=98=E3=82=8C?= =?UTF-8?q?=E3=81=9F=E6=AE=B5=E8=90=BD=E3=82=92=E5=89=8A=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...aths-for-referring-to-an-item-in-the-module-tree.md | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/ch07-03-paths-for-referring-to-an-item-in-the-module-tree.md b/src/ch07-03-paths-for-referring-to-an-item-in-the-module-tree.md index 6754b962d..a632973bf 100644 --- a/src/ch07-03-paths-for-referring-to-an-item-in-the-module-tree.md +++ b/src/ch07-03-paths-for-referring-to-an-item-in-the-module-tree.md @@ -155,16 +155,6 @@ to make an item like a function or struct private, you put it in a module. Rustでは、すべての要素(関数、メソッド、構造体、enum、モジュール、そして定数)はデフォルトでは親モジュールに対して非公開です。 関数や構造体などの要素を非公開にしたければ、モジュールの中に置いてください。 - -モジュールはコードの整理に役立つだけではありません。 -モジュールはRustの *プライバシー境界* も定義します。これは、外部のコードが知ったり、呼び出したり、依存したりしてはいけない実装の詳細をカプセル化する線引きです。 -なので、関数や構造体といった要素を非公開にしたければ、モジュールに入れればよいのです。 - -次に リスト7-22に示すように、*src/front_of_house.rs* という名前の新しいファイルに、波かっこの中にあったコードを配置してください。 +次に、リスト7-22に示すように、*src/front_of_house.rs* という名前の新しいファイルに、波かっこの中にあったコードを配置してください。 コンパイラは、クレートルートで`front_of_house`という名前のモジュール宣言を見つけたときは、このファイルを探せばいいということを知っています。