diff --git a/1.6/ja/book/SUMMARY.md b/1.6/ja/book/SUMMARY.md index 169db56e..784cb4fa 100644 --- a/1.6/ja/book/SUMMARY.md +++ b/1.6/ja/book/SUMMARY.md @@ -31,9 +31,9 @@ * [クロージャ](closures.md) * [共通の関数呼出構文](ufcs.md) * [クレートとモジュール](crates-and-modules.md) - * [`const`と`static`](const-and-static.md) + * [`const` と `static`](const-and-static.md) * [アトリビュート](attributes.md) - * [`type`エイリアス](type-aliases.md) + * [`type` エイリアス](type-aliases.md) * [型間のキャスト](casting-between-types.md) * [関連型](associated-types.md) * [サイズ不定型](unsized-types.md) @@ -48,7 +48,7 @@ * [条件付きコンパイル](conditional-compilation.md) * [ドキュメント](documentation.md) * [イテレータ](iterators.md) - * [並行](concurrency.md) + * [並行性](concurrency.md) * [エラーハンドリング](error-handling.md) * [保証を選ぶ](choosing-your-guarantees.md) * [FFI](ffi.md) diff --git a/1.6/ja/book/advanced-linking.md b/1.6/ja/book/advanced-linking.md index c39ca1f1..abbbf420 100644 --- a/1.6/ja/book/advanced-linking.md +++ b/1.6/ja/book/advanced-linking.md @@ -14,8 +14,8 @@ Rustにおけるリンクの一般的なケースについては本書の前の -どのようにリンクをカスタマイズするかを`rustc`に指示するために、1つの方法があります。それは、`link_args`アトリビュートを使うことです。 -このアトリビュートは`extern`ブロックに適用され、生成物を作るときにリンカに渡したいフラグをそのまま指定します。 +どのようにリンクをカスタマイズするかを `rustc` に指示するために、1つの方法があります。それは、 `link_args` アトリビュートを使うことです。 +このアトリビュートは `extern` ブロックに適用され、生成物を作るときにリンカに渡したいフラグをそのまま指定します。 使い方の例は次のようになります。 ``` no_run @@ -34,14 +34,14 @@ extern {} -これはリンクを実行するための認められた方法ではないため、この機能は現在`feature(link_args)`ゲートによって隠されているということに注意しましょう。 -今は`rustc`がシステムリンカ(多くのシステムでは`gcc`、MSVCでは`link.exe`)に渡すので、追加のコマンドライン引数を提供することには意味がありますが、それが今後もそうだとは限りません。 -将来、`rustc`がネイティブライブラリをリンクするためにLLVMを直接使うようになるかもしれませんし、そのような場合には`link_args`は意味がなくなるでしょう。 -`rustc`に`-C link-args`引数をつけることで、`link_args`アトリビュートと同じような効果を得ることができます。 +これはリンクを実行するための認められた方法ではないため、この機能は現在 `feature(link_args)` ゲートによって隠されているということに注意しましょう。 +今は `rustc` がシステムリンカ(多くのシステムでは `gcc` 、MSVCでは `link.exe` )に渡すので、追加のコマンドライン引数を提供することには意味がありますが、それが今後もそうだとは限りません。 +将来、 `rustc` がネイティブライブラリをリンクするためにLLVMを直接使うようになるかもしれませんし、そのような場合には `link_args` は意味がなくなるでしょう。 +`rustc` に `-C link-args` 引数をつけることで、 `link_args` アトリビュートと同じような効果を得ることができます。 -このアトリビュートは使わ *ない* ことが強く推奨されているので、代わりにもっと正式な`#[link(...)]`アトリビュートを`extern`ブロックに使いましょう。 +このアトリビュートは使わ *ない* ことが強く推奨されているので、代わりにもっと正式な `#[link(...)]` アトリビュートを `extern` ブロックに使いましょう。 # スタティックリンク @@ -55,7 +55,7 @@ extern {} スタティックリンクとは全ての必要なライブラリを含めた成果物を生成する手順のことで、そうすればコンパイルされたプロジェクトを使いたいシステム全てにライブラリをインストールする必要がなくなります。 Rustのみで構築された依存関係はデフォルトでスタティックリンクされます。そのため、Rustをインストールしなくても、作成されたバイナリやライブラリを使うことができます。 -対照的に、ネイティブライブラリ(例えば`libc`や`libm`)はダイナミックリンクされるのが普通です。しかし、これを変更してそれらを同様にスタティックリンクすることも可能です。 +対照的に、ネイティブライブラリ(例えば `libc` や `libm` )はダイナミックリンクされるのが普通です。しかし、これを変更してそれらを同様にスタティックリンクすることも可能です。 @@ -69,8 +69,8 @@ Rustのみで構築された依存関係はデフォルトでスタティック -デフォルトでは、Linux上の全てのRustのプログラムはシステムの`libc`とその他のいくつものライブラリとリンクされます。 -GCCと`glibc`(Linuxにおける最も一般的な`libc`)を使った64ビットLinuxマシンでの例を見てみましょう。 +デフォルトでは、Linux上の全てのRustのプログラムはシステムの `libc` とその他のいくつものライブラリとリンクされます。 +GCCと `glibc` (Linuxにおける最も一般的な `libc` )を使った64ビットLinuxマシンでの例を見てみましょう。 ``` text $ cat example.rs @@ -95,8 +95,8 @@ $ ldd example -スタティックリンクは代わりの`libc`である[`musl`](http://www.musl-libc.org/)によってサポートされています。 -以下の手順に従い、`musl`を有効にした独自バージョンのRustをコンパイルして独自のディレクトリにインストールすることができます。 +スタティックリンクは代わりの `libc` である [`musl`](http://www.musl-libc.org/) によってサポートされています。 +以下の手順に従い、 `musl` を有効にした独自バージョンのRustをコンパイルして独自のディレクトリにインストールすることができます。 ```text $ mkdir musldist @@ -142,7 +142,7 @@ $ du -h musldist/bin/rustc -これで`musl`が有効になったRustのビルドが手に入りました! +これで `musl` が有効になったRustのビルドが手に入りました! 独自のプレフィックスを付けてインストールしたので、試しに実行するときにはシステムがバイナリと適切なライブラリを見付けられることを確かめなければなりません。 ```text @@ -171,5 +171,5 @@ thread '
' panicked at 'failed', example.rs:1 -`cargo build`も`--target`オプションを受け付けるので、あなたのクレートも普通にビルドできるはずです。 -ただし、リンクする前にネイティブライブラリを`musl`向けにリコンパイルする必要はあるかもしれません。 +`cargo build` も `--target` オプションを受け付けるので、あなたのクレートも普通にビルドできるはずです。 +ただし、リンクする前にネイティブライブラリを `musl` 向けにリコンパイルする必要はあるかもしれません。 diff --git a/1.6/ja/book/borrow-and-asref.md b/1.6/ja/book/borrow-and-asref.md index 1cfeb262..5f473f08 100644 --- a/1.6/ja/book/borrow-and-asref.md +++ b/1.6/ja/book/borrow-and-asref.md @@ -1,17 +1,22 @@ -% Borrow and AsRef +% BorrowとAsRef + -The [`Borrow`][borrow] and [`AsRef`][asref] traits are very similar, but -different. Here’s a quick refresher on what these two traits mean. + + +[`Borrow`][borrow] トレイトと [`AsRef`][asref] トレイトはとてもよく似ていますが違うものです。ここでは2つのトレイトの意味を簡単に説明します。 [borrow]: ../std/borrow/trait.Borrow.html [asref]: ../std/convert/trait.AsRef.html + # Borrow -The `Borrow` trait is used when you’re writing a datastructure, and you want to -use either an owned or borrowed type as synonymous for some purpose. + + +`Borrow` トレイトはデータ構造を書いていて、所有型と借用型を同等に扱いたいときに使います。 -For example, [`HashMap`][hashmap] has a [`get` method][get] which uses `Borrow`: + +例えば、 [`HashMap`][hashmap] には `Borrow` を使った [`get` メソッド][get] があります。 ```rust,ignore fn get(&self, k: &Q) -> Option<&V> @@ -22,17 +27,19 @@ fn get(&self, k: &Q) -> Option<&V> [hashmap]: ../std/collections/struct.HashMap.html [get]: ../std/collections/struct.HashMap.html#method.get -This signature is pretty complicated. The `K` parameter is what we’re interested -in here. It refers to a parameter of the `HashMap` itself: + + +このシグネチャは少し複雑です。`K` パラメータに注目してください。これは以下のように `HashMap` 自身のパラメータになっています。 ```rust,ignore struct HashMap { ``` -The `K` parameter is the type of _key_ the `HashMap` uses. So, looking at -the signature of `get()` again, we can use `get()` when the key implements -`Borrow`. That way, we can make a `HashMap` which uses `String` keys, -but use `&str`s when we’re searching: + + + + +`K` パラメータは `HashMap` の「キー」を表す型です。ここで再び `get()` のシグネチャを見ると、キーが `Borrow` を実装しているときに `get()` を使えることが分かります。そのため、以下のように `String` をキーとした `HashMap` を検索するときに `&str` を使うことができます。 ```rust use std::collections::HashMap; @@ -43,13 +50,15 @@ map.insert("Foo".to_string(), 42); assert_eq!(map.get("Foo"), Some(&42)); ``` -This is because the standard library has `impl Borrow for String`. + +これは標準ライブラリが `impl Borrow for String` を提供しているためです。 -For most types, when you want to take an owned or borrowed type, a `&T` is -enough. But one area where `Borrow` is effective is when there’s more than one -kind of borrowed value. This is especially true of references and slices: you -can have both an `&T` or a `&mut T`. If we wanted to accept both of these types, -`Borrow` is up for it: + + + + + +所有型か借用型のどちらかを取りたい場合、たいていは `&T` で十分ですが、借用された値が複数種類ある場合 `Borrow` が役に立ちます。特に参照とスライスは `&T` と `&mut T` のいずれも取りうるため、そのどちらも受け入れたい場合は `Borrow` がよいでしょう。 ```rust use std::borrow::Borrow; @@ -65,12 +74,15 @@ foo(&i); foo(&mut i); ``` -This will print out `a is borrowed: 5` twice. + +上のコードは `a is borrowed: 5` を二度出力します。 + # AsRef -The `AsRef` trait is a conversion trait. It’s used for converting some value to -a reference in generic code. Like this: + + +`AsRef` トレイトは変換用のトレイトです。ジェネリックなコードにおいて、値を参照に変換したい場合に使います。 ```rust let s = "Hello".to_string(); @@ -80,14 +92,18 @@ fn foo>(s: T) { } ``` -# Which should I use? + +# どちらを使うべきか -We can see how they’re kind of the same: they both deal with owned and borrowed -versions of some type. However, they’re a bit different. + + +ここまでで見てきた通り、2つのトレイトは、どちらもある型の所有型バージョンと借用型バージョンの両方を扱う、という意味で同じような種類のものですが、少し違います。 -Choose `Borrow` when you want to abstract over different kinds of borrowing, or -when you’re building a datastructure that treats owned and borrowed values in -equivalent ways, such as hashing and comparison. + + + +いくつかの異なる種類の借用を抽象化したい場合や、ハッシュ化や比較のために所有型と借用型を同等に扱いたいデータ構造を作る場合は `Borrow` を使ってください。 -Choose `AsRef` when you want to convert something to a reference directly, and -you’re writing generic code. + + +ジェネリックなコードで値を参照に直接変換したい場合は `AsRef` を使ってください。 diff --git a/1.6/ja/book/casting-between-types.md b/1.6/ja/book/casting-between-types.md index 7108d957..4a76c16a 100644 --- a/1.6/ja/book/casting-between-types.md +++ b/1.6/ja/book/casting-between-types.md @@ -1,41 +1,59 @@ -% Casting Between Types +% 型間のキャスト + -Rust, with its focus on safety, provides two different ways of casting + +Rustは安全性に焦点を合わせており、異なる型の間を互いにキャストするために二つの異なる方法を提供しています。 +一つは `as` であり、これは安全なキャストに使われます。 +逆に `transmute` は任意のキャストに使え、Rustにおける最も危険なフィーチャの一つです! -# Coercion + +# 型強制 -Coercion between types is implicit and has no syntax of its own, but can -be spelled out with [`as`](#explicit-coercions). + +型強制は暗黙に行われ、それ自体に構文はありませんが、[`as`](#明示的型強制) で書くこともできます。 -Coercion occurs in `let`, `const`, and `static` statements; in + +型強制が現れるのは、 `let` ・ `const` ・ `static` 文、関数呼び出しの引数、構造体初期化の際のフィールド値、そして関数の結果です。 -The most common case of coercion is removing mutability from a reference: + +一番よくある型強制は、参照からミュータビリティを取り除くものです。 - * `&mut T` to `&T` - -An analogous conversion is to remove mutability from a -[raw pointer](raw-pointers.md): + + * `&mut T` から `&T` へ - * `*mut T` to `*const T` - -References can also be coerced to raw pointers: + +似たような変換としては、 [生ポインタ](raw-pointers.md) からミュータビリティを取り除くものがあります。 - * `&T` to `*const T` + + * `*mut T` から `*const T` へ - * `&mut T` to `*mut T` + +参照も同様に、生ポインタへ型強制できます。 -Custom coercions may be defined using [`Deref`](deref-coercions.md). + + * `&T` から `*const T` へ -Coercion is transitive. - + + * `&mut T` から `*mut T` へ + + +[`Deref`](deref-coercions.md) によって、カスタマイズされた型強制が定義されることもあります。 + + +型強制は推移的です。 + + # `as` -The `as` keyword does safe casting: + +`as` というキーワードは安全なキャストを行います。 ```rust let x: i32 = 5; @@ -43,29 +61,43 @@ let x: i32 = 5; let y = x as i64; ``` -There are three major categories of safe cast: explicit coercions, casts -between numeric types, and pointer casts. + +安全なキャストは大きく三つに分類されます。 +明示的型強制、数値型間のキャスト、そして、ポインタキャストです。 -Casting is not transitive: even if `e as U1 as U2` is a valid + +キャストは推移的ではありません。 +`e as U1 as U2` が正しい式であったとしても、 `e as U2` が必ずしも正しいとは限らないのです。 +(実際、この式が正しくなるのは、 `U1` が `U2` へ型強制されるときのみです。) -## Explicit coercions + +## 明示的型強制 -A cast `e as U` is valid if `e` has type `T` and `T` *coerces* to `U`. + +`e as U` というキャストは、 `e` が型 `T` を持ち、かつ `T` が `U` に *型強制* されるとき、有効です。 -## Numeric casts + +## 数値キャスト -A cast `e as U` is also valid in any of the following cases: + +`e as U` というキャストは、以下のどの場合でも有効です。 - * `e` has type `T` and `T` and `U` are any numeric types; *numeric-cast* - * `e` is a C-like enum (with no data attached to the variants), - and `U` is an integer type; *enum-cast* - * `e` has type `bool` or `char` and `U` is an integer type; *prim-int-cast* - * `e` has type `u8` and `U` is `char`; *u8-char-cast* - -For example + + + + +* `e` が型 `T` を持ち、 `T` と `U` が数値型であるとき; *numeric-cast* +* `e` が C-likeな列挙型であり(つまり、ヴァリアントがデータを持っておらず)、 `U` が整数型であるとき; *enum-cast* +* `e` の型が `bool` か `char` であり、 `U` が整数型であるとき; *prim-int-cast* +* `e` が型 `u8` を持ち、 `U` が `char` であるとき; *u8-char-cast* + + +例えば、 ```rust let one = true as u8; @@ -73,9 +105,10 @@ let at_sign = 64 as char; let two_hundred = -56i8 as u8; ``` -The semantics of numeric casts are: + +数値キャストのセマンティクスは以下の通りです。 -* Casting between two integers of the same size (e.g. i32 -> u32) is a no-op + +* サイズの同じ二つの整数間のキャスト (例えば、i32 -> u32) は何も行いません +* サイズの大きい整数から小さい整数へのキャスト (例えば、u32 -> u8) では切り捨てを行います +* サイズの小さい整数から大きい整数へのキャスト (例えば、u8 -> u32) では、 + * 元の整数が符号無しならば、ゼロ拡張を行います + * 元の整数が符号付きならば、符号拡張を行います +* 浮動小数点数から整数へのキャストでは、0方向への丸めを行います + * **[注意: 現在、丸められた値がキャスト先の整数型で扱えない場合、このキャストは未定義動作を引き起こします。][float-int]** + これには Inf や NaN も含まれます。 + これはバグであり、修正される予定です。 +* 整数から浮動小数点数へのキャストでは、必要に応じて丸めが行われて、その整数を表す浮動小数点数がつくられます + (丸め戦略は指定されていません) +* f32 から f64 へのキャストは完全で精度は落ちません +* f64 から f32 へのキャストでは、表現できる最も近い値がつくられます + (丸め戦略は指定されていません) + * **[注意: 現在、値が有限でありながらf32 で表現できる最大(最小)の有限値より大きい(小さい)場合、このキャストは未定義動作を引き起こします。][float-float]** + これはバグであり、修正される予定です。 [float-int]: https://github.com/rust-lang/rust/issues/10184 [float-float]: https://github.com/rust-lang/rust/issues/15536 - -## Pointer casts - -Perhaps surprisingly, it is safe to cast [raw pointers](raw-pointers.md) to and + + +## ポインタキャスト + + +驚くかもしれませんが、いくつかの制約のもとで、 [生ポインタ](raw-pointers.md) と整数の間のキャストや、ポインタと他の型の間のキャストは安全です。 +安全でないのはポインタの参照外しだけなのです。 ```rust -let a = 300 as *const char; // a pointer to location 300 +# // let a = 300 as *const char; // a pointer to location 300 +let a = 300 as *const char; // 300番地へのポインタ let b = a as u32; ``` -`e as U` is a valid pointer cast in any of the following cases: + +`e as U` が正しいポインタキャストであるのは、以下の場合です。 -* `e` has type `*T`, `U` has type `*U_0`, and either `U_0: Sized` or - `unsize_kind(T) == unsize_kind(U_0)`; a *ptr-ptr-cast* - -* `e` has type `*T` and `U` is a numeric type, while `T: Sized`; *ptr-addr-cast* + +* `e` が型 `*T` を持ち、 `U` が `*U_0` であり、 `U_0: Sized` または `unsize_kind(T) == unsize_kind(U_0)` である場合; *ptr-ptr-cast* -* `e` is an integer and `U` is `*U_0`, while `U_0: Sized`; *addr-ptr-cast* + +* `e` が型 `*T` を持ち、 `U` が数値型で、 `T: Sized` である場合; *ptr-addr-cast* -* `e` has type `&[T; n]` and `U` is `*const T`; *array-ptr-cast* + +* `e` が整数、`U` が `*U_0` であり、 `U_0: Sized` である場合; *addr-ptr-cast* -* `e` is a function pointer type and `U` has type `*T`, - while `T: Sized`; *fptr-ptr-cast* + +* `e` が型 `&[T; n]` を持ち、 `U` が `*const T` である場合; *array-ptr-cast* -* `e` is a function pointer type and `U` is an integer; *fptr-addr-cast* + +* `e` が関数ポインタ型であり、 `U` が `*T` であって、`T: Sized` の場合; *fptr-ptr-cast* + +* `e` が関数ポインタ型であり、 `U` が整数型である場合; *fptr-addr-cast* # `transmute` -`as` only allows safe casting, and will for example reject an attempt to -cast four bytes into a `u32`: + +`as` は安全なキャストしか許さず、例えば4つのバイト値を `u32` へキャストすることはできません。 ```rust,ignore let a = [0u8, 0u8, 0u8, 0u8]; -let b = a as u32; // four eights makes 32 +# // let b = a as u32; // four eights makes 32 +let b = a as u32; // 4つの8で32になる ``` -This errors with: + +これは以下のようなメッセージがでて、エラーになります。 -```text + +```text +error: non-scalar cast: `[u8; 4]` as `u32` +let b = a as u32; // 4つの8で32になる + ^~~~~~~~ ``` -This is a ‘non-scalar cast’ because we have multiple values here: the four + +これは「non-scalar cast」であり、複数の値、つまり配列の4つの要素、があることが原因です。 +この種類のキャストはとても危険です。 +なぜなら、複数の裏に隠れた構造がどう実装されているかについて仮定をおいているからです。 +そのためもっと危険なものが必要になります。 -The `transmute` function is provided by a [compiler intrinsic][intrinsics], and + +`transmute` 関数は [コンパイラ intrinsic][intrinsics] によって提供されており、やることはとてもシンプルながら、とても恐ろしいです。 +この関数は、Rustに対し、ある型の値を他の型であるかのように扱うように伝えます。 +これは型検査システムに関係なく行われ、完全に使用者頼みです。 [intrinsics]: intrinsics.html -In our previous example, we know that an array of four `u8`s represents a `u32` + +先ほどの例では、4つの `u8` からなる配列が ちゃんと `u32` を表していることを知った上で、キャストを行おうとしました。 +これは、`as` の代わりに `transmute` を使うことで、次のように書けます。 ```rust use std::mem; @@ -172,15 +248,22 @@ unsafe { } ``` -We have to wrap the operation in an `unsafe` block for this to compile + +コンパイルを成功させるために、この操作は `unsafe` ブロックでくるんであります。 +技術的には、 `mem::transmute` の呼び出しのみをブロックに入れればいいのですが、今回はどこを見ればよいかわかるよう、関連するもの全部を囲んでいます。 +この例では `a` に関する詳細も重要であるため、ブロックにいれてあります。 +ただ、文脈が離れすぎているときは、こう書かないこともあるでしょう。 +そういうときは、コード全体を `unsafe` でくるむことは良い考えではないのです。 + + +`transmute` はほとんどチェックを行わないのですが、最低限、型同士が同じサイズかの確認はします。 +そのため、次の例はエラーになります。 ```rust,ignore use std::mem; @@ -192,11 +275,13 @@ unsafe { } ``` -with: + +エラーメッセージはこうです。 ```text error: transmute called with differently sized types: [u8; 4] (32 bits) to u64 (64 bits) ``` -Other than that, you're on your own! + +ただそれ以外に関しては、自己責任です! diff --git a/1.6/ja/book/comments.md b/1.6/ja/book/comments.md index 809db63d..b5bcc8ee 100644 --- a/1.6/ja/book/comments.md +++ b/1.6/ja/book/comments.md @@ -28,7 +28,7 @@ let x = 5; // this is also a line comment. その他の種類のコメントはドキュメンテーションコメントです。 -ドキュメンテーションコメントは`//`の代わりに`///`を使い、その中でMarkdown記法をサポートします。 +ドキュメンテーションコメントは `//` の代わりに `///` を使い、その中でMarkdown記法をサポートします。 ```rust # /// Adds one to the number given. @@ -52,7 +52,7 @@ fn add_one(x: i32) -> i32 { -もう1つのスタイルのドキュメンテーションコメントに`//!`があります。これは、その後に続く要素ではなく、それを含んでいる要素(例えばクレート、モジュール、関数)にコメントを付けます。 +もう1つのスタイルのドキュメンテーションコメントに `//!` があります。これは、その後に続く要素ではなく、それを含んでいる要素(例えばクレート、モジュール、関数)にコメントを付けます。 一般的にはクレートルート(lib.rs)やモジュールルート(mod.rs)の中で使われます。 ``` @@ -68,11 +68,11 @@ fn add_one(x: i32) -> i32 { ドキュメンテーションコメントを書いているとき、いくつかの使い方の例を提供することは非常に非常に有用です。 -ここでは新しいマクロ、`assert_eq!`を使っていることに気付くでしょう。 -これは2つの値を比較し、もしそれらが互いに等しくなければ`panic!`します。 +ここでは新しいマクロ、 `assert_eq!` を使っていることに気付くでしょう。 +これは2つの値を比較し、もしそれらが互いに等しくなければ `panic!` します。 これはドキュメントの中で非常に便利です。 -もう1つのマクロ、`assert!`は、それに渡された値が`false`であれば`panic!`します。 +もう1つのマクロ、 `assert!` は、それに渡された値が `false` であれば `panic!` します。 -それらのドキュメンテーションコメントからHTMLドキュメントを生成するため、そしてコード例をテストとして実行するためにも[`rustdoc`](documentation.html)ツールを使うことができます! +それらのドキュメンテーションコメントからHTMLドキュメントを生成するため、そしてコード例をテストとして実行するためにも [`rustdoc`](documentation.html) ツールを使うことができます! diff --git a/1.6/ja/book/concurrency.md b/1.6/ja/book/concurrency.md index 8ea6f4f6..688c987f 100644 --- a/1.6/ja/book/concurrency.md +++ b/1.6/ja/book/concurrency.md @@ -1,72 +1,106 @@ -% Concurrency - -Concurrency and parallelism are incredibly important topics in computer -science, and are also a hot topic in industry today. Computers are gaining more -and more cores, yet many programmers aren't prepared to fully utilize them. - -Rust's memory safety features also apply to its concurrency story too. Even -concurrent Rust programs must be memory safe, having no data races. Rust's type -system is up to the task, and gives you powerful ways to reason about -concurrent code at compile time. - -Before we talk about the concurrency features that come with Rust, it's important -to understand something: Rust is low-level enough that the vast majority of -this is provided by the standard library, not by the language. This means that -if you don't like some aspect of the way Rust handles concurrency, you can -implement an alternative way of doing things. -[mio](https://github.com/carllerche/mio) is a real-world example of this -principle in action. - -## Background: `Send` and `Sync` - -Concurrency is difficult to reason about. In Rust, we have a strong, static -type system to help us reason about our code. As such, Rust gives us two traits -to help us make sense of code that can possibly be concurrent. +% 並行性 + + + + + +並行性と並列性はコンピュータサイエンスにおいて極めて重要なトピックであり、現在では産業界でもホットトピックです。 +コンピュータはどんどん多くのコアを持つようになってきていますが、多くのプログラマはまだそれを十分に使いこなす準備ができていません。 + + + + + +Rustのメモリ安全性の機能は、Rustの並行性の話においても適用されます。 +Rustプログラムは並行であっても、メモリ安全でなければならず、データ競合を起こさないのです。 +Rustの型システムはこの問題を扱うことができ、並行なコードをコンパイル時に確かめるための強力な方法を与えます。 + + + + + + + + +Rustが備えている並行性の機能について語る前に、理解しておくべき重要なことがあります。 +それは、Rustは十分にローレベルであるため、その大部分は、言語によってではなく、標準ライブラリによって提供されるということです。 +これは、もしRustの並行性の扱い方に気に入らないところがあれば、代わりの方法を実装できるということを意味します。 +[mio](https://github.com/carllerche/mio) はこの原則を行動で示している実例です。 + + +## 背景: `Send` と `Sync` + + + + +並行性を確かめるのは難しいことです。 +Rustには、コードを確かめるのを支援する強力で静的な型システムがあります。 +そしてRustは、並行になりうるコードの理解を助ける2つのトレイトを提供します。 ### `Send` -The first trait we're going to talk about is -[`Send`](../std/marker/trait.Send.html). When a type `T` implements `Send`, it -indicates that something of this type is able to have ownership transferred -safely between threads. - -This is important to enforce certain restrictions. For example, if we have a -channel connecting two threads, we would want to be able to send some data -down the channel and to the other thread. Therefore, we'd ensure that `Send` was -implemented for that type. - -In the opposite way, if we were wrapping a library with [FFI][ffi] that isn't -threadsafe, we wouldn't want to implement `Send`, and so the compiler will help -us enforce that it can't leave the current thread. + + + + +最初に取り上げるトレイトは [`Send`](../std/marker/trait.Send.html) です。 +型 `T` が `Send` を実装していた場合、 この型のものはスレッド間で安全に受け渡しされる所有権を持てることを意味します。 + + + + + +これはある種の制約を強制させる際に重要です。 +例えば、もし2つのスレッドをつなぐチャネルがあり、そのチャネルを通じてデータを別のスレッドに送れるようにしたいとします。 +このときには、その型について `Send` が実装されているかを確かめます。 + + + + +逆に、スレッドセーフでない [FFI][ffi] でライブラリを包んでいて、 `Send` を実装したくなかったとします。 +このときコンパイラは、そのライブラリが現在のスレッドの外にいかないよう強制することを支援してくれるでしょう。 [ffi]: ffi.html ### `Sync` -The second of these traits is called [`Sync`](../std/marker/trait.Sync.html). -When a type `T` implements `Sync`, it indicates that something -of this type has no possibility of introducing memory unsafety when used from -multiple threads concurrently through shared references. This implies that -types which don't have [interior mutability](mutability.html) are inherently -`Sync`, which includes simple primitive types (like `u8`) and aggregate types -containing them. - -For sharing references across threads, Rust provides a wrapper type called -`Arc`. `Arc` implements `Send` and `Sync` if and only if `T` implements -both `Send` and `Sync`. For example, an object of type `Arc>` cannot -be transferred across threads because -[`RefCell`](choosing-your-guarantees.html#refcellt) does not implement -`Sync`, consequently `Arc>` would not implement `Send`. - -These two traits allow you to use the type system to make strong guarantees -about the properties of your code under concurrency. Before we demonstrate -why, we need to learn how to create a concurrent Rust program in the first -place! - -## Threads - -Rust's standard library provides a library for threads, which allow you to -run Rust code in parallel. Here's a basic example of using `std::thread`: + + + + + + + +2つ目のトレイトは [`Sync`](../std/marker/trait.Sync.html) といいます。 +型 `T` が `Sync` を実装していた場合、この型のものは共有された参照を通じて複数スレッドから並行に使われたとしても、必ずメモリ安全であることを意味します。 +そのため、 [interior mutability](mutability.html) を持たない型はもともと `Sync` であるといえます。 +そのような型としては、 `u8` などの単純なプリミティブ型やそれらを含む合成型などがあります。 + + + + + + + +スレッドをまたいで参照を共有するために、Rustは `Arc` というラッパ型を提供しています。 +`T` が `Send` と `Sync` の両方を実装している時かつその時に限り、 `Arc` は `Send` と `Sync` を実装します。 +例えば、型 `Arc>` のオブジェクトをスレッドをまたいで受け渡すことはできません。 +なぜなら、 [`RefCell`](choosing-your-guarantees.html#refcellt) は `Sync` を実装していないため、 `Arc>` は `Send` を実装しないためです。 + + + + + +これらの2つのトレイトのおかげで、コードの並行性に関する性質を強く保証するのに型システムを使うことができます。 +ただ、それがどうしてかということを示す前に、まずどうやって並行なRustプログラムをつくるかということを学ぶ必要があります! + + +## スレッド + + + +Rustの標準ライブラリはスレッドのためのライブラリを提供しており、それによりRustのコードを並列に走らせることができます。 +これが `std::thread` を使う基本的な例です。 ```rust use std::thread; @@ -78,9 +112,12 @@ fn main() { } ``` -The `thread::spawn()` method accepts a [closure](closures.html), which is executed in a -new thread. It returns a handle to the thread, that can be used to -wait for the child thread to finish and extract its result: + + + +`thread::spawn()` というメソッドは [クロージャ](closures.html) を受け取り、それを新たなスレッドで実行します。 +そして、元のスレッドにハンドルを返します。 +このハンドルは、子スレッドが終了するのを待機しその結果を取り出すのに使うことが出来ます。 ```rust use std::thread; @@ -94,30 +131,48 @@ fn main() { } ``` -Many languages have the ability to execute threads, but it's wildly unsafe. -There are entire books about how to prevent errors that occur from shared -mutable state. Rust helps out with its type system here as well, by preventing -data races at compile time. Let's talk about how you actually share things -between threads. + + + + + +多くの言語はスレッドを実行できますが、それはひどく危険です。 +shared mutable stateによって引き起こされるエラーをいかに防ぐかを丸々あつかった本もあります。 +Rustはこれについて型システムによって、コンパイル時にデータ競合を防ぐことで支援します。 +それでは、実際にどうやってスレッド間での共有を行うかについて話しましょう。 + +> 訳注: "shared mutable state" は 「共有されたミュータブルな状態」という意味ですが、定型句として、訳さずそのまま使用しています。 -## Safe Shared Mutable State + +## 安全な Shared Mutable State -Due to Rust's type system, we have a concept that sounds like a lie: "safe + +Rustの型システムのおかげで、「安全な shared mutable state」という嘘のようにきこえる概念があらわれます。 +shared mutable state がとてもとても悪いものであるということについて、多くのプログラマの意見は一致しています。 -Someone once said this: + +このようなことを言った人がいます。 > Shared mutable state is the root of all evil. Most languages attempt to deal > with this problem through the 'mutable' part, but Rust deals with it by > solving the 'shared' part. -The same [ownership system](ownership.html) that helps prevent using pointers -incorrectly also helps rule out data races, one of the worst kinds of -concurrency bugs. +> 訳: shared mutable state は諸悪の根源だ。 +> 多くの言語は `mutable` の部分を通じてこの問題に対処しようとしている。 +> しかし、Rustは `shared` の部分を解決することで対処する。 -As an example, here is a Rust program that would have a data race in many -languages. It will not compile: + + + +ポインタの誤った使用の防止には [所有権のシステム](ownership.html) が役立ちますが、このシステムはデータ競合を排除する際にも同様に一役買います。 +データ競合は、並行性のバグの中で最悪なものの一つです。 + + + +例として、多くの言語で起こるようなデータ競合を含んだRustプログラムをあげます。 +これは、コンパイルが通りません。 ```ignore use std::thread; @@ -136,7 +191,8 @@ fn main() { } ``` -This gives us an error: + +以下のようなエラーがでます。 ```text 8:17 error: capture of moved value: `data` @@ -144,24 +200,33 @@ This gives us an error: ^~~~ ``` -Rust knows this wouldn't be safe! If we had a reference to `data` in each -thread, and the thread takes ownership of the reference, we'd have three -owners! - -So, we need some type that lets us have more than one reference to a value and -that we can share between threads, that is it must implement `Sync`. - -We'll use `Arc`, Rust's standard atomic reference count type, which -wraps a value up with some extra runtime bookkeeping which allows us to -share the ownership of the value between multiple references at the same time. - -The bookkeeping consists of a count of how many of these references exist to -the value, hence the reference count part of the name. - -The Atomic part means `Arc` can safely be accessed from multiple threads. -To do this the compiler guarantees that mutations of the internal count use -indivisible operations which can't have data races. - + + + +Rustはこれが安全でないだろうと知っているのです! +もし、各スレッドに `data` への参照があり、スレッドごとにその参照の所有権があるとしたら、3人の所有者がいることになってしまうのです! + + + +そのため、1つの値に対して2つ以上の参照を持てるようにして、スレッド間で共有できるような型が必要です。 +そして、その型は `Sync` を実装していなければなりません。 + + + + +Rustの標準アトミック参照カウント型である `Arc` を使いましょう。 +これは複数の参照間で値の所有権を同時に共有できるように、値を特別な実行時の管理用データでくるむものです。 + + + +その管理用データには、値への参照がいくつ存在しているかというカウントが記録されています。 +すなわち名前の「参照カウント」の部分にあたります。 + + + + +「アトミック」という部分は `Arc` が複数スレッドから安全にアクセスできることを意味しています。 +このためにコンパイラは、内部のカウントの更新には、データ競合が起こりえない分割不能な操作が用いられることを保証します。 ```ignore use std::thread; @@ -182,10 +247,14 @@ fn main() { } ``` -We now call `clone()` on our `Arc`, which increases the internal count. -This handle is then moved into the new thread. + + +ここで `Arc` について `clone()` を呼んで、内部のカウントを増やしています。 +そして、このハンドルは新たなスレッドに移動されます。 -And... still gives us an error. + +そうすると... +まだ、エラーがでます。 ```text :11:24 error: cannot borrow immutable borrowed content as mutable @@ -193,18 +262,26 @@ And... still gives us an error. ^~~~ ``` -`Arc` assumes one more property about its contents to ensure that it is safe -to share across threads: it assumes its contents are `Sync`. This is true for -our value if it's immutable, but we want to be able to mutate it, so we need -something else to persuade the borrow checker we know what we're doing. + + + + +`Arc` はスレッドをまたいだ共有を安全にするために、その中身に対してもう一つの仮定をおいています。 +それは、中身が `Sync` であるという仮定です。 +この仮定は値がイミュータブルであるときは真になりますが、今回は値を変化できるようにしたいです。 +そのため、借用チェッカに対し、我々は自分たちが何をやっているかを知っています、と説得するための何かが必要になります。 -It looks like we need some type that allows us to safely mutate a shared value, -for example a type that can ensure only one thread at a time is able to -mutate the value inside it at any one time. + + + +共有された値を安全に変更できるようにするための型が必要そうです。 +例えば、どの時点においても、同時に一つのスレッドのなかでしか値は変更できないということを保証できる型です。 -For that, we can use the `Mutex` type! + +そのためには、 `Mutex` 型を使うことができます! -Here's the working version: + +これが動くバージョンです。 ```rust use std::sync::{Arc, Mutex}; @@ -226,20 +303,24 @@ fn main() { } ``` -Note that the value of `i` is bound (copied) to the closure and not shared -among the threads. + +`i` の値はクロージャへ束縛(コピー)されるだけで、スレッド間で共有されるわけではないことに注意してください。 -Also note that [`lock`](../std/sync/struct.Mutex.html#method.lock) method of -[`Mutex`](../std/sync/struct.Mutex.html) has this signature: + + +また、[`Mutex`](../std/sync/struct.Mutex.html) の [`lock`](../std/sync/struct.Mutex.html#method.lock) メソッドは以下のシグネチャを持つことにも注意してください。 ```ignore fn lock(&self) -> LockResult> ``` -and because `Send` is not implemented for `MutexGuard`, the guard cannot -cross thread boundaries, ensuring thread-locality of lock acquire and release. + + +そして、 `Send` は `MutexGuard` に対して実装されていないため、ガードはスレッドの境界をまたげず、ロックの獲得と解放のスレッドローカル性が保証されています。 -Let's examine the body of the thread more closely: + +それでは、スレッドの中身をさらに詳しく見ていきましょう。 ```rust # use std::sync::{Arc, Mutex}; @@ -258,25 +339,39 @@ thread::spawn(move || { # } ``` -First, we call `lock()`, which acquires the mutex's lock. Because this may fail, -it returns an `Result`, and because this is just an example, we `unwrap()` -it to get a reference to the data. Real code would have more robust error handling -here. We're then free to mutate it, since we have the lock. - -Lastly, while the threads are running, we wait on a short timer. But -this is not ideal: we may have picked a reasonable amount of time to -wait but it's more likely we'll either be waiting longer than -necessary or not long enough, depending on just how much time the -threads actually take to finish computing when the program runs. - -A more precise alternative to the timer would be to use one of the -mechanisms provided by the Rust standard library for synchronizing -threads with each other. Let's talk about one of them: channels. - -## Channels - -Here's a version of our code that uses channels for synchronization, rather -than waiting for a specific time: + + + + +まず、 `lock()` を呼び、mutex のロックを獲得します。 +これは失敗するかもしれないため、`Result` が返されます。 +そして、今回は単なる例なので、データへの参照を得るためにそれを `unwrap()` します。 +実際のコードでは、ここでもっとちゃんとしたエラーハンドリングをするでしょう。 +そうしたら、ロックを持っているので、自由に値を変更できます。 + + + + + + +最後の部分で、スレッドが実行されている間、短いタイマーで待機しています。 +しかし、これはよろしくないです。 +というのも、ちょうどよい待機時間を選んでいた可能性より、必要以上に長い時間待ってしまっていたり、十分に待っていなかったりする可能性の方が高いからです。 +適切な待ち時間というのは、プログラムを実行した際に、実際に計算が終わるまでどれだけの時間がかかったかに依存します。 + + + + +タイマーに代わるより良い選択肢は、Rust標準ライブラリによって提供されている、スレッドがお互いに同期するためのメカニズムを用いることです。 +それでは、そのようなものの一つについて話しましょう。 +チャネルです。 + + +## チャネル + + + +このコードが、適当な時間を待つ代わりに、同期のためにチャネルを使ったバージョンです。 ```rust use std::sync::{Arc, Mutex}; @@ -305,11 +400,14 @@ fn main() { } ``` -We use the `mpsc::channel()` method to construct a new channel. We just `send` -a simple `()` down the channel, and then wait for ten of them to come back. + + +`mpsc::channel()` メソッドを使って、新たなチャネルを生成しています。 +そして、ただの `()` をチャネルを通じて単に `send` し、それが10個戻ってくるのを待機します。 -While this channel is just sending a generic signal, we can send any data that -is `Send` over the channel! + + +このチャネルはただシグナルを送っているだけですが、 `Send` であるデータならばなんでもこのチャネルを通じて送れます! ```rust use std::thread; @@ -334,14 +432,17 @@ fn main() { } ``` -Here we create 10 threads, asking each to calculate the square of a number (`i` -at the time of `spawn()`), and then `send()` back the answer over the channel. - + + +ここでは、10個のスレッドを生成し、それぞれに数値 ( `spawn()` したときの `i` ) の2乗を計算させ、その答えをチャネルを通じて `send()` で送り返させています。 -## Panics + +## パニック -A `panic!` will crash the currently executing thread. You can use Rust's -threads as a simple isolation mechanism: + + +`panic!` は現在実行中のスレッドをクラッシュさせます。 +Rustのスレッドは独立させるための単純なメカニズムとして使うことができます。 ```rust use std::thread; @@ -355,5 +456,6 @@ let result = handle.join(); assert!(result.is_err()); ``` -`Thread.join()` gives us a `Result` back, which allows us to check if the thread -has panicked or not. + + +`Thread.join()` は `Result` を返し、これによってスレッドがパニックしたかどうかをチェックできます。 diff --git a/1.6/ja/book/conditional-compilation.md b/1.6/ja/book/conditional-compilation.md index 07f2afa6..d729b1b2 100644 --- a/1.6/ja/book/conditional-compilation.md +++ b/1.6/ja/book/conditional-compilation.md @@ -39,7 +39,7 @@ Rustには `#[cfg]` という特別なアトリビュートがあり、 -このようなスイッチの有効・無効の切り替えはCargoを利用している場合`Cargo.toml`中の [`[features]` セクション][features] で設定できます。 +このようなスイッチの有効・無効の切り替えはCargoを利用している場合 `Cargo.toml` 中の [`[features]` セクション][features] で設定できます。 [features]: http://doc.crates.io/manifest.html#the-features-section @@ -76,7 +76,7 @@ mod foo { もしこのコードを `cargo build --features "foo"` としてコンパイルを行うと、 `--cfg features="foo"` が `rustc` に渡され、出力には `mod foo` が含まれます。 -もし標準的な `cargo build` でコンパイルを行った場合、`rustc` に追加のフラグは渡されず`foo` モジュールは存在しない事になります。 +もし標準的な `cargo build` でコンパイルを行った場合、`rustc` に追加のフラグは渡されず `foo` モジュールは存在しない事になります。 # cfg_attr diff --git a/1.6/ja/book/dining-philosophers.md b/1.6/ja/book/dining-philosophers.md index 95df8b0c..24fcaae6 100644 --- a/1.6/ja/book/dining-philosophers.md +++ b/1.6/ja/book/dining-philosophers.md @@ -6,7 +6,7 @@ 私たちの2番目のプロジェクトとして、古典的な並行処理問題を考えていきましょう。「食事する哲学者(the dining philosophers)」とよばれる問題です。 -オリジナルは1965年にダイクストラ(Dijkstra)により考案されましたが、ここではトニー・ホーア(Tony Hoare)による1985年の[この論文][paper]を少しばかり脚色したバージョンを用います。 +オリジナルは1965年にダイクストラ(Dijkstra)により考案されましたが、ここではトニー・ホーア(Tony Hoare)による1985年の [この論文][paper] を少しばかり脚色したバージョンを用います。 [paper]: http://www.usingcsp.com/cspbook.pdf @@ -67,13 +67,13 @@ 3. 3番目の哲学者は、アルゴリズムに従って左側のフォークを取上げます。 4. 4番目の哲学者は、アルゴリズムに従って左側のフォークを取上げます。 5. 5番目の哲学者は、アルゴリズムに従って左側のフォークを取上げます。 -6. ...?全てのフォークが取られたのに、誰も食事できません! +6. ...?全てのフォークが取られたのに、誰も食事できません! この問題を解決する方法はいくつかあります。チュートリアルでは独自の解法をとります。 -さっそく、`cargo`を使って新規プロジェクトを作り始めましょう: +さっそく、 `cargo` を使って新規プロジェクトを作り始めましょう: ```bash $ cd ~/projects @@ -83,7 +83,7 @@ $ cd dining_philosophers -それでは、問題をモデル化するところから始めましょう。`src/main.rs`にて、哲学者から手を付けていきます: +それでは、問題をモデル化するところから始めましょう。 `src/main.rs` にて、哲学者から手を付けていきます: ```rust struct Philosopher { @@ -114,8 +114,8 @@ fn main() { -ここでは、哲学者を表す[`struct`(構造体)][struct]を作ります。まずは名前だけで十分でしょう。 -名前には`&str`型ではなく[`String`][string]型を選びました。一般的に、データを所有する型を用いた方が、 +ここでは、哲学者を表す [`struct` (構造体) ][struct] を作ります。まずは名前だけで十分でしょう。 +名前には `&str` 型ではなく [`String`][string] 型を選びました。一般的に、データを所有する型を用いた方が、 データを参照する型の利用よりも簡単になります。 [struct]: structs.html @@ -139,7 +139,7 @@ impl Philosopher { -この`impl`ブロックは`Philosopher`構造体に関する定義を与えます。ここでは、`new`という「関連関数」を定義します。 +この `impl` ブロックは `Philosopher` 構造体に関する定義を与えます。ここでは、 `new` という「関連関数(associated function)」を定義します。 最初の行は次の通りです: ```rust @@ -157,7 +157,7 @@ fn new(name: &str) -> Philosopher { -関数は`&str`型の引数1つ、`name`をとります。これは他の文字列への参照です。そして`Philosopher`構造体のインスタンスを返します。 +関数は `&str` 型の引数1つ、 `name` をとります。これは他の文字列への参照です。そして `Philosopher` 構造体のインスタンスを返します。 ```rust # struct Philosopher { @@ -176,17 +176,17 @@ Philosopher { -関数は新しい`Philosopher`インスタンスを作成し、その`name`フィールドに引数`name`を設定します。 -ここでは引数を直接設定するのではなく、`.to_string()`を呼び出しています。これにより`&str`が指す文字列のコピーが作られ、 -`Philosopher`の`name`フィールド型に合わせた新しい`String`が得られます。 +関数は新しい `Philosopher` インスタンスを作成し、その `name` フィールドに引数 `name` を設定します。 +ここでは引数を直接設定するのではなく、 `.to_string()` を呼び出しています。これにより `&str` が指す文字列のコピーが作られ、 +`Philosopher` の `name` フィールド型に合わせた新しい `String` が得られます。 -なぜ引数に直接`String`を受付けないのかって?いい質問です。仮に`String`をとるとしたら、呼出し元は`&str`値をもっていますから、 -呼出元でメソッドを呼ぶ必要がでしまいます。この利便性の代償として、_常に_コピーが作られてしまいます。 +なぜ引数に直接 `String` を受付けないのかって?いい質問です。仮に `String` をとるとしたら、呼出し元は `&str` 値をもっていますから、 +呼出元でメソッドを呼ぶ必要がでしまいます。この利便性の代償として、 _常に_ コピーが作られてしまいます。 今回のプログラムでは、短い文字列しか与えないことが分かっているため、これは大して重要な問題ではありません。 @@ -195,15 +195,15 @@ Philosopher { -最後の注意点として: ここは`Philosopher`を定義しただけで、何もしていないように見えます。Rust言語は「式ベース」なので、 +最後の注意点として: ここは `Philosopher` を定義しただけで、何もしていないように見えます。Rust言語は「式ベース(expression based)」なので、 Rustではほとんどが値を返す式となります。関数についても同じことが言え―最後の式が自動的に戻り値となります。 -ここでは関数内の最後の式で新しい`Philosopher`を生成し、それを戻り値としているのです。 +ここでは関数内の最後の式で新しい `Philosopher` を生成し、それを戻り値としているのです。 -この`new()`という名前、Rustにとって特別な意味を持ちませんが、構造体の新しいインスタンスを生成する関数としてよく用いられます。 -その理由について話す前に、再び`main()`を見ていきましょう: +この `new()` という名前、Rustにとって特別な意味を持ちませんが、構造体の新しいインスタンスを生成する関数としてよく用いられます。 +その理由について話す前に、再び `main()` を見ていきましょう: ```rust # struct Philosopher { @@ -230,7 +230,7 @@ fn main() { -ここでは、5つの新しい哲学者に対して5つの変数束縛を作ります。仮に`new`関数を定義_しない_なら、次ように書く必要があります: +ここでは、5つの新しい哲学者に対して5つの変数束縛を作ります。仮に `new` 関数を定義 _しない_ なら、次ように書く必要があります: ```rust # struct Philosopher { @@ -247,7 +247,7 @@ fn main() { -これでは面倒ですよね。`new`の利用には他の利点もありますが、今回のような単純なケースでも、 +これでは面倒ですよね。 `new` の利用には他の利点もありますが、今回のような単純なケースでも、 利用側コードをシンプルにできるのです。 @@ -295,14 +295,14 @@ fn main() { -最初は`main()`から見ていきます。哲学者たちに5つの変数束縛を個別に行うのではなく、代わりに`Vec`を用いました。 -`Vec`は「ベクトル」とも呼ばれる、可変長の配列型です。ベクトルの走査には[`for`][for]ループを使っているため、 +最初は `main()` から見ていきます。哲学者たちに5つの変数束縛を個別に行うのではなく、代わりに `Vec` を用いました。 +`Vec` は「ベクタ(vector)」とも呼ばれる、可変長の配列型です。ベクタの走査には [`for`][for] ループを使っているため、 それぞれの哲学者への参照が順番に得られれます。 [for]: loops.html#for -ループ本体の中では、上記で定義した`p.eat()`を呼び出します: +ループ本体の中では、上記で定義した `p.eat()` を呼び出します: ```rust,ignore fn eat(&self) { @@ -315,8 +315,8 @@ fn eat(&self) { -Rustでは、メソッドは明示的な`self`パラメータを取ります。なので`eat()`はメソッドとなり、 -`new()`は`self`を取らないため関連関数となります。最初の`eat()`バージョンでは、哲学者の名前と、 +Rustでは、メソッドは明示的な `self` パラメータを取ります。なので `eat()` はメソッドとなり、 +`new()` は `self` を取らないため関連関数となります。最初の `eat()` バージョンでは、哲学者の名前と、 食事が終わったことを表示するだけです。このプログラムを実行すると次の出力がえられるはずです: ```text @@ -329,7 +329,7 @@ Michel Foucault is done eating. -これだけなら簡単ですね、出来ました!私たちはまだ真の問題を実装していませんから、実際のところは出来ていませんけど! +これだけなら簡単ですね、出来ました!私たちはまだ真の問題を実装していませんから、実際のところは出来ていませんけど! @@ -383,7 +383,7 @@ use std::thread; -`use`は名前をスコープに持ち込みます。標準ライブラリから`thread`モジュールを使いたいので、`use`が必要になります。 +`use` は名前をスコープに持ち込みます。標準ライブラリから `thread` モジュールを使いたいので、 `use` が必要になります。 ```rust,ignore fn eat(&self) { @@ -397,7 +397,7 @@ use std::thread; -今回は間に`sleep`を挟んで、2つのメッセージを出力します。これで哲学者が食事をする時間をシミュレートしましょう。 +今回は間に `sleep` を挟んで、2つのメッセージを出力します。これで哲学者が食事をする時間をシミュレートしましょう。 このプログラムを実行すると、哲学者たちが順番に食事する様子がわかります: @@ -417,7 +417,7 @@ Michel Foucault is done eating. -素晴らしい!ここまで来ました。残る問題はたった1つ: この問題の核心である並行性に関して、実際には手を付けていませんね! +素晴らしい!ここまで来ました。残る問題はたった1つ: この問題の核心である並行性に関して、実際には手を付けていませんね! @@ -470,7 +470,7 @@ fn main() { -`main()`内のループ変更と、1ヵ所の追加で全部です!まずは前半の変更から: +`main()` 内のループ変更と、1ヵ所の追加で全部です!まずは前半の変更から: ```rust,ignore let handles: Vec<_> = philosophers.into_iter().map(|p| { @@ -493,10 +493,10 @@ let handles: Vec<_> = -ここでは新しい束縛、`handles`を導入します。今から新しいスレッドを作成していきますが、今から新しいスレッドを作成していきますが、 +ここでは新しい束縛、 `handles` を導入します。今から新しいスレッドを作成していきますが、 スレッドはそのスレッドを制御するハンドルを返すのでこの名前としました。後ほど議論する問題があるため、 -ここでは明示的な型アノテーションが必要となります。`_`は型プレースホルダです。 -つまり「`handles`は何らかの型のベクトルとするが、その型が何であるかはRustが解決せよ。」と言っています。 +ここでは明示的な型アノテーションが必要となります。 `_` は型プレースホルダです。 +つまり「 `handles` は何らかの型のベクトルとするが、その型が何であるかはRustが解決せよ。」と言っています。 ```rust,ignore philosophers.into_iter().map(|p| { @@ -506,8 +506,8 @@ philosophers.into_iter().map(|p| { -哲学者のリストに対して`into_iter()`を呼び出します。このメソッドは、哲学者の所有権を持つイテレータを生成します。 -スレッドに各要素を渡すため、このようにしました。イテレータに対して`map`を呼び出し、その引数として要素毎に順番に呼ばれるクロージャを渡します。 +哲学者のリストに対して `into_iter()` を呼び出します。このメソッドは、哲学者の所有権を持つイテレータを生成します。 +スレッドに各要素を渡すため、このようにしました。イテレータに対して `map` を呼び出し、その引数として要素毎に順番に呼ばれるクロージャを渡します。 ```rust,ignore thread::spawn(move || { @@ -520,17 +520,17 @@ philosophers.into_iter().map(|p| { -ここが並行実行される部分です。`thread::spawn`関数はクロージャを1つ引数にとり、新しいスレッド上でそのクロージャを実行します。 -このクロージャは特別なアノテーション、`move`を必要とします。これによりキャプチャする値の所有権がクロージャ内へと移動されます。 -今回のケースでは、`map`関数の変数`p`が該当します。 +ここが並行実行される部分です。 `thread::spawn` 関数はクロージャを1つ引数にとり、新しいスレッド上でそのクロージャを実行します。 +このクロージャは特別なアノテーション、 `move` を必要とします。これによりキャプチャする値の所有権がクロージャ内へと移動されます。 +今回のケースでは、 `map` 関数の変数 `p` が該当します。 -スレッド内では、`p`に対して`eat()`を呼び出しておしまいです。`thread::spawn`呼び出しの末尾にセミコロンを置かないことで、 +スレッド内では、 `p` に対して `eat()` を呼び出しておしまいです。 `thread::spawn` 呼び出しの末尾にセミコロンを置かないことで、 式としている点に注意してください。正しい戻り値を返すために、この区別は重要です。詳細については、 -[式 vs. 文][es]を参照ください。 +[式 vs. 文][es] を参照ください。 [es]: functions.html#expressions-vs-statements @@ -543,9 +543,9 @@ philosophers.into_iter().map(|p| { -最後に、`map`呼び出しの結果をまとめ上げます。`collect()`は何らかのコレクション型を生成しますが、要求する戻り値型アノテーションを必要とします: -ここでは`Vec`です。またその要素は`thread::spawn`呼び出しの戻り値、つまり各スレッドへのハンドルとなっています。 -フゥー! +最後に、 `map` 呼び出しの結果をまとめ上げます。 `collect()` は何らかのコレクション型を生成しますが、要求する戻り値型アノテーションを必要とします: +ここでは `Vec` です。またその要素は `thread::spawn` 呼び出しの戻り値、つまり各スレッドへのハンドルとなっています。 +フゥー! ```rust,ignore for h in handles { @@ -556,13 +556,13 @@ for h in handles { -`main()`の最後に、ハンドルへの`join()`呼び出しをループし、各スレッド実行が完了するまで実行をブロックします。 +`main()` の最後に、ハンドルへの `join()` 呼び出しをループし、各スレッド実行が完了するまで実行をブロックします。 これにより、プログラム終了前にスレッド処理が完了すると保証します。 -このプログラムを実行すると、哲学者たちが同不順に食事するさまが見られるでしょう! -マルチスレッド処理だ! +このプログラムを実行すると、哲学者たちが順不同に食事するさまが見られるでしょう! +マルチスレッド処理だ! ```text Judith Butler is eating. @@ -578,10 +578,10 @@ Michel Foucault is done eating. ``` -あれ、フォークはどこ行ったの?まだモデル化していませんでしたね。 +あれ、フォークはどこ行ったの?まだモデル化していませんでしたね。 -という訳で、新しい`struct`を作っていきましょう: +という訳で、新しい `struct` を作っていきましょう: ```rust use std::sync::Mutex; @@ -595,12 +595,12 @@ struct Table { -この`Table`は`Mutex`のベクトルを保持します。ミューテックスは並行処理を制御するための機構です: +この `Table` は `Mutex` のベクトルを保持します。ミューテックスは並行処理を制御するための機構です: その内容へ同時アクセスできるのは1スレッドに限定されます。これは正に今回のフォークに求められる性質です。 -単に保持するだけで、実際に値を使うあても無いため、ミューテックスの中身は空タプル`()`とします。 +単に保持するだけで、実際に値を使うあても無いため、ミューテックスの中身は空タプル `()` とします。 -プログラムで`Table`を使うよう変更しましょう: +プログラムで `Table` を使うよう変更しましょう: ```rust use std::thread; @@ -672,7 +672,7 @@ fn main() { -変更がたくさん!とはいえ、このイテレーションで、動作するプログラムが出来ました。細かく見ていきましょう: +変更がたくさん!とはいえ、このイテレーションで、動作するプログラムが出来ました。細かく見ていきましょう: ```rust,ignore use std::sync::{Mutex, Arc}; @@ -680,7 +680,7 @@ use std::sync::{Mutex, Arc}; -ここでは`std::sync`パッケージからもう一つの構造体: `Arc`を利用します。その詳細は使うときに説明します。 +ここでは `std::sync` パッケージからもう一つの構造体: `Arc` を利用します。その詳細は使うときに説明します。 ```rust,ignore struct Philosopher { @@ -695,9 +695,9 @@ struct Philosopher { -`Philosopher`に2つのフィールドを追加する必要があります。哲学者はそれぞれ2本のフォークを使います: -1本は左手に、もう1本は右手に。フォークの表現はベクトルのインデックスに対応するため、ここでは`usize`型を使います。 -2つの値は`Table`が保持する`forks`のインデクス値を表しています。 +`Philosopher` に2つのフィールドを追加する必要があります。哲学者はそれぞれ2本のフォークを使います: +1本は左手に、もう1本は右手に。フォークの表現はベクトルのインデックスに対応するため、ここでは `usize` 型を使います。 +2つの値は `Table` が保持する `forks` のインデクス値を表しています。 ```rust,ignore fn new(name: &str, left: usize, right: usize) -> Philosopher { @@ -711,7 +711,7 @@ fn new(name: &str, left: usize, right: usize) -> Philosopher { -インスタンス生成時に`left`と`right`の値が必要になりますから、`new()`を拡張しました。 +インスタンス生成時に `left` と `right` の値が必要になりますから、 `new()` を拡張しました。 ```rust,ignore fn eat(&self, table: &Table) { @@ -735,17 +735,17 @@ fn eat(&self, table: &Table) { -新しい行が3つあります。新しい引数`table`も追加しました。`Table`が保持するフォークのリストにアクセスし、 -フォークにアクセスするため`self.left`と`self.right`をインデクス値に用います。そのインデクスから`Mutex`が得られたら、 -`lock()`を呼び出します。ミューテックスが別スレッドから並行アクセスされていた場合は、有効になるまでブロックされるでしょう。 -またフォークを取上げる操作が一瞬で終わらないよう、最初のフォークを取上げてから2つ目のフォークを取上げるまでの間に`thread::sleep`を呼び出します。 +新しい行が3つあります。新しい引数 `table` も追加しました。 `Table` が保持するフォークのリストにアクセスし、 +フォークにアクセスするため `self.left` と `self.right` をインデクス値に用います。そのインデクスから `Mutex` が得られたら、 +`lock()` を呼び出します。ミューテックスが別スレッドから並行アクセスされていた場合は、有効になるまでブロックされるでしょう。 +またフォークを取上げる操作が一瞬で終わらないよう、最初のフォークを取上げてから2つ目のフォークを取上げるまでの間に `thread::sleep` を呼び出します。 -`lock()`呼び出しは失敗する可能性があり、その場合は、プログラムをクラッシュさせます。この状況は、ミューテックスが[「poisoned」][poison]状態、 -つまりロック保持中のスレッドがパニックした場合にしか発生しません。つまり今は起こりえないため、単に`unwrap()`を使っています。 +`lock()` 呼び出しは失敗する可能性があり、その場合は、プログラムをクラッシュさせます。この状況は、ミューテックスが [「poisoned」][poison] 状態、 +つまりロック保持中のスレッドがパニックした場合にしか発生しません。つまり今は起こりえないため、単に `unwrap()` を使っています。 [poison]: ../std/sync/struct.Mutex.html#poisoning @@ -754,14 +754,14 @@ fn eat(&self, table: &Table) { -もう一つの変わった点として: 結果を`_left`と`_right`と名づけました。このアンダースコアはなにもの? -ええと、ロック内ではこれらの値を_使う_予定がありません。単にロックを獲得したいだけです。 +もう一つの変わった点として: 結果を `_left` と `_right` と名づけました。このアンダースコアはなにもの? +ええと、ロック内ではこれらの値を _使う_ 予定がありません。単にロックを獲得したいだけです。 そうなると、Rustは値が未使用だと警告してくるでしょう。アンダースコアを使えば、Rustにこちらの意図を伝えることができ、 警告されなくなるのです。 -ロックの解放はどうしましょう?はい、`_left`と`_right`がスコープから抜けるとき、自動的に解放されます。 +ロックの解放はどうしましょう?はい、 `_left` と `_right` がスコープから抜けるとき、自動的に解放されます。 ```rust,ignore let table = Arc::new(Table { forks: vec![ @@ -777,8 +777,8 @@ fn eat(&self, table: &Table) { -続いて、`main()`では、新しい`Table`を作って`Arc`に包んでいます。「arc」は「アトミック参照カウント(atomic reference count)」を意味し、 -複数スレッドから`Table`を共有するために必要となります。共有するときは参照カウントを増やし、 +続いて、 `main()` では、新しい `Table` を作って `Arc` に包んでいます。「arc」は「アトミック参照カウント(atomic reference count)」を意味し、 +複数スレッドから `Table` を共有するために必要となります。共有するときは参照カウントを増やし、 各スレッドの終了時にはカウントを減らします。 ```rust,ignore @@ -799,9 +799,9 @@ let philosophers = vec![ -`Philosopher`のコンストラクタには`left`と`right`の値を渡す必要があります。ここではもう1つ細かい話がありますが、 -これは_非常に_重要な部分です。規則性という点では、最後以外は特に問題ありません。ムッシュ・フーコー(Foucault)は`4, 0`を引数にとるべきですが、 -代わりに、`0, 4`としています。これはデッドロックを防ぐためのものです。実は: 哲学者の一人は左利きだったのです! +`Philosopher` のコンストラクタには `left` と `right` の値を渡す必要があります。ここではもう1つ細かい話がありますが、 +これは_非常に_重要な部分です。規則性という点では、最後以外は特に問題ありません。ムッシュ・フーコー(Foucault)は `4, 0` を引数にとるべきですが、 +代わりに、 `0, 4` としています。これはデッドロックを防ぐためのものです。実は: 哲学者の一人は左利きだったのです! これは問題解決の一つのやり方ですが、私の見立てでは、最も単純な方法です。実引数の順番を変更すれば、デッドロックが生じるのを観測できるでしょう。 ```rust,ignore @@ -819,19 +819,19 @@ let handles: Vec<_> = philosophers.into_iter().map(|p| { -最後に、`map()`/`collect()`ループの中で、`table.clone()`を呼び出します。`Arc`の`clone()`メソッドにより参照カウントが増加し、 -スコープ外に出たときは、参照カウントが減算されます。これは、スレッドを跨いで`table`への参照が何個あるかを知るのに必要です。 +最後に、 `map()` / `collect()` ループの中で、 `table.clone()` を呼び出します。 `Arc` の `clone()` メソッドにより参照カウントが増加し、 +スコープ外に出たときは、参照カウントが減算されます。これは、スレッドを跨いで `table` への参照が何個あるかを知るのに必要です。 参照カウントを行わないと、いつ解放すればよいかが分からなくなってしまいます。 -ここでは新しい束縛`table`を導入して、古い方を覆い隠していることに気付くでしょう。 +ここでは新しい束縛 `table` を導入して、古い方を覆い隠していることに気付くでしょう。 これは2つの異なる名前を必要としないため、よく用いられる方法です。 -これで、プログラムが動くようになりました!2人の哲学者だけが同時に食事できるようになり、次のような出力がえられるでしょう: +これで、プログラムが動くようになりました!2人の哲学者だけが同時に食事できるようになり、次のような出力がえられるでしょう: ```text Gilles Deleuze is eating. @@ -847,4 +847,4 @@ Michel Foucault is done eating. ``` -おめでとう!古典並行処理問題をRustを使って実装できましたね。 +おめでとう!古典並行処理問題をRustを使って実装できましたね。 diff --git a/1.6/ja/book/documentation.md b/1.6/ja/book/documentation.md index a6dae604..5177f665 100644 --- a/1.6/ja/book/documentation.md +++ b/1.6/ja/book/documentation.md @@ -8,12 +8,12 @@ プロジェクトのドキュメントを作成するために、Rustが提供するツールについて話しましょう。 -## `rustdoc`について +## `rustdoc` について -Rustの配布物には`rustdoc`というドキュメントを生成するツールが含まれています。 -`rustdoc`は`cargo doc`によってCargoでも使われます。 +Rustの配布物には `rustdoc` というドキュメントを生成するツールが含まれています。 +`rustdoc` は `cargo doc` によってCargoでも使われます。 @@ -52,7 +52,7 @@ pub fn new(value: T) -> Rc { -この注釈について注意すべき1つ目のことは、`//`の代わりに`///`が使われていることです。 +この注釈について注意すべき1つ目のことは、 `//` の代わりに `///` が使われていることです。 3連スラッシュはドキュメンテーションコメントを示します。 @@ -102,7 +102,7 @@ hello.rs:4 } -この[残念なエラー](https://github.com/rust-lang/rust/issues/22547)は正しいのです。ドキュメンテーションコメントはそれらの後のものに適用されるところ、その最後のコメントの後には何もないからです。 +この [残念なエラー](https://github.com/rust-lang/rust/issues/22547) は正しいのです。ドキュメンテーションコメントはそれらの後のものに適用されるところ、その最後のコメントの後には何もないからです。 [rc-new]: https://doc.rust-lang.org/nightly/std/rc/struct.Rc.html#method.new @@ -146,7 +146,7 @@ hello.rs:4 } 次は特別なセクションです。 -それらには`#`が付いていて、ヘッダであることを示しています。 +それらには `#` が付いていて、ヘッダであることを示しています。 一般的には、4種類のヘッダが使われます。 今のところそれらは特別な構文ではなく、単なる慣習です。 @@ -171,8 +171,8 @@ Rustにおいて、関数の回復不可能な誤用(つまり、プログラ -もし関数やメソッドが`Result`を戻すのであれば、それが`Err(E)`を戻したときの状況をドキュメントで説明するのはよいことです。 -これは`Panics`のときに比べると重要性は少し下です。失敗は型システムによってコード化されますが、それでもまだそうすることはよいことだからです。 +もし関数やメソッドが `Result` を戻すのであれば、それが `Err(E)` を戻したときの状況をドキュメントで説明するのはよいことです。 +これは `Panics` のときに比べると重要性は少し下です。失敗は型システムによってコード化されますが、それでもまだそうすることはよいことだからです。 ```rust /// # Safety @@ -181,7 +181,7 @@ Rustにおいて、関数の回復不可能な誤用(つまり、プログラ -もし関数が`unsafe`であれば、呼出元が動作を続けるためにはどの不変条件について責任を持つべきなのかを説明すべきです。 +もし関数が `unsafe` であれば、呼出元が動作を続けるためにはどの不変条件について責任を持つべきなのかを説明すべきです。 ```rust /// # Examples @@ -198,7 +198,7 @@ Rustにおいて、関数の回復不可能な誤用(つまり、プログラ -4つ目は`Examples`です。 +4つ目は `Examples` です。 関数やメソッドの使い方の例を1つ以上含めてください。そうすればユーザから愛されることでしょう。 それらの例はコードブロック注釈内に入れます。コードブロック注釈についてはすぐ後で話しますが、それらは1つ以上のセクションを持つことができます。 @@ -252,15 +252,15 @@ Rustにおいて、関数の回復不可能な誤用(つまり、プログラ これは、使われている言語が何であるかに応じてハイライトされます。 -もし単なるプレーンテキストを書いているのであれば、`text`を選択してください。 +もし単なるプレーンテキストを書いているのであれば、 `text` を選択してください。 -ここでは正しい注釈を選ぶことが重要です。なぜなら、`rustdoc`はそれを興味深い方法で使うからです。それらが実際のコードと不整合を起こさないように、ライブラリクレート内で実際にあなたの例をテストするために使うのです。 -もし例の中にCのコードが含まれているのに、あなたが注釈を付けるのを忘れてしまい、`rustdoc`がそれをRustのコードだと考えてしまえば、`rustdoc`はドキュメントを生成しようとするときに怒るでしょう。 +ここでは正しい注釈を選ぶことが重要です。なぜなら、 `rustdoc` はそれを興味深い方法で使うからです。それらが実際のコードと不整合を起こさないように、ライブラリクレート内で実際にあなたの例をテストするために使うのです。 +もし例の中にCのコードが含まれているのに、あなたが注釈を付けるのを忘れてしまい、 `rustdoc` がそれをRustのコードだと考えてしまえば、 `rustdoc` はドキュメントを生成しようとするときに怒るでしょう。 ## テストとしてのドキュメント @@ -278,8 +278,8 @@ Rustにおいて、関数の回復不可能な誤用(つまり、プログラ -`fn main()`とかがここでは不要だということに気が付くでしょう。 -`rustdoc`は自動的に`main()`ラッパーをコードの周りに、正しい場所へ配置するためのヒューリスティクスを使って追加します。 +`fn main()` とかがここでは不要だということに気が付くでしょう。 +`rustdoc` は自動的に `main()` ラッパーをコードの周りに、正しい場所へ配置するためのヒューリスティクスを使って追加します。 例えば、こうです。 ```rust @@ -313,11 +313,11 @@ fn main() { -1. 前の方にある全ての`#![foo]`アトリビュートは、そのままクレートのアトリビュートとして置いておく -2. `unused_variables`、`unused_assignments`、`unused_mut`、`unused_attributes`、`dead_code`などのいくつかの一般的な`allow`アトリビュートを追加する。 +1. 前の方にある全ての `#![foo]` アトリビュートは、そのままクレートのアトリビュートとして置いておく +2. `unused_variables` 、 `unused_assignments` 、 `unused_mut` 、 `unused_attributes` 、 `dead_code` などのいくつかの一般的な `allow` アトリビュートを追加する。 小さな例はしばしばこれらのリントに引っ掛かる -3. もしその例が`extern crate`を含んでいなければ、`extern crate ;`を挿入する(`#[macro_use]`がないことに注意する) -4. 最後に、もし例が`fn main`を含んでいなければ、テキストの残りの部分を`fn main() { your_code }`で囲む +3. もしその例が `extern crate` を含んでいなければ、 `extern crate ;` を挿入する( `#[macro_use]` がないことに注意する) +4. 最後に、もし例が `fn main` を含んでいなければ、テキストの残りの部分を `fn main() { your_code }` で囲む @@ -325,15 +325,15 @@ fn main() { -こうして生成された`fn main`は問題になり得ます! -もし`use`文によって参照される例のコードに`extern crate`文や`mod`文が入っていれば、それらはステップ4を抑制するために少なくとも`fn main() {}`を含んでいない限り失敗します。 -`#[macro_use] extern crate`も同様に、クレートのルート以外では動作しません。そのため、マクロのテストには明示的な`main`が常に必要なのです。 +こうして生成された `fn main` は問題になり得ます! +もし `use` 文によって参照される例のコードに `extern crate` 文や `mod` 文が入っていれば、それらはステップ4を抑制するために少なくとも `fn main() {}` を含んでいない限り失敗します。 +`#[macro_use] extern crate` も同様に、クレートのルート以外では動作しません。そのため、マクロのテストには明示的な `main` が常に必要なのです。 しかし、ドキュメントを散らかす必要はありません……続きを読みましょう! しかし、これでは不十分なことがときどきあります。 -例えば、今まで話してきた全ての`///`の付いたコード例はどうだったでしょうか。 +例えば、今まで話してきた全ての `///` の付いたコード例はどうだったでしょうか。 生のテキストはこうなっています。 ```text @@ -359,7 +359,7 @@ fn main() { -そうです。正解です。`# `で始まる行を追加することで、コードをコンパイルするときには使われるけれども、出力はされないというようにすることができます。 +そうです。正解です。 `# ` で始まる行を追加することで、コードをコンパイルするときには使われるけれども、出力はされないというようにすることができます。 これは都合のよいように使うことができます。 この場合、ドキュメンテーションコメントそのものを見せたいので、ドキュメンテーションコメントを何らかの関数に適用する必要があります。そのため、その後に小さい関数定義を追加する必要があります。 同時に、それは単にコンパイラを満足させるためだけのものなので、それを隠すことで、例がすっきりするのです。 @@ -477,13 +477,13 @@ macro_rules! panic_unless { -3つのことに気が付くでしょう。`#[macro_use]`アトリビュートを追加するために、自分で`extern crate`行を追加しなければなりません。 -2つ目に、`main()`も自分で追加する必要があります(理由は前述しました)。 -最後に、それらの2つが出力されないようにコメントアウトするという`#`の賢い使い方です。 +3つのことに気が付くでしょう。 `#[macro_use]` アトリビュートを追加するために、自分で `extern crate` 行を追加しなければなりません。 +2つ目に、 `main()` も自分で追加する必要があります(理由は前述しました)。 +最後に、それらの2つが出力されないようにコメントアウトするという `#` の賢い使い方です。 -`#`の使うと便利な場所のもう1つのケースは、エラーハンドリングを無視したいときです。 +`#` の使うと便利な場所のもう1つのケースは、エラーハンドリングを無視したいときです。 次のようにしたいとしましょう。 ```rust,ignore @@ -494,7 +494,7 @@ macro_rules! panic_unless { -問題は`try!`が`Result`を返すところ、テスト関数は何も返さないことで、これは型のミスマッチエラーを起こします。 +問題は `try!` が `Result` を返すところ、テスト関数は何も返さないことで、これは型のミスマッチエラーを起こします。 ```rust,ignore # /// A doc test using try! @@ -515,7 +515,7 @@ macro_rules! panic_unless { これは関数内のコードをラッピングすることで回避できます。 -これはドキュメント上のテストが実行されるときに`Result`を捕まえて飲み込みます。 +これはドキュメント上のテストが実行されるときに `Result` を捕まえて飲み込みます。 このパターンは標準ライブラリ内でよく現れます。 @@ -534,13 +534,13 @@ $ cargo test -正解です。`cargo test`は組み込まれたドキュメントもテストします。 +正解です。 `cargo test` は組み込まれたドキュメントもテストします。 **しかし、`cargo test`がテストするのはライブラリクレートだけで、バイナリクレートはテストしません。** -これは`rustdoc`の動き方によるものです。それはテストするためにライブラリをリンクしますが、バイナリには何もリンクするものがないからです。 +これは `rustdoc` の動き方によるものです。それはテストするためにライブラリをリンクしますが、バイナリには何もリンクするものがないからです。 -`rustdoc`がコードをテストするときに正しく動作するのを助けるために便利な注釈があと少しあります。 +`rustdoc` がコードをテストするときに正しく動作するのを助けるために便利な注釈があと少しあります。 ```rust /// ```ignore @@ -553,9 +553,9 @@ $ cargo test -`ignore`ディレクティブはRustにコードを無視するよう指示します。 +`ignore` ディレクティブはRustにコードを無視するよう指示します。 これはあまりに汎用的なので、必要になることはほとんどありません。 -もしそれがコードではなければ、代わりに`text`の注釈を付けること、又は問題となる部分だけが表示された、動作する例を作るために`#`を使うことを検討してください。 +もしそれがコードではなければ、代わりに `text` の注釈を付けること、又は問題となる部分だけが表示された、動作する例を作るために `#` を使うことを検討してください。 ```rust /// ```should_panic @@ -566,7 +566,7 @@ $ cargo test -`should_panic`は、そのコードは正しくコンパイルされるべきではあるが、実際にテストとして成功する必要まではないということを`rustdoc`に教えます。 +`should_panic` は、そのコードは正しくコンパイルされるべきではあるが、実際にテストとして成功する必要まではないということを `rustdoc` に教えます。 ```rust /// ```no_run @@ -580,14 +580,14 @@ $ cargo test -`no_run`アトリビュートはコードをコンパイルしますが、実行はしません。 +`no_run` アトリビュートはコードをコンパイルしますが、実行はしません。 これは「これはネットワークサービスを開始する方法です」というような例や、コンパイルされることは保証したいけれども、無限ループになってしまうような例にとって重要です! ### モジュールのドキュメントの作成 -Rustには別の種類のドキュメンテーションコメント、`//!`があります。 +Rustには別の種類のドキュメンテーションコメント、 `//!` があります。 このコメントは次に続く要素のドキュメントではなく、それを囲っている要素のドキュメントです。 言い換えると、こうです。 @@ -604,8 +604,8 @@ mod foo { -`//!`を頻繁に見る場所がここ、モジュールドキュメントです。 -もし`foo.rs`内にモジュールを持っていれば、しばしばそのコードを開くとこれを見るでしょう。 +`//!` を頻繁に見る場所がここ、モジュールドキュメントです。 +もし `foo.rs` 内にモジュールを持っていれば、しばしばそのコードを開くとこれを見るでしょう。 ```rust # //! A module for using `foo`s. @@ -620,7 +620,7 @@ mod foo { -ドキュメントのスタイルや書式についての全ての慣習を知るには[RFC 505][rfc505]をチェックしてください。 +ドキュメントのスタイルや書式についての全ての慣習を知るには [RFC 505][rfc505] をチェックしてください。 [rfc505]: https://github.com/rust-lang/rfcs/blob/master/text/0505-api-comment-conventions.md @@ -630,7 +630,7 @@ mod foo { ここにある振舞いは全て、Rust以外のソースコードファイルでも働きます。 -コメントはMarkdownで書かれるので、しばしば`.md`ファイルになります。 +コメントはMarkdownで書かれるので、しばしば `.md` ファイルになります。 @@ -675,10 +675,10 @@ Markdownファイルの中ではこうします。 ``` -この`%`行はそのファイルの一番先頭の行に書く必要があります。 +この `%` 行はそのファイルの一番先頭の行に書く必要があります。 -## `doc`アトリビュート +## `doc` アトリビュート @@ -709,7 +709,7 @@ Markdownファイルの中ではこうします。 ### 再エクスポート -`rustdoc`はパブリックな再エクスポートがなされた場合に、両方の場所にドキュメントを表示します。 +`rustdoc` はパブリックな再エクスポートがなされた場合に、両方の場所にドキュメントを表示します。 ```ignore extern crate foo; @@ -720,11 +720,11 @@ pub use foo::bar; -これは`bar`のドキュメントをクレートのドキュメントの中に生成するのと同様に、`foo`クレートのドキュメントの中にも生成します。 +これは `bar` のドキュメントをクレートのドキュメントの中に生成するのと同様に、 `foo` クレートのドキュメントの中にも生成します。 同じドキュメントが両方の場所で使われます。 -この振舞いは`no_inline`で抑制することができます。 +この振舞いは `no_inline` で抑制することができます。 ```ignore extern crate foo; @@ -742,14 +742,14 @@ pub use foo::bar; ときどき、プロジェクト内の公開されている全てのものについて、ドキュメントが作成されていることを確認したいことがあります。これは特にライブラリについて作業をしているときにあります。 Rustでは、要素にドキュメントがないときに警告やエラーを生成することができます。 -警告を生成するためには、`warn`を使います。 +警告を生成するためには、 `warn` を使います。 ```rust #![warn(missing_docs)] ``` -そしてエラーを生成するとき、`deny`を使います。 +そしてエラーを生成するとき、 `deny` を使います。 ```rust,ignore #![deny(missing_docs)] @@ -758,7 +758,7 @@ Rustでは、要素にドキュメントがないときに警告やエラーを 何かを明示的にドキュメント化されていないままにするため、それらの警告やエラーを無効にしたい場合があります。 -これは`allow`を使えば可能です。 +これは `allow` を使えば可能です。 ```rust #[allow(missing_docs)] @@ -778,7 +778,7 @@ struct Hidden; -`rustdoc`の生成するHTMLのいくつかの外見は、`#![doc]`アトリビュートを通じて制御することができます。 +`rustdoc` の生成するHTMLのいくつかの外見は、 `#![doc]` アトリビュートを通じて制御することができます。 ```rust #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", @@ -794,7 +794,7 @@ struct Hidden; -`rustdoc`がドキュメントの例をテストする方法は、`#[doc(test(..))]`アトリビュートを通じて設定することができます。 +`rustdoc` がドキュメントの例をテストする方法は、 `#[doc(test(..))]` アトリビュートを通じて設定することができます。 ```rust #![doc(test(attr(allow(unused_variables), deny(warnings))))] @@ -808,16 +808,16 @@ struct Hidden; ## 生成オプション -`rustdoc`はさらなるカスタマイズのために、その他にもコマンドラインのオプションをいくつか持っています。 +`rustdoc` はさらなるカスタマイズのために、その他にもコマンドラインのオプションをいくつか持っています。 -- `--html-in-header FILE`: FILEの内容を`...`セクションの末尾に加える -- `--html-before-content FILE`: FILEの内容を``の直後、レンダリングされた内容(検索バーを含む)の直前に加える -- `--html-after-content FILE`: FILEの内容を全てのレンダリングされた内容の後に加える +- `--html-in-header FILE` : FILEの内容を `...` セクションの末尾に加える +- `--html-before-content FILE` : FILEの内容を `` の直後、レンダリングされた内容(検索バーを含む)の直前に加える +- `--html-after-content FILE` : FILEの内容を全てのレンダリングされた内容の後に加える ## セキュリティ上の注意 diff --git a/1.6/ja/book/enums.md b/1.6/ja/book/enums.md index 8ad4eeed..545e8457 100644 --- a/1.6/ja/book/enums.md +++ b/1.6/ja/book/enums.md @@ -1,7 +1,9 @@ -% Enums +% 列挙型 + -An `enum` in Rust is a type that represents data that could be one of -several possible variants: + +Rustの `enum` は、いくつかのヴァリアントのうちからどれか一つをとるデータを表す型です。 ```rust enum Message { @@ -12,17 +14,27 @@ enum Message { } ``` -Each variant can optionally have data associated with it. The syntax for + +各ヴァリアントは、自身に関連するデータを持つこともできます。 +ヴァリアントの定義のための構文は、構造体を定義するのに使われる構文と似ており、 +(unit-like構造体のような) データを持たないヴァリアント、名前付きデータを持つヴァリアント、 (タプル構造体のような) 名前なしデータを持つヴァリアントがありえます。 +しかし、別々に構造体を定義する場合とは異なり、 `enum` は一つの型です。 +列挙型の値はどのヴァリアントにもマッチしうるのです。 +このことから、列挙型は「直和型」(sum type) と呼ばれることもあります。 +列挙型としてありうる値の集合は、各ヴァリアントとしてありうる値の集合の和であるためです。 + + +各ヴァリアントの名前を使うためには、 `::` 構文を使います。 +すなわち、ヴァリアントの名前は `enum` 自体の名前によってスコープ化されています。 +これにより、以下は動きます。 ```rust # enum Message { @@ -38,36 +50,50 @@ enum BoardGameTurn { let y: BoardGameTurn = BoardGameTurn::Move { squares: 1 }; ``` -Both variants are named `Move`, but since they’re scoped to the name of -the enum, they can both be used without conflict. + +どちらのヴァリアントも `Move` という名前ですが、列挙型の名前でスコープ化されているため、衝突することなく使うことができます。 -A value of an enum type contains information about which variant it is, + +列挙型の値は、ヴァリアントに関連するデータに加え、その値自身がどのヴァリアントであるかという情報を持っています。 +これを「タグ付き共用体」(tagged union) ということもあります。 +データが、それ自身がどの型なのかを示す「タグ」をもっているためです。 +コンパイラはこの情報を用いて、列挙型内のデータへ安全にアクセスすることを強制します。 +例えば、値をどれか一つのヴァリアントであるかのようにみなして、その中身を取り出すということはできません。 ```rust,ignore fn process_color_change(msg: Message) { - let Message::ChangeColor(r, g, b) = msg; // compile-time error +# // let Message::ChangeColor(r, g, b) = msg; // compile-time error + let Message::ChangeColor(r, g, b) = msg; // コンパイル時エラー } ``` -Not supporting these operations may seem rather limiting, but it’s a limitation + +こういった操作が許されないことで制限されているように感じられるかもしれませんが、この制限は克服できます。 +それには二つの方法があります。 +一つは等値性を自分で実装する方法、もう一つは次のセクションで学ぶ [`match`][match] 式でヴァリアントのパターンマッチを行う方法です。 +等値性を実装するにはRustについてまだ知るべきことがありますが、 [`トレイト`][traits] のセクションに書いてあります。 [match]: match.html [if-let]: if-let.html [traits]: traits.html -# Constructors as functions + +# 関数としてのコンストラクタ -An enum’s constructors can also be used like functions. For example: + +列挙型のコンストラクタも、関数のように使うことができます。 +例えばこうです。 ```rust # enum Message { @@ -76,7 +102,8 @@ An enum’s constructors can also be used like functions. For example: let m = Message::Write("Hello, world".to_string()); ``` -Is the same as + +これは、以下と同じです。 ```rust # enum Message { @@ -89,10 +116,12 @@ fn foo(x: String) -> Message { let x = foo("Hello, world".to_string()); ``` -This is not immediately useful to us, but when we get to + +また、すぐに役立つことではないのですが、[`クロージャ`][closures] までいくと、関数を他の関数へ引数として渡す話をします。 +例えば、これを [`イテレータ`][iterators] とあわせることで、 `String` のベクタから `Message::Write` へ変換することができます。 ```rust # enum Message { diff --git a/1.6/ja/book/error-handling.md b/1.6/ja/book/error-handling.md index 57389bdc..3baa6fcf 100644 --- a/1.6/ja/book/error-handling.md +++ b/1.6/ja/book/error-handling.md @@ -1,71 +1,122 @@ -% Error Handling - -Like most programming languages, Rust encourages the programmer to handle -errors in a particular way. Generally speaking, error handling is divided into -two broad categories: exceptions and return values. Rust opts for return -values. - -In this chapter, we intend to provide a comprehensive treatment of how to deal -with errors in Rust. More than that, we will attempt to introduce error handling -one piece at a time so that you'll come away with a solid working knowledge of -how everything fits together. - -When done naïvely, error handling in Rust can be verbose and annoying. This -chapter will explore those stumbling blocks and demonstrate how to use the -standard library to make error handling concise and ergonomic. - -# Table of Contents - -This chapter is very long, mostly because we start at the very beginning with -sum types and combinators, and try to motivate the way Rust does error handling -incrementally. As such, programmers with experience in other expressive type -systems may want to jump around. - -* [The Basics](#the-basics) - * [Unwrapping explained](#unwrapping-explained) - * [The `Option` type](#the-option-type) - * [Composing `Option` values](#composing-optiont-values) - * [The `Result` type](#the-result-type) - * [Parsing integers](#parsing-integers) - * [The `Result` type alias idiom](#the-result-type-alias-idiom) - * [A brief interlude: unwrapping isn't evil](#a-brief-interlude-unwrapping-isnt-evil) -* [Working with multiple error types](#working-with-multiple-error-types) - * [Composing `Option` and `Result`](#composing-option-and-result) - * [The limits of combinators](#the-limits-of-combinators) - * [Early returns](#early-returns) - * [The `try!` macro](#the-try-macro) - * [Defining your own error type](#defining-your-own-error-type) -* [Standard library traits used for error handling](#standard-library-traits-used-for-error-handling) - * [The `Error` trait](#the-error-trait) - * [The `From` trait](#the-from-trait) - * [The real `try!` macro](#the-real-try-macro) - * [Composing custom error types](#composing-custom-error-types) - * [Advice for library writers](#advice-for-library-writers) -* [Case study: A program to read population data](#case-study-a-program-to-read-population-data) - * [Initial setup](#initial-setup) - * [Argument parsing](#argument-parsing) - * [Writing the logic](#writing-the-logic) - * [Error handling with `Box`](#error-handling-with-boxerror) - * [Reading from stdin](#reading-from-stdin) - * [Error handling with a custom type](#error-handling-with-a-custom-type) - * [Adding functionality](#adding-functionality) -* [The short story](#the-short-story) - -# The Basics - -You can think of error handling as using *case analysis* to determine whether -a computation was successful or not. As you will see, the key to ergonomic error -handling is reducing the amount of explicit case analysis the programmer has to -do while keeping code composable. - -Keeping code composable is important, because without that requirement, we -could [`panic`](../std/macro.panic!.html) whenever we -come across something unexpected. (`panic` causes the current task to unwind, -and in most cases, the entire program aborts.) Here's an example: +% エラーハンドリング + + + + + + +他のほとんどのプログラミング言語と同様、Rustはプログラマに、ある決まった作法でエラーを扱うことを促します。 +一般的にエラーハンドリングは、例外、もしくは、戻り値を使ったものの、大きく2つに分類されます。 +Rustでは戻り値を使います。 + + + + + +この章では、Rustでのエラーハンドリングに関わる包括的な扱い方を提示しようと思います。 +単にそれだけではなく、エラーハンドリングのやり方を、ひとつひとつ、順番に積み上げていきます。 +こうすることで、全体がどう組み合わさっているのかの理解が進み、より実用的な知識が身につくでしょう。 + + + + +もし素朴なやり方を用いたなら、Rustにおけるエラーハンドリングは、冗長で面倒なものになり得ます。 +この章では、エラーを処理する上でどのような課題があるかを吟味し、標準ライブラリを使うと、それがいかにシンプルでエルゴノミック(人間にとって扱いやすいもの)に変わるのかを紹介します。 + + +# 目次 + + + + + +この章はとても長くなります。 +というのは、直和型(sum type) とコンビネータから始めることで、Restにおけるエラーハンドリングを徐々に改善していくための動機を与えるからです。 +このような構成ですので、もしすでに他の表現力豊かな型システムの経験があるプログラマでしたら、あちこち拾い読みしたくなるかもしれません。 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +* [基礎](#基礎) + * [アンラップ(unwrap) とは](#アンラップunwrap-とは) + * [`Option` 型](#option-型) + * [`Option` 値を合成する](#optiont-値を合成する) + * [`Result` 型](#result-型) + * [整数をパースする](#整数をパースする) + * [`Result` 型エイリアスを用いたイディオム](#result-型エイリアスを用いたイディオム) + * [小休止:アンラップは悪ではない](#小休止アンラップは悪ではない) +* [複数のエラー型を扱う](#複数のエラー型を扱う) + * [`Option` と `Result` を合成する](#option-と-result-を合成する) + * [コンビネータの限界](#コンビネータの限界) + * [早期リターン](#早期リターン) + * [`try!` マクロ](#try-マクロ) + * [独自のエラー型を定義する](#独自のエラー型を定義する) +* [標準ライブラリのトレイトによるエラー処理](#standard-library-traits-used-for-error-handling) + * [`Error` トレイト](#the-error-trait) + * [`From` トレイト](#the-from-trait) + * [本当の `try!` マクロ](#the-real-try-macro) + * [独自のエラー型を合成する](#composing-custom-error-types) + * [ライブラリ作者たちへのアドバイス](#advice-for-library-writers) +* [ケーススタディ:人口データを読み込むプログラム](#case-study-a-program-to-read-population-data) + * [最初のセットアップ](#initial-setup) + * [引数のパース](#argument-parsing) + * [ロジックを書く](#writing-the-logic) + * [`Box` によるエラー処理](#error-handling-with-boxerror) + * [標準入力から読み込む](#reading-from-stdin) + * [独自のエラー型によるエラー処理](#error-handling-with-a-custom-type) + * [機能を追加する](#adding-functionality) +* [簡単な説明(まとめ)](#the-short-story) + + +# 基礎 + + + + + +エラーハンドリングとは、ある処理が成功したかどうかを *場合分け(case analysis)* に基づいて判断するものだと考えられます。 +これから見ていくように、エラーハンドリングをエルゴノミックにするために重要なのは、プログラマがコードを合成可能(composable) に保ったまま、明示的な場合分けの回数を、いかに減らしていくかということです。 + + + + + +コードを合成可能に保つのは重要です。 +なぜなら、もしこの要求がなかったら、想定外のことが起こる度に [`panic`](../std/macro.panic!.html) することを選ぶかもしれないからです。 +(`panic` は現タスクを巻き戻し(unwind) して、ほとんどの場合、プログラム全体をアボートします。) ```rust,should_panic -// Guess a number between 1 and 10. -// If it matches the number we had in mind, return true. Else, return false. +# // Guess a number between 1 and 10. +# // If it matches the number we had in mind, return true. Else, return false. +// 1から10までの数字を予想します。 +// もし予想した数字に一致したらtrueを返し、そうでなけれは、falseを返します。 fn guess(n: i32) -> bool { if n < 1 || n > 10 { panic!("Invalid number: {}", n); @@ -78,14 +129,25 @@ fn main() { } ``` -If you try running this code, the program will crash with a message like this: +> 訳注:文言の意味は +> +> * Invalid number: {}:無効な数字です: {} +> +> ですが、エディタの設定などによっては、ソースコード中の +> コメント以外の場所に日本語を使うとコンパイルできないことがあるので、 +> 英文のままにしてあります。 + + +このコードを実行すると、プログラムがクラッシュして、以下のようなメッセージが表示されます。 ```text thread '
' panicked at 'Invalid number: 11', src/bin/panic-simple.rs:5 ``` -Here's another example that is slightly less contrived. A program that accepts -an integer as an argument, doubles it and prints it. + + +次は、もう少し自然な例です。 +このプログラムは引数として整数を受け取り、2倍した後に表示します。 @@ -94,37 +156,52 @@ use std::env; fn main() { let mut argv = env::args(); - let arg: String = argv.nth(1).unwrap(); // error 1 - let n: i32 = arg.parse().unwrap(); // error 2 + let arg: String = argv.nth(1).unwrap(); // エラー1 + let n: i32 = arg.parse().unwrap(); // エラー2 println!("{}", 2 * n); } ``` -If you give this program zero arguments (error 1) or if the first argument -isn't an integer (error 2), the program will panic just like in the first -example. - -You can think of this style of error handling as similar to a bull running -through a china shop. The bull will get to where it wants to go, but it will -trample everything in the process. - -## Unwrapping explained - -In the previous example, we claimed -that the program would simply panic if it reached one of the two error -conditions, yet, the program does not include an explicit call to `panic` like -the first example. This is because the -panic is embedded in the calls to `unwrap`. - -To “unwrap” something in Rust is to say, “Give me the result of the -computation, and if there was an error, just panic and stop the program.” -It would be better if we just showed the code for unwrapping because it is so -simple, but to do that, we will first need to explore the `Option` and `Result` -types. Both of these types have a method called `unwrap` defined on them. - -### The `Option` type - -The `Option` type is [defined in the standard library][5]: + + + +もし、このプログラムに引数を与えなかったら(エラー1)、あるいは、最初の引数が整数でなかったら(エラー2)、このプログラムは、最初の例と同じようにパニックするでしょう。 + + + + +このようなスタイルのエラーハンドリングは、まるで、陶器店の中を駆け抜ける雄牛のようなものです。 +雄牛は自分の行きたいところへたどり着くでしょう。 +でも彼は、途中にある、あらゆるものを蹴散らしてしまいます。 + + +## アンラップ(unwrap) とは + + + + + + +先ほどの例で、プログラムが2つのエラー条件のいずれかを満たしたときに、パニックすると言いました。 +でもこのプログラムは、最初の例とは違って明示的に `panic` を呼び出してはいません。 +実はパニックは `unwrap` の呼び出しの中に埋め込まれているのです。 + + + + + + +Rustでなにかを「アンラップする」とき、こう言っているのと同じです。 +「計算結果を取り出しなさい。もしエラーになっていたのなら、パニックを起こしてプログラムを終了させなさい。」 +アンラップのコードはとてもシンプルなので、多分、それを見せたほうが早いでしょう。 +でもそのためには、まず `Option` と `Result` 型について調べる必要があります。 +どちらの型にも `unwrap` という名前のメソッドが定義されています。 + + +### `Option` 型 + + +`Option` 型は [標準ライブラリで定義されています][5]: ```rust enum Option { @@ -133,17 +210,24 @@ enum Option { } ``` -The `Option` type is a way to use Rust's type system to express the -*possibility of absence*. Encoding the possibility of absence into the type -system is an important concept because it will cause the compiler to force the -programmer to handle that absence. Let's take a look at an example that tries -to find a character in a string: + + + + + +`Option` 型は、Rustの型システムを使って *不在の可能性* を示すためのものです。 +不在の可能性を型システムにエンコードすることは、重要なコンセプトです。 +なぜなら、その不在に対処することを、コンパイラがプログラマに強制させるからです。 +では、文字列から文字を検索する例を見てみましょう。 ```rust -// Searches `haystack` for the Unicode character `needle`. If one is found, the -// byte offset of the character is returned. Otherwise, `None` is returned. +# // Searches `haystack` for the Unicode character `needle`. If one is found, the +# // byte offset of the character is returned. Otherwise, `None` is returned. +// `haystack`(干し草の山)からUnicode文字 `needle`(縫い針)を検索します。 +// もし見つかったら、文字のバイトオフセットを返します。見つからなければ、`None` を +// 返します。 fn find(haystack: &str, needle: char) -> Option { for (offset, c) in haystack.char_indices() { if c == needle { @@ -154,16 +238,26 @@ fn find(haystack: &str, needle: char) -> Option { } ``` -Notice that when this function finds a matching character, it doesn't just -return the `offset`. Instead, it returns `Some(offset)`. `Some` is a variant or -a *value constructor* for the `Option` type. You can think of it as a function -with the type `fn(value: T) -> Option`. Correspondingly, `None` is also a -value constructor, except it has no arguments. You can think of `None` as a -function with the type `fn() -> Option`. - -This might seem like much ado about nothing, but this is only half of the -story. The other half is *using* the `find` function we've written. Let's try -to use it to find the extension in a file name. + + + + + + +この関数がマッチする文字を見つけたとき、単に `offset` を返すだけではないことに注目してください。 +その代わりに `Some(offset)` を返します。 +`Some` は `Option` 型の *値コンストラクタ* の一つです。 +これは `fn(value: T) -> Option` という型の関数だと考えることもできます。 +これに対応して `None` もまた値コンストラクタですが、こちらには引数がありません。 +`None` は `fn() -> Option` という型の関数だと考えることもできます。 + + + + +何もないことを表すのに、ずいぶん大げさだと感じるかもしれません。 +でもこれはまだ、話の半分に過ぎません。 +残りの半分は、いま書いた `find` 関数を *使う* 場面です。 +これを使って、ファイル名から拡張子を見つけてみましょう。 ```rust # fn find(_: &str, _: char) -> Option { None } @@ -176,15 +270,27 @@ fn main() { } ``` -This code uses [pattern matching][1] to do *case -analysis* on the `Option` returned by the `find` function. In fact, case -analysis is the only way to get at the value stored inside an `Option`. This -means that you, as the programmer, must handle the case when an `Option` is -`None` instead of `Some(t)`. +> 訳注: +> +> * No file extension found:ファイル拡張子は見つかりませんでした +> * File extension: {}:ファイル拡張子:{} + + + + + + +このコードは `find` 関数が返した `Option` の *場合分け* に、 [パターンマッチ][1] を使っています。 +実のところ、場合分けが、`Option` に格納された値を取り出すための唯一の方法なのです。 +これは、`Option` が `Some(t)` ではなく `None` だったとき、プログラマであるあなたが、このケースに対処しなければならないことを意味します。 -But wait, what about `unwrap`,which we used [`previously`](#code-unwrap-double)? -There was no case analysis there! Instead, the case analysis was put inside the -`unwrap` method for you. You could define it yourself if you want: + + + +でも、ちょっと待ってください。 [さっき](#code-unwrap-double) 使った `unwrap` はどうだったでしょうか? +場合分けはどこにもありませんでした! +実は場合分けは `unwrap` メソッドの中に埋め込まれていたのです。 +もし望むなら、このように自分で定義することもできます: @@ -205,28 +311,45 @@ impl Option { } ``` -The `unwrap` method *abstracts away the case analysis*. This is precisely the thing -that makes `unwrap` ergonomic to use. Unfortunately, that `panic!` means that -`unwrap` is not composable: it is the bull in the china shop. +> 訳注: +> +> called `Option::unwrap()` on a `None` value:
+> `None` な値に対して `Option:unwpal()` が呼ばれました + + + + +`unwrap` メソッドは *場合分けを抽象化します* 。このことは確かに `unwrap` をエルゴノミックにしています。 +しかし残念なことに、そこにある `panic!` が意味するものは、`unwrap` が合成可能ではない、つまり、陶器店の中の雄牛だということです。 -### Composing `Option` values + +### `Option` 値を合成する -In an [example from before](#code-option-ex-string-find), -we saw how to use `find` to discover the extension in a file name. Of course, -not all file names have a `.` in them, so it's possible that the file name has -no extension. This *possibility of absence* is encoded into the types using -`Option`. In other words, the compiler will force us to address the -possibility that an extension does not exist. In our case, we just print out a -message saying as such. + + + + + + + +[先ほどの例](#code-option-ex-string-find) では、ファイル名から拡張子を見つけるために `find` をどのように使うかを見ました。 +当然ながら全てのファイル名に `.` があるわけではなく、拡張子のないファイル名もあり得ます。 +このような *不在の可能性* は `Option` を使うことによって、型の中にエンコードされています。 +すなわち、コンパイラは、拡張子が存在しない可能性に対処することを、私たちに強制してくるわけです。 +今回は単に、そうなったことを告げるメッセージを表示するようにしました。 -Getting the extension of a file name is a pretty common operation, so it makes -sense to put it into a function: + + +ファイル名から拡張子を取り出すことは一般的な操作ですので、それを関数にすることは理にかなっています。 ```rust # fn find(_: &str, _: char) -> Option { None } -// Returns the extension of the given file name, where the extension is defined -// as all characters proceeding the first `.`. -// If `file_name` has no `.`, then `None` is returned. +# // Returns the extension of the given file name, where the extension is defined +# // as all characters proceeding the first `.`. +# // If `file_name` has no `.`, then `None` is returned. +// 与えられたファイル名の拡張子を返す。拡張子の定義は、最初の +// `.` に続く、全ての文字である。 +// もし `file_name` に `.` がなければ、`None` が返される。 fn extension_explicit(file_name: &str) -> Option<&str> { match find(file_name, '.') { None => None, @@ -235,23 +358,32 @@ fn extension_explicit(file_name: &str) -> Option<&str> { } ``` -(Pro-tip: don't use this code. Use the + + + +(プロ向けのヒント:このコードは使わず、代わりに標準ライブラリの [`extension`](../std/path/struct.Path.html#method.extension) -method in the standard library instead.) - -The code stays simple, but the important thing to notice is that the type of -`find` forces us to consider the possibility of absence. This is a good thing -because it means the compiler won't let us accidentally forget about the case -where a file name doesn't have an extension. On the other hand, doing explicit -case analysis like we've done in `extension_explicit` every time can get a bit -tiresome. - -In fact, the case analysis in `extension_explicit` follows a very common -pattern: *map* a function on to the value inside of an `Option`, unless the -option is `None`, in which case, just return `None`. - -Rust has parametric polymorphism, so it is very easy to define a combinator -that abstracts this pattern: +メソッドを使ってください) + + + + + + + +このコードはいたってシンプルですが、ひとつだけ注目して欲しいのは、`find` の型が不在の可能性について考慮することを強制していることです。 +これは良いことです。なぜなら、コンパイラが私たちに、ファイル名が拡張子を持たないケースを、うっかり忘れないようにしてくれるからです。 +しかし一方で、 `extension_explicit` でしたような明示的な場合分けを毎回続けるのは、なかなか面倒です。 + + + + +実は `extension_explicit` での場合分けは、ごく一般的なパターンである、`Option` への *map* の適用に当てはめられます。 +これは、もしオプションが `None` なら `None` を返し、そうでなけれは、オプションの中の値に関数を適用する、というパターンです。 + + + +Rustはパラメトリック多相をサポートしていますので、このパターンを抽象化するためのコンビネータが簡単に定義できます: @@ -264,26 +396,35 @@ fn map(option: Option, f: F) -> Option where F: FnOnce(T) -> A { } ``` -Indeed, `map` is [defined as a method][2] on `Option` in the standard library. + +もちろん `map` は、標準のライブラリの `Option` で [メソッドとして定義されています][2]。 -Armed with our new combinator, we can rewrite our `extension_explicit` method -to get rid of the case analysis: + + +新しいコンビネータを手に入れましたので、 `extension_explicit` メソッドを書き直して、場合分けを省きましょう: ```rust # fn find(_: &str, _: char) -> Option { None } -// Returns the extension of the given file name, where the extension is defined -// as all characters proceeding the first `.`. -// If `file_name` has no `.`, then `None` is returned. +# // Returns the extension of the given file name, where the extension is defined +# // as all characters proceeding the first `.`. +# // If `file_name` has no `.`, then `None` is returned. +// 与えられたファイル名の拡張子を返す。拡張子の定義は、最初の +// `.` に続く、全ての文字である。 +// もし `file_name` に `.` がなければ、`None` が返される。 fn extension(file_name: &str) -> Option<&str> { find(file_name, '.').map(|i| &file_name[i+1..]) } ``` -One other pattern we commonly find is assigning a default value to the case -when an `Option` value is `None`. For example, maybe your program assumes that -the extension of a file is `rs` even if none is present. As you might imagine, -the case analysis for this is not specific to file extensions - it can work -with any `Option`: + + + + + +もう一つの共通のパターンは、`Option` の値が `None` だったときのデフォルト値を与えることです。 +例えばファイルの拡張子がないときは、それを `rs` とみなすようなプログラムを書きたくなるかもしれません。 +ご想像の通り、このような場合分けはファイルの拡張子に特有のものではありません。 +どんな `Option` でも使えるでしょう: ```rust fn unwrap_or(option: Option, default: T) -> T { @@ -294,8 +435,10 @@ fn unwrap_or(option: Option, default: T) -> T { } ``` -The trick here is that the default value must have the same type as the value -that might be inside the `Option`. Using it is dead simple in our case: + + +ここでの仕掛けは、`Option` に入れる値と同じ型になるよう、デフォルト値の型を制限していることです。 +これを使うのは、すごく簡単です: ```rust # fn find(haystack: &str, needle: char) -> Option { @@ -316,21 +459,30 @@ fn main() { } ``` -(Note that `unwrap_or` is [defined as a method][3] on `Option` in the -standard library, so we use that here instead of the free-standing function we -defined above. Don't forget to check out the more general [`unwrap_or_else`][4] -method.) + + + + +(`unwrap_or` は、標準のライブラリの `Option` で、 [メソッドとして定義されています][3] ので、いま定義したフリースタンディングな関数の代わりに、そちらを使いましょう。) -There is one more combinator that we think is worth paying special attention to: -`and_then`. It makes it easy to compose distinct computations that admit the -*possibility of absence*. For example, much of the code in this section is -about finding an extension given a file name. In order to do this, you first -need the file name which is typically extracted from a file *path*. While most -file paths have a file name, not *all* of them do. For example, `.`, `..` or -`/`. + + + + + + + +もうひとつ特筆すべきコンビネータがあります。それは `and_then` です。これを使うと *不在の可能性* を考慮しながら、別々の処理を簡単に組み合わせることができます。 +例えば、この節のほとんどのコードは、与えられたファイル名について拡張子を見つけだします。 +そのためには、まずファイル *パス* から取り出したファイル名が必要です。 +大抵のパスにはファイル名がありますが、 *全て* がというわけではありません。 +例えば `.`, `..`, `/` などは例外です。 + + + +つまり、与えられたファイル *パス* から拡張子を見つけ出せるか、トライしなければなりません。 +まず明示的な場合分けから始めましょう: -So, we are tasked with the challenge of finding an extension given a file -*path*. Let's start with explicit case analysis: ```rust # fn extension(file_name: &str) -> Option<&str> { None } @@ -345,17 +497,23 @@ fn file_path_ext_explicit(file_path: &str) -> Option<&str> { } fn file_name(file_path: &str) -> Option<&str> { - // implementation elided +# // implementation elided + // 実装は省略 unimplemented!() } ``` -You might think that we could just use the `map` combinator to reduce the case -analysis, but its type doesn't quite fit. Namely, `map` takes a function that -does something only with the inner value. The result of that function is then -*always* [rewrapped with `Some`](#code-option-map). Instead, we need something -like `map`, but which allows the caller to return another `Option`. Its generic -implementation is even simpler than `map`: + + + + + + +場合分けを減らすために単に `map` コンビネータを使えばいいと思うかもしれませんが、型にうまく適合しません。 +なぜなら `map` が引数にとる関数は、中の値だけに適用されるからです。 +そして関数が返した値は *必ず* [`Some` でラップされ直します](#code-option-map) 。 +つまりこの代わりに、 `map` に似ていながら、呼び出し元が別の `Option` を返せるしくみが必要です。 +これの汎用的な実装は `map` よりもシンプルです: ```rust fn and_then(option: Option, f: F) -> Option @@ -367,7 +525,8 @@ fn and_then(option: Option, f: F) -> Option } ``` -Now we can rewrite our `file_path_ext` function without explicit case analysis: + +では、明示的な場合分けを省くように、 `file_path_ext` を書き直しましょう: ```rust # fn extension(file_name: &str) -> Option<&str> { None } @@ -377,22 +536,32 @@ fn file_path_ext(file_path: &str) -> Option<&str> { } ``` -The `Option` type has many other combinators [defined in the standard -library][5]. It is a good idea to skim this list and familiarize -yourself with what's available—they can often reduce case analysis -for you. Familiarizing yourself with these combinators will pay -dividends because many of them are also defined (with similar -semantics) for `Result`, which we will talk about next. + + + + + +`Option` 型には、他にもたくさんのコンビネータが [標準ライブラリで定義されています][5] 。 +それらの一覧をざっと眺めて、なにがあるか知っておくといいでしょう。 +大抵の場合、場合分けを減らすのに役立ちます。 +それらのコンビネータに慣れるための努力は、すぐに報われるでしょう。 +なぜなら、そのほとんどは次に話す `Result` 型でも、(よく似たセマンティクスで)定義されているからです。 -Combinators make using types like `Option` ergonomic because they reduce -explicit case analysis. They are also composable because they permit the caller -to handle the possibility of absence in their own way. Methods like `unwrap` -remove choices because they will panic if `Option` is `None`. + + + + +コンビネータは明示的な場合分けを減らしてくれるので、 `Option` のような型をエルゴノミックにします。 +またこれらは *不在の可能性* を、呼び出し元がそれに合った方法で扱えるようにするので、合成可能だといえます。 +`unwrap` のようなメソッドは、 `Option` が `None` のときにパニックを起こすので、このような選択の機会を与えません。 -## The `Result` type + +## `Result` 型 -The `Result` type is also -[defined in the standard library][6]: + + +`Result` 型も [標準ライブラリで定義されています][6] 。 @@ -403,29 +572,42 @@ enum Result { } ``` -The `Result` type is a richer version of `Option`. Instead of expressing the -possibility of *absence* like `Option` does, `Result` expresses the possibility -of *error*. Usually, the *error* is used to explain why the execution of some -computation failed. This is a strictly more general form of `Option`. Consider -the following type alias, which is semantically equivalent to the real -`Option` in every way: + + + + + + +`Result` 型は `Option` 型の豪華版です。 +`Option` のように *不在* の可能性を示す代わりに、`Result` は *エラー* になる可能性を示します。 +通常 *エラー* は、なぜ処理が実行に失敗したのかを説明するために用いられます。 +これは厳密には `Option` をさらに一般化した形式だといえます。 +以下のような型エイリアスがあるとしましょう。 +これは全てにおいて、本物の `Option` と等しいセマンティクスを持ちます。 ```rust type Option = Result; ``` -This fixes the second type parameter of `Result` to always be `()` (pronounced -“unit” or “empty tuple”). Exactly one value inhabits the `()` type: `()`. (Yup, -the type and value level terms have the same notation!) + + + +これは `Result` の2番目の型パラメータを `()` (「ユニット」または「空タプル」と発音します)に固定したものです。 +`()` 型のただ一つの値は `()` です。 +(そうなんです。型レベルと値レベルの項が、全く同じ表記法を持ちます!) -The `Result` type is a way of representing one of two possible outcomes in a -computation. By convention, one outcome is meant to be expected or “`Ok`” while -the other outcome is meant to be unexpected or “`Err`”. + + + +`Result` 型は、処理の結果がとりうる2つの可能性のうち、1つを表すための方法です。 +慣例に従い、一方が期待されている結果、つまり「`Ok`」となり、もう一方が予想外の結果、つまり「`Err`」になります。 -Just like `Option`, the `Result` type also has an -[`unwrap` method -defined][7] -in the standard library. Let's define it: + + + + +`Option` と全く同じように、`Result` 型も標準ライブラリで [`unwrap` メソッドが定義されています][7] 。 +定義してみましょう: ```rust # enum Result { Ok(T), Err(E) } @@ -440,22 +622,35 @@ impl Result { } ``` -This is effectively the same as our [definition for -`Option::unwrap`](#code-option-def-unwrap), except it includes the -error value in the `panic!` message. This makes debugging easier, but -it also requires us to add a [`Debug`][8] constraint on the `E` type -parameter (which represents our error type). Since the vast majority -of types should satisfy the `Debug` constraint, this tends to work out -in practice. (`Debug` on a type simply means that there's a reasonable -way to print a human readable description of values with that type.) +> 訳注: +> +> called `Result::unwrap()` on an `Err` value: {:?}":
+> `Err` 値 {:?} に対して `Result::unwrap()` が呼ばれました + + + + + + + + + +これは実質的には私たちの [`Option::unwrap` の定義](#code-option-def-unwrap) と同じですが、 `panic!` メッセージにエラーの値が含まれているところが異なります。 +これはデバッグをより簡単にしますが、一方で、(エラーの型を表す)型パラメータ `E` に [`Debug`][8] 制約を付けることが求められます。 +大半の型は `Debug` 制約を満たしているので、実際のところ、うまくいく傾向にあります。 +(`Debug` が型に付くということは、単にその型の値が、人間が読める形式で表示できることを意味しています。) -OK, let's move on to an example. + +では、例を見ていきましょう。 -### Parsing integers + +### 整数をパースする -The Rust standard library makes converting strings to integers dead simple. -It's so easy in fact, that it is very tempting to write something like the -following: + + + +Rustの標準ライブラリを使うと、文字列を整数に変換することが、すごく簡単にできます。 +あまりにも簡単なので、実際のところ、以下のように書きたいという誘惑に負けることがあります: ```rust fn double_number(number_str: &str) -> i32 { @@ -468,19 +663,27 @@ fn main() { } ``` -At this point, you should be skeptical of calling `unwrap`. For example, if -the string doesn't parse as a number, you'll get a panic: + + +すでにあなたは、`unwrap` を呼ぶことについて懐疑的になっているはずです。 +例えば、文字列が数字としてパースできなければ、パニックが起こります。 ```text thread '
' panicked at 'called `Result::unwrap()` on an `Err` value: ParseIntError { kind: InvalidDigit }', /home/rustbuild/src/rust-buildbot/slave/beta-dist-rustc-linux/build/src/libcore/result.rs:729 ``` -This is rather unsightly, and if this happened inside a library you're -using, you might be understandably annoyed. Instead, we should try to -handle the error in our function and let the caller decide what to -do. This means changing the return type of `double_number`. But to -what? Well, that requires looking at the signature of the [`parse` -method][9] in the standard library: + + + + + + +これは少し目障りです。 +もしあなたが使っているライブラリの中でこれが起こされたら、イライラするに違いありません。 +代わりに、私たちの関数の中でエラーを処理し、呼び出し元にどうするのかを決めさせるべきです。 +そのためには、`double_number` の戻り値の型(リターン型)を変更しなければなりません。 +でも、一体何に? +ええと、これはつまり、標準ライブラリの [`parse` メソッド][9] のシグネチャを見ろということです。 ```rust,ignore impl str { @@ -488,27 +691,45 @@ impl str { } ``` -Hmm. So we at least know that we need to use a `Result`. Certainly, it's -possible that this could have returned an `Option`. After all, a string either -parses as a number or it doesn't, right? That's certainly a reasonable way to -go, but the implementation internally distinguishes *why* the string didn't -parse as an integer. (Whether it's an empty string, an invalid digit, too big -or too small.) Therefore, using a `Result` makes sense because we want to -provide more information than simply “absence.” We want to say *why* the -parsing failed. You should try to emulate this line of reasoning when faced -with a choice between `Option` and `Result`. If you can provide detailed error -information, then you probably should. (We'll see more on this later.) - -OK, but how do we write our return type? The `parse` method as defined -above is generic over all the different number types defined in the -standard library. We could (and probably should) also make our -function generic, but let's favor explicitness for the moment. We only -care about `i32`, so we need to [find its implementation of -`FromStr`](../std/primitive.i32.html) (do a `CTRL-F` in your browser -for “FromStr”) and look at its [associated type][10] `Err`. We did -this so we can find the concrete error type. In this case, it's -[`std::num::ParseIntError`](../std/num/struct.ParseIntError.html). -Finally, we can rewrite our function: + + + + + + + + + + +うむ。最低でも `Result` を使わないといけないことはわかりました。 +もちろん、これが `Option` を戻すようにすることも可能だったでしょう。 +結局のところ、文字列が数字としてパースできたかどうかが知りたいわけですよね? +それも悪いやり方ではありませんが、実装の内側では *なぜ* 文字列が整数としてパースできなかったを、ちゃんと区別しています。 +(空の文字列だったのか、有効な数字でなかったのか、大きすぎたり、小さすぎたりしたのか。) +従って、`Result` を使ってより多くの情報を提供するほうが、単に「不在」を示すことよりも理にかなっています。 +今後、もし `Option` と `Result` のどちらを選ぶという事態に遭遇したときは、このような理由付けのやり方を真似てみてください。 +もし詳細なエラー情報を提供できるのなら、多分、それをしたほうがいいでしょう。 +(後ほど別の例もお見せます。) + + + + + + + + + + + +それでは、リターン型をどう書きましょうか? +上の `parse` メソッドは一般化されているので、標準ライブラリにある、あらゆる数値型について定義されています。 +この関数を同じように一般化することもできますが(そして、そうするべきでしょうが)、今は明快さを優先しましょう。 +`i32` だけを扱うことにしますので、それの [`FromStr` の実装がどうなっているか探しましょう](../std/primitive.i32.html) 。 +(ブラウザで `CTRL-F` を押して「FromStr」を探します。) +そして [関連型(associated type)][10] から `Err` を見つけます。 +こうすれば、具体的なエラー型が見つかります。 +この場合、それは [`std::num::ParseIntError`](../std/num/struct.ParseIntError.html) です。 +これでようやく関数を書き直せます: ```rust use std::num::ParseIntError; @@ -528,12 +749,18 @@ fn main() { } ``` -This is a little better, but now we've written a lot more code! The case -analysis has once again bitten us. + + +これで少し良くなりましたが、たくさんのコードを書いてしまいました! +場合分けに、またしてもやられたわけです。 -Combinators to the rescue! Just like `Option`, `Result` has lots of combinators -defined as methods. There is a large intersection of common combinators between -`Result` and `Option`. In particular, `map` is part of that intersection: + + + +コンビネータに助けを求めましょう! +ちょうど `Option` と同じように `Result` にもたくさんのコンビネータが、メソッドとして定義されています。 +`Result` と `Option` の間では、共通のコンビネータが数多く存在します。 +例えば `map` も共通なものの一つです: ```rust use std::num::ParseIntError; @@ -550,24 +777,34 @@ fn main() { } ``` -The usual suspects are all there for `Result`, including -[`unwrap_or`](../std/result/enum.Result.html#method.unwrap_or) and -[`and_then`](../std/result/enum.Result.html#method.and_then). -Additionally, since `Result` has a second type parameter, there are -combinators that affect only the error type, such as -[`map_err`](../std/result/enum.Result.html#method.map_err) (instead of -`map`) and [`or_else`](../std/result/enum.Result.html#method.or_else) -(instead of `and_then`). - -### The `Result` type alias idiom - -In the standard library, you may frequently see types like -`Result`. But wait, [we defined `Result`](#code-result-def) to -have two type parameters. How can we get away with only specifying -one? The key is to define a `Result` type alias that *fixes* one of -the type parameters to a particular type. Usually the fixed type is -the error type. For example, our previous example parsing integers -could be rewritten like this: + + + + + + + + +`Result` でいつも候補にあがるのは [`unwrap_or`](../std/result/enum.Result.html#method.unwrap_or) と [`and_then`](../std/result/enum.Result.html#method.and_then) です。 +さらに `Result` は2つ目の型パラメータを取りますので、エラー型だけに影響を与える [`map_err`](../std/result/enum.Result.html#method.map_err) (`map` に相当)と [`or_else`](../std/result/enum.Result.html#method.or_else) (`and_then` に相当)もあります。 + + +### `Result` 型エイリアスを用いたイディオム + + + + + + + + +標準ライブラリでは `Result` のような型をよく見ると思います。 +でも、待ってください。 +2つの型パラメータを取るように [`Result` を定義したはずです](#code-result-def) 。 +どうして、1つだけを指定して済んだのでしょう? +種を明かすと、`Result` の型エイリアスを定義して、一方の型パラメータを特定の型に *固定* したのです。 +通常はエラー型の方を固定します。 +例えば、先ほどの整数のパースの例は、こう書き換えることもできます。 ```rust use std::num::ParseIntError; @@ -580,97 +817,151 @@ fn double_number(number_str: &str) -> Result { } ``` -Why would we do this? Well, if we have a lot of functions that could return -`ParseIntError`, then it's much more convenient to define an alias that always -uses `ParseIntError` so that we don't have to write it out all the time. - -The most prominent place this idiom is used in the standard library is -with [`io::Result`](../std/io/type.Result.html). Typically, one writes -`io::Result`, which makes it clear that you're using the `io` -module's type alias instead of the plain definition from -`std::result`. (This idiom is also used for -[`fmt::Result`](../std/fmt/type.Result.html).) - -## A brief interlude: unwrapping isn't evil - -If you've been following along, you might have noticed that I've taken a pretty -hard line against calling methods like `unwrap` that could `panic` and abort -your program. *Generally speaking*, this is good advice. - -However, `unwrap` can still be used judiciously. What exactly justifies use of -`unwrap` is somewhat of a grey area and reasonable people can disagree. I'll -summarize some of my *opinions* on the matter. - -* **In examples and quick 'n' dirty code.** Sometimes you're writing examples - or a quick program, and error handling simply isn't important. Beating the - convenience of `unwrap` can be hard in such scenarios, so it is very - appealing. -* **When panicking indicates a bug in the program.** When the invariants of - your code should prevent a certain case from happening (like, say, popping - from an empty stack), then panicking can be permissible. This is because it - exposes a bug in your program. This can be explicit, like from an `assert!` - failing, or it could be because your index into an array was out of bounds. - -This is probably not an exhaustive list. Moreover, when using an -`Option`, it is often better to use its -[`expect`](../std/option/enum.Option.html#method.expect) -method. `expect` does exactly the same thing as `unwrap`, except it -prints a message you give to `expect`. This makes the resulting panic -a bit nicer to deal with, since it will show your message instead of -“called unwrap on a `None` value.” - -My advice boils down to this: use good judgment. There's a reason why the words -“never do X” or “Y is considered harmful” don't appear in my writing. There are -trade offs to all things, and it is up to you as the programmer to determine -what is acceptable for your use cases. My goal is only to help you evaluate -trade offs as accurately as possible. - -Now that we've covered the basics of error handling in Rust, and -explained unwrapping, let's start exploring more of the standard -library. - -# Working with multiple error types - -Thus far, we've looked at error handling where everything was either an -`Option` or a `Result`. But what happens when you have both an -`Option` and a `Result`? Or what if you have a `Result` and a -`Result`? Handling *composition of distinct error types* is the next -challenge in front of us, and it will be the major theme throughout the rest of -this chapter. - -## Composing `Option` and `Result` - -So far, I've talked about combinators defined for `Option` and combinators -defined for `Result`. We can use these combinators to compose results of -different computations without doing explicit case analysis. - -Of course, in real code, things aren't always as clean. Sometimes you have a -mix of `Option` and `Result` types. Must we resort to explicit case analysis, -or can we continue using combinators? - -For now, let's revisit one of the first examples in this chapter: + + + +なぜ、こうするのでしょうか? +もし `ParseIntError` を返す関数をたくさん定義するとしたら、常に `ParseIntError` を使うエイリアスを定義したほうが便利だからです。 +こうすれば、同じことを何度も書かずに済みます。 + + + + + + + +標準ライブラリで、このイディオムが際立って多く使われている場所では、[`io::Result`](../std/io/type.Result.html) を用いています。 +それらは通常 `io::Result` のように書かれ、`std::result` のプレーンな定義の代わりに `io` モジュールの型エイリアスを使っていることが、明確にわかるようになっています。 + + +## 小休止:アンラップは悪ではない + + + + +これまでの説明を読んだあなたは、 `unwrap` のような `panic` を起こし、プログラムをアボートするようなメソッドについて、私がきっぱりと否定する方針をとっていたことに気づいたかもしれません。 +*一般的には* これは良いアドバイスです。 + + + + +しかしながら `unwrap` を使うのが懸命なこともあります。 +どんな場合が `unwrap` の使用を正当化できるのかについては、グレーな部分があり、人によって意見が分かれます。 +ここで、この問題についての、私の *個人的な意見* をまとめたいと思います。 + + + + + +* **即興で書いたサンプルコード。** + サンプルコードや簡単なプログラムを書いていて、エラーハンドリングが単に重要でないこともあります。 + このようなときに `unwrap` の便利さは、とても魅力的に映るでしょう。 + これに打ち勝つのは難しいことです。 + + + + + + +* **パニックがプログラムのバグの兆候となるとき。** + コードの中の不変条件が、ある特定のケースの発生を未然に防ぐとき(例えば、空のスタックから取り出そうとしたなど)、パニックを起こしても差し支えありません。 + なぜなら、そうすることでプログラムに潜むバグが明るみに出るからです。 + これは `assert!` の失敗のような明示的な要因によるものだったり、配列のインデックスが境界から外れたからだったりします。 + + + + + + + + +これは多分、完全なリストではないでしょう。 +さらに `Option` を使うときは、ほとんどの場合で [`expect`](../std/option/enum.Option.html#method.expect) メソッドを使う方がいいでしょう。 +`expect` は `unwrap` とほぼ同じことをしますが、 `expect` では与えられたメッセージを表示するところが異なります。 +この方が結果として起こったパニックを、少し扱いやすいものにします。 +なぜなら「 `None` な値に対してアンラップが呼ばれました」というメッセージの代わりに、指定したメッセージが表示されるからです。 + + + + + + +私のアドバイスを突き詰めると、よく見極めなさい、ということです。 +私の書いた文章の中に「決して、Xをしてはならない」とか「Yは有害だと考えよう」といった言葉が現れないのには、れっきとした理由があります。 +あるユースケースでこれが容認できるかどうかは、プログラマであるあなたの判断に委ねられます。 +私が目指していることは、あなたがトレードオフをできるかぎり正確に評価できるよう、手助けをすることなのです。 + + + + +これでRustにおけるエラーハンドリングの基礎をカバーできました。 +また、アンラップについても解説しました。 +では標準ライブラリをもっと探索していきましょう。 + + +# 複数のエラー型を扱う + + +これまで見てきたエラーハンドリングでは、 `Option` または `Result` が1つあるだけでした。 +ではもし `Option` と `Result` の両方があったらどうなるでしょうか? +あるいは、`Result` と `Result` があったら? +*異なるエラー型の組み合わせ* を扱うことが、いま目の前にある次なる課題です。 +またこれが、この章の残りの大半に共通する、主要なテーマとなります。 + + +## `Option` と `Result` を合成する + + + + +これまで話してきたのは `Option` のために定義されたコンビネータと、 `Result` のために定義されたコンビネータについてでした。 +これらのコンビネータを使うと、様々な処理の結果を明示的な場合分けなしに組み合わせることができました。 + + + + +もちろん現実のコードは、いつもこんなにクリーンではありません。 +時には `Option` 型と `Result` 型が混在していることもあるでしょう。 +そんなときは、明示的な場合分けに頼るしかないのでしょうか? +それとも、コンビネータを使い続けることができるのでしょうか? + + +ここで、この章の最初の方にあった例に戻ってみましょう: ```rust,should_panic use std::env; fn main() { let mut argv = env::args(); - let arg: String = argv.nth(1).unwrap(); // error 1 - let n: i32 = arg.parse().unwrap(); // error 2 + let arg: String = argv.nth(1).unwrap(); // エラー1 + let n: i32 = arg.parse().unwrap(); // エラー2 println!("{}", 2 * n); } ``` -Given our new found knowledge of `Option`, `Result` and their various -combinators, we should try to rewrite this so that errors are handled properly -and the program doesn't panic if there's an error. + + + +これまでに獲得した知識、つまり `Option` 、`Result` と、それらのコンビネータに関する知識を動員して、これを書き換えましょう。 +エラーを適切に処理し、もしエラーが起こっても、プログラムがパニックしないようにするのです。 -The tricky aspect here is that `argv.nth(1)` produces an `Option` while -`arg.parse()` produces a `Result`. These aren't directly composable. When faced -with both an `Option` and a `Result`, the solution is *usually* to convert the -`Option` to a `Result`. In our case, the absence of a command line parameter -(from `env::args()`) means the user didn't invoke the program correctly. We -could just use a `String` to describe the error. Let's try: + + + + + + +ここでの問題は `argv.nth(1)` が `Option` を返すのに、 `arg.parse()` は `Result` を返すことです。 +これらを直接合成することはできません。 +`Option` と `Result` の両方に出会ったときの *通常の* 解決策は `Option` を `Result` に変換することです。 +この例で(`env::args()` が)コマンドライン引数を返さなかったということは、ユーザーがプログラムを正しく起動しなかったことを意味します。 +エラーの理由を示すために、単純に `String` を使うこともできます。 +試してみましょう: @@ -692,11 +983,20 @@ fn main() { } ``` -There are a couple new things in this example. The first is the use of the -[`Option::ok_or`](../std/option/enum.Option.html#method.ok_or) -combinator. This is one way to convert an `Option` into a `Result`. The -conversion requires you to specify what error to use if `Option` is `None`. -Like the other combinators we've seen, its definition is very simple: +> 訳注: +> +> Please give at least one argument:引数を最低1つ指定してください。 + + + + + + +この例では、いくつか新しいことがあります。 +ひとつ目は [`Option::ok_or`](../std/option/enum.Option.html#method.ok_or) コンビネータを使ったことです。 +これは `Option` を `Result` へ変換する方法の一つです。 +変換には `Option` が `None` のときに使われるエラーを指定する必要があります。 +他のコンビネータと同様に、その定義はとてもシンプルです: ```rust fn ok_or(option: Option, err: E) -> Result { @@ -707,32 +1007,49 @@ fn ok_or(option: Option, err: E) -> Result { } ``` -The other new combinator used here is -[`Result::map_err`](../std/result/enum.Result.html#method.map_err). -This is just like `Result::map`, except it maps a function on to the *error* -portion of a `Result` value. If the `Result` is an `Ok(...)` value, then it is -returned unmodified. - -We use `map_err` here because it is necessary for the error types to remain -the same (because of our use of `and_then`). Since we chose to convert the -`Option` (from `argv.nth(1)`) to a `Result`, we must -also convert the `ParseIntError` from `arg.parse()` to a `String`. - -## The limits of combinators - -Doing IO and parsing input is a very common task, and it's one that I -personally have done a lot of in Rust. Therefore, we will use (and continue to -use) IO and various parsing routines to exemplify error handling. - -Let's start simple. We are tasked with opening a file, reading all of its -contents and converting its contents to a number. Then we multiply it by `2` -and print the output. - -Although I've tried to convince you not to use `unwrap`, it can be useful -to first write your code using `unwrap`. It allows you to focus on your problem -instead of the error handling, and it exposes the points where proper error -handling need to occur. Let's start there so we can get a handle on the code, -and then refactor it to use better error handling. + + + + + +ここで使った、もう一つの新しいコンビネータは [`Result::map_err`](../std/result/enum.Result.html#method.map_err) です。 +これは `Result::map` に似ていますが、 `Result` 値の *エラー* の部分に対して関数をマップするところが異なります。 +もし `Result` の値が `Ok(...)` だったら、そのまま変更せずに返します。 + + + + + +`map_err` を使った理由は、(`and_then` の用法により)エラーの型を同じに保つ必要があったからです。 +ここでは(`argv.nth(1)`が返した) `Option` を `Result` に変換することを選んだため、`arg.parse()` が返した `ParseIntError` も `String` に変換しなければならなかったわけです。 + + +## コンビネータの限界 + + + + +入出力と共に入力をパースすることは、非常によく行われます。 +そして私がRustを使って個人的にやってきたことのほとんども、これに該当しています。 +ですから、ここでは(そして、この後も) IOと様々なパースを行うルーチンを、エラーハンドリングの例として扱っていきます。 + + + + +まずは簡単なものから始めましょう。 +ここでのタスクは、ファイルを開き、その内容を全て読み込み、1つの数値に変換することです。 +そしてそれに `2` を掛けて、結果を表示します。 + + + + + + +いままで `unwrap` を使わないよう説得してきたわけですが、最初にコードを書くときには `unwrap` が便利に使えます。 +こうすることで、エラーハンドリングではなく、本来解決すべき課題に集中できます。 +それと同時に `unwrap` は、適切なエラーハンドリングが必要とされる場所を教えてくれます。 +ここから始めることをコーディングへの取っ掛かりとしましょう。 +その後、リファクタリングによって、エラーハンドリングを改善していきます。 ```rust,should_panic use std::fs::File; @@ -740,10 +1057,10 @@ use std::io::Read; use std::path::Path; fn file_double>(file_path: P) -> i32 { - let mut file = File::open(file_path).unwrap(); // error 1 + let mut file = File::open(file_path).unwrap(); // エラー1 let mut contents = String::new(); - file.read_to_string(&mut contents).unwrap(); // error 2 - let n: i32 = contents.trim().parse().unwrap(); // error 3 + file.read_to_string(&mut contents).unwrap(); // エラー2 + let n: i32 = contents.trim().parse().unwrap(); // エラー3 2 * n } @@ -753,47 +1070,76 @@ fn main() { } ``` -(N.B. The `AsRef` is used because those are the -[same bounds used on -`std::fs::File::open`](../std/fs/struct.File.html#method.open). -This makes it ergonomic to use any kind of string as a file path.) - -There are three different errors that can occur here: - -1. A problem opening the file. -2. A problem reading data from the file. -3. A problem parsing the data as a number. - -The first two problems are described via the -[`std::io::Error`](../std/io/struct.Error.html) type. We know this -because of the return types of -[`std::fs::File::open`](../std/fs/struct.File.html#method.open) and -[`std::io::Read::read_to_string`](../std/io/trait.Read.html#method.read_to_string). -(Note that they both use the [`Result` type alias -idiom](#the-result-type-alias-idiom) described previously. If you -click on the `Result` type, you'll [see the type -alias](../std/io/type.Result.html), and consequently, the underlying -`io::Error` type.) The third problem is described by the -[`std::num::ParseIntError`](../std/num/struct.ParseIntError.html) -type. The `io::Error` type in particular is *pervasive* throughout the -standard library. You will see it again and again. - -Let's start the process of refactoring the `file_double` function. To make this -function composable with other components of the program, it should *not* panic -if any of the above error conditions are met. Effectively, this means that the -function should *return an error* if any of its operations fail. Our problem is -that the return type of `file_double` is `i32`, which does not give us any -useful way of reporting an error. Thus, we must start by changing the return -type from `i32` to something else. - -The first thing we need to decide: should we use `Option` or `Result`? We -certainly could use `Option` very easily. If any of the three errors occur, we -could simply return `None`. This will work *and it is better than panicking*, -but we can do a lot better. Instead, we should pass some detail about the error -that occurred. Since we want to express the *possibility of error*, we should -use `Result`. But what should `E` be? Since two *different* types of -errors can occur, we need to convert them to a common type. One such type is -`String`. Let's see how that impacts our code: + + + + +(備考: `AsRef` を使ったのは、[`std::fs::File::open` で使われているものと同じ境界](../std/fs/struct.File.html#method.open) だからです。 +ファイルパスとして、どんな文字列でも受け付けるので、エルゴノミックになります。) + + +ここでは3種類のエラーが起こる可能性があります: + + + + +1. ファイルを開くときの問題 +2. ファイルからデータを読み込むときの問題 +3. データを数値としてパースするときの問題 + + + + + + + + + + + + + + +最初の2つの問題は、[`std::io::Error`](../std/io/struct.Error.html) 型で記述されます。 +これは [`std::fs::File::open`](../std/fs/struct.File.html#method.open) と [`std::io::Read::read_to_string`](../std/io/trait.Read.html#method.read_to_string) のリターン型からわかります。 +(ちなみにどちらも、以前紹介した [`Result` 型エイリアスのイディオム](#result-型エイリアスを用いたイディオム) を用いています。 +`Result` 型のところをクリックすると、いま言った [型エイリアスを見たり](../std/io/type.Result.html)、必然的に、中で使われている `io::Error` 型も見ることになるでしょう。) +3番目の問題は [`std::num::ParseIntError`](../std/num/struct.ParseIntError.html) 型で記述されます。 +特にこの `io::Error` 型は標準ライブラリ全体に *深く浸透しています* 。 +これからこの型を幾度となく見ることでしょう。 + + + + + + + + +まず最初に `file_double` 関数をリファクタリングしましょう。 +この関数を、このプログラムの他の構成要素と合成可能にするためには、上記の問題のいずれかに遭遇しても、パニック *しない* ようにしなければなりません。 +これは実質的には、なにかの操作に失敗したときに、この関数が *エラーを返すべき* であることを意味します。 +ここでの問題は、`file_double` のリターン型が `i32` であるため、エラーの報告には全く役立たないことです。 +従ってリターン型を `i32` から別の何かに変えることから始めましょう。 + + + + + + + + + +最初に決めるべきことは、 `Option` と `Result` のどちらを使うかです。 +`Option` なら間違いなく簡単に使えます。 +もし3つのエラーのどれかが起こったら、単に `None` を返せばいいのですから。 +これはたしかに動きますし、 *パニックを起こすよりは良くなっています* 。 +とはいえ、もっと良くすることもできます。 +`Option` の代わりに、発生したエラーについての詳細を渡すべきでしょう。 +ここでは *エラーの可能性* を示したいのですから、`Result` を使うのがよさそうです。 +でも `E` を何にしたらいいのでしょうか? +2つの *異なる* 型のエラーが起こり得ますので、これらを共通の型に変換する必要があります。 +そのような型の一つに `String` があります。 +この変更がコードにどんな影響を与えるか見てみましょう: ```rust use std::fs::File; @@ -824,39 +1170,62 @@ fn main() { } ``` -This code looks a bit hairy. It can take quite a bit of practice before code -like this becomes easy to write. The way we write it is by *following the -types*. As soon as we changed the return type of `file_double` to -`Result`, we had to start looking for the right combinators. In -this case, we only used three different combinators: `and_then`, `map` and -`map_err`. - -`and_then` is used to chain multiple computations where each computation could -return an error. After opening the file, there are two more computations that -could fail: reading from the file and parsing the contents as a number. -Correspondingly, there are two calls to `and_then`. - -`map` is used to apply a function to the `Ok(...)` value of a `Result`. For -example, the very last call to `map` multiplies the `Ok(...)` value (which is -an `i32`) by `2`. If an error had occurred before that point, this operation -would have been skipped because of how `map` is defined. - -`map_err` is the trick that makes all of this work. `map_err` is just like -`map`, except it applies a function to the `Err(...)` value of a `Result`. In -this case, we want to convert all of our errors to one type: `String`. Since -both `io::Error` and `num::ParseIntError` implement `ToString`, we can call the -`to_string()` method to convert them. - -With all of that said, the code is still hairy. Mastering use of combinators is -important, but they have their limits. Let's try a different approach: early -returns. - -## Early returns - -I'd like to take the code from the previous section and rewrite it using *early -returns*. Early returns let you exit the function early. We can't return early -in `file_double` from inside another closure, so we'll need to revert back to -explicit case analysis. + + + + + + +このコードは、やや難解になってきました。 +このようなコードを簡単に書けるようになるまでには、結構な量の練習が必要かもしれません。 +こういうもの書くときは *型に導かれる* ようにします。 +`file_double` のリターン型を `Result` に変更したらすぐに、それに合ったコンビネータを探し始めるのです。 +この例では `and_then`, `map`, `map_err` の、3種類のコンビネータだけを使いました。 + + + + + +`and_then` は、エラーを返すかもしれない処理同士を繋いでいくために使います。 +ファイルを開いた後に、失敗するかもしれない処理が2つあります: +ファイルからの読み込む所と、内容を数値としてパースする所です。 +これに対応して `and_then` も2回呼ばれています。 + + + + + +`map` は `Result` の値が `Ok(...)` のときに関数を適用するために使います。 +例えば、一番最後の `map` の呼び出しは、`Ok(...)` の値( `i32` 型)に `2` を掛けます。 +もし、これより前にエラーが起きたなら、この操作は `map` の定義に従ってスキップされます。 + + + + + + +`map_err` は全体をうまく動かすための仕掛けです。 +`map_err` は `map` に似ていますが、 `Result` の値が `Err(...)` のときに関数を適用するところが異なります。 +今回の場合は、全てのエラーを `String` という同一の型に変換する予定でした。 +`io::Error` と `num::ParseIntError` の両方が `ToString` を実装していたので、 `to_string()` メソッドを呼ぶことで変換できました。 + + + + +説明し終わった後でも、このコードは難解なままです。 +コンビネータの使い方をマスターすることは重要ですが、コンビネータには限界もあるのです。 +次は、早期リターンと呼ばれる、別のアプローチを試してみましょう。 + + +## 早期リターン + + + + + +前の節で使ったコードを、 *早期リターン* を使って書き直してみようと思います。 +早期リターンとは、関数の途中で抜けることを指します。 +`file_double` のクロージャの中にいる間は、早期リターンはできないので、明示的な場合分けまでいったん戻る必要があります。 ```rust use std::fs::File; @@ -887,25 +1256,40 @@ fn main() { } ``` -Reasonable people can disagree over whether this code is better that the code -that uses combinators, but if you aren't familiar with the combinator approach, -this code looks simpler to read to me. It uses explicit case analysis with -`match` and `if let`. If an error occurs, it simply stops executing the -function and returns the error (by converting it to a string). - -Isn't this a step backwards though? Previously, we said that the key to -ergonomic error handling is reducing explicit case analysis, yet we've reverted -back to explicit case analysis here. It turns out, there are *multiple* ways to -reduce explicit case analysis. Combinators aren't the only way. - -## The `try!` macro - -A cornerstone of error handling in Rust is the `try!` macro. The `try!` macro -abstracts case analysis just like combinators, but unlike combinators, it also -abstracts *control flow*. Namely, it can abstract the *early return* pattern -seen above. - -Here is a simplified definition of a `try!` macro: + + + + + +このコードが、コンビネータを使ったコードよりも良くなったのかについては、人によって意見が分かれるでしょう。 +でも、もしあなたがコンビネータによるアプローチに不慣れだったら、このコードのほうが読みやすいと思うかもしれません。 +ここでは明示的な場合分けを `match` と `if let` で行っています。 +もしエラーが起きたら関数の実行を打ち切って、エラーを(文字列に変換してから)返します。 + + + + + +でもこれって逆戻りしてませんか? +以前は、エラーハンドリングをエルゴノミックにするために、明示的な場合分けを減らすべきだと言っていました。 +それなのに、今は明示的な場合分けに戻ってしまっています。 +すぐにわかりますが、明示的な場合分けを減らす方法は *複数* あるのです。 +コンビネータが唯一の方法ではありません。 + + +## `try!` マクロ + + + + + +Rustでのエラー処理の基礎となるのは `try!` マクロです。 +`try!` マクロはコンビネータと同様、場合分けを抽象化します。 +しかし、コンビネータと異なるのは *制御フロー* も抽象化してくれることです。 +つまり、先ほど見た *早期リターン* のパターンを抽象化できるのです。 + + +`try!` マクロの簡略化した定義はこうなります: @@ -918,12 +1302,16 @@ macro_rules! try { } ``` -(The [real definition](../std/macro.try!.html) is a bit more -sophisticated. We will address that later.) + + +([本当の定義](../std/macro.try!.html) はもっと洗練されています。 +後ほど紹介します。) -Using the `try!` macro makes it very easy to simplify our last example. Since -it does the case analysis and the early return for us, we get tighter code that -is easier to read: + + + +`try!` マクロを使うと、最後の例をシンプルにすることが、とても簡単にできます。 +場合分けと早期リターンを肩代わりしてくれますので、コードが締まって読みやすくなります。 ```rust use std::fs::File; @@ -946,61 +1334,92 @@ fn main() { } ``` -The `map_err` calls are still necessary given -[our definition of `try!`](#code-try-def-simple). -This is because the error types still need to be converted to `String`. -The good news is that we will soon learn how to remove those `map_err` calls! -The bad news is that we will need to learn a bit more about a couple important -traits in the standard library before we can remove the `map_err` calls. - -## Defining your own error type - -Before we dive into some of the standard library error traits, I'd like to wrap -up this section by removing the use of `String` as our error type in the -previous examples. - -Using `String` as we did in our previous examples is convenient because it's -easy to convert errors to strings, or even make up your own errors as strings -on the spot. However, using `String` for your errors has some downsides. - -The first downside is that the error messages tend to clutter your -code. It's possible to define the error messages elsewhere, but unless -you're unusually disciplined, it is very tempting to embed the error -message into your code. Indeed, we did exactly this in a [previous -example](#code-error-double-string). - -The second and more important downside is that `String`s are *lossy*. That is, -if all errors are converted to strings, then the errors we pass to the caller -become completely opaque. The only reasonable thing the caller can do with a -`String` error is show it to the user. Certainly, inspecting the string to -determine the type of error is not robust. (Admittedly, this downside is far -more important inside of a library as opposed to, say, an application.) - -For example, the `io::Error` type embeds an -[`io::ErrorKind`](../std/io/enum.ErrorKind.html), -which is *structured data* that represents what went wrong during an IO -operation. This is important because you might want to react differently -depending on the error. (e.g., A `BrokenPipe` error might mean quitting your -program gracefully while a `NotFound` error might mean exiting with an error -code and showing an error to the user.) With `io::ErrorKind`, the caller can -examine the type of an error with case analysis, which is strictly superior -to trying to tease out the details of an error inside of a `String`. - -Instead of using a `String` as an error type in our previous example of reading -an integer from a file, we can define our own error type that represents errors -with *structured data*. We endeavor to not drop information from underlying -errors in case the caller wants to inspect the details. - -The ideal way to represent *one of many possibilities* is to define our own -sum type using `enum`. In our case, an error is either an `io::Error` or a -`num::ParseIntError`, so a natural definition arises: + + + + + + +[今の私たちの `try!` の定義](#code-try-def-simple) ですと、 `map_err` は今でも必要です。 +なぜなら、エラー型を `String` に変換しなければならないからです。 +でも、いい知らせがあります。 +`map_err` の呼び出しを省く方法をすぐに習うのです! +悪い知らせは、`map_err` を省く前に、標準ライブラリのいくつかの重要なトレイトについて、もう少し学ぶ必要があるということです。 + + +## 独自のエラー型を定義する + + + + +標準ライブラリのいくつかのエラートレイトについて学ぶ前に、これまでの例にあったエラー型における `String` の使用を取り除くことで、この節を締めくくりたいと思います。 + + + + +これまでの例では `String` を便利に使ってきました。 +なぜなら、エラーは簡単に文字列へ変換できますし、問題が起こったその場で、文字列によるエラーを新たに作ることもできるからです。 +しかし `String` を使ってエラーを表すことには欠点もあります。 + + + + + + +ひとつ目の欠点は、エラーメッセージがコードのあちこちに散らかる傾向があることです。 +エラーメッセージをどこか別の場所でまとめて定義することもできますが、特別に訓練された人でない限りは、エラーメッセージをコードに埋め込むことへの誘惑に負けてしまうでしょう。 +実際、私たちは [以前の例](#code-error-double-string) でも、その通りのことをしました。 + + + + + + + +ふたつ目の、もっと重大な欠点は、 `String` への変換で *情報が欠落する* ことです。 +もし全てのエラーを文字列に変換してしまったら、呼び出し元に渡したエラーが、オペーク(不透明)になってしまいます。 +呼び出し元が `String` のエラーに対してできる唯一妥当なことは、それをユーザーに表示することだけです。 +文字列を解析して、どのタイプのエラーだったか判断するのは、もちろん強固なやり方とはいえません。 +(この問題は、ライブラリーの中の方が、他のアプケーションのようなものよりも、間違いなく重大なものになるでしょう。) + + + + + + + + + + +例えば `io::Error` 型には [`io::ErrorKind`](../std/io/enum.ErrorKind.html) が埋め込まれます。 +これは *構造化されたデータ* で、IO操作において何が失敗したのかを示します。 +エラーによって違った対応を取りたいこともあるので、このことは重要です。 +(例: あなたのアプリケーションでは `BrokenPipe` エラーは正規の手順を踏んだ終了を意味し、 `NotFound` エラーはエラーコードと共に異常終了して、ユーザーにエラーを表示することを意味するかもしれません。) +`io::ErrorKind` なら、呼び出し元でエラーの種類を調査するために、場合分けが使えます。 +これは `String` の中からエラーの詳細がなんだったのか探りだすことよりも、明らかに優れています。 + + + + + +ファイルから整数値を取り出す例で `String` をエラー型として用いた代わりに、独自のエラー型を定義し、 *構造化されたデータ* によってエラー内容を表すことができます。 +呼び出し元が詳細を検査したいときに備え、大元のエラーについての情報を取りこぼさないよう、努力してみましょう。 + + + + +*多くの可能性のうちの一つ* を表す理想的な方法は、 `enum` を使って独自の直和型を定義することです。 +このケースでは、エラーは `io::Error` もしくは `num::ParseIntError` でした。 +ここから思い浮かぶ自然な定義は: ```rust use std::io; use std::num; -// We derive `Debug` because all types should probably derive `Debug`. -// This gives us a reasonable human readable description of `CliError` values. +# // We derive `Debug` because all types should probably derive `Debug`. +# // This gives us a reasonable human readable description of `CliError` values. +// 全ての型は `Debug` を導出するべきでしょうから、ここでも `Debug` を導出します。 +// これにより `CliError` 値について、人間が十分理解できる説明を得られます。 #[derive(Debug)] enum CliError { Io(io::Error), @@ -1008,9 +1427,11 @@ enum CliError { } ``` -Tweaking our code is very easy. Instead of converting errors to strings, we -simply convert them to our `CliError` type using the corresponding value -constructor: + + + +コードの微調整はいとも簡単です。 +エラーを文字列に変換する代わりに、エラーに対応する値コンストラクタを用いて `CliError` 型に変換すればいいのです: ```rust # #[derive(Debug)] @@ -1035,17 +1456,24 @@ fn main() { } ``` -The only change here is switching `map_err(|e| e.to_string())` (which converts -errors to strings) to `map_err(CliError::Io)` or `map_err(CliError::Parse)`. -The *caller* gets to decide the level of detail to report to the user. In -effect, using a `String` as an error type removes choices from the caller while -using a custom `enum` error type like `CliError` gives the caller all of the -conveniences as before in addition to *structured data* describing the error. - -A rule of thumb is to define your own error type, but a `String` error type -will do in a pinch, particularly if you're writing an application. If you're -writing a library, defining your own error type should be strongly preferred so -that you don't remove choices from the caller unnecessarily. + + + + + + +ここでの変更点は、(エラーを文字列に変換する) `map_err(|e| e.to_string())` を、`map_err(CliError::Io)` や `map_err(CliError::Parse)` へ切り替えたことです。 +こうして *呼び出し元* が、ユーザーに対してどの程度の詳細を報告するか決められるようになりました。 +`String` をエラー型として用いることは、事実上、呼び出し元からこうした選択肢を奪ってしまいます。 +`CliError` のような独自の `enum` エラー型を用いることは、 *構造化されたデータ* によるエラーの説明だけでなく、これまでと同様の使いやすさをもたらします。 + + + + + +目安となる方法は独自のエラー型を定義することですが、 `String` エラー型も、いざというときに役立ちます。 +特にアプリケーションを書いているときなどはそうです。 +もしライブラリを書いているのなら、呼び出し元の選択肢を理由もなく奪わないために、独自のエラー型を定義することを強く推奨します。 # Standard library traits used for error handling diff --git a/1.6/ja/book/ffi.md b/1.6/ja/book/ffi.md index c3896e4e..5a6e7415 100644 --- a/1.6/ja/book/ffi.md +++ b/1.6/ja/book/ffi.md @@ -1,18 +1,25 @@ -% Foreign Function Interface +% 他言語関数インターフェイス + -# Introduction + +# 導入 -This guide will use the [snappy](https://github.com/google/snappy) -compression/decompression library as an introduction to writing bindings for -foreign code. Rust is currently unable to call directly into a C++ library, but -snappy includes a C interface (documented in -[`snappy-c.h`](https://github.com/google/snappy/blob/master/snappy-c.h)). + + + + + +このガイドでは、他言語コードのためのバインディングを書く導入に [snappy](https://github.com/google/snappy) という圧縮・展開ライブラリを使います。 +Rustは現在、C++ライブラリを直接呼び出すことができませんが、snappyはCのインターフェイスを持っています(ドキュメントが [`snappy-c.h`](https://github.com/google/snappy/blob/master/snappy-c.h) にあります)。 -## A note about libc + +## libcについてのメモ -Many of these examples use [the `libc` crate][libc], which provides various -type definitions for C types, among other things. If you’re trying these -examples yourself, you’ll need to add `libc` to your `Cargo.toml`: + + + +これらの例の多くは [`libc`クレート][libc] を使っています。これは、主にCの様々な型の定義を提供するものです。 +もしこれらの例を自分で試すのであれば、次のように `libc` を `Cargo.toml` に追加する必要があるでしょう。 ```toml [dependencies] @@ -21,12 +28,15 @@ libc = "0.2.0" [libc]: https://crates.io/crates/libc -and add `extern crate libc;` to your crate root. + +そして、クレートのルートに `extern crate libc;` を追加しましょう。 -## Calling foreign functions + +## 他言語関数の呼出し -The following is a minimal example of calling a foreign function which will -compile if snappy is installed: + + +次のコードは、snappyがインストールされていればコンパイルできる他言語関数を呼び出す最小の例です。 ```no_run # #![feature(libc)] @@ -44,23 +54,29 @@ fn main() { } ``` -The `extern` block is a list of function signatures in a foreign library, in -this case with the platform's C ABI. The `#[link(...)]` attribute is used to -instruct the linker to link against the snappy library so the symbols are -resolved. - -Foreign functions are assumed to be unsafe so calls to them need to be wrapped -with `unsafe {}` as a promise to the compiler that everything contained within -truly is safe. C libraries often expose interfaces that aren't thread-safe, and -almost any function that takes a pointer argument isn't valid for all possible -inputs since the pointer could be dangling, and raw pointers fall outside of -Rust's safe memory model. - -When declaring the argument types to a foreign function, the Rust compiler can -not check if the declaration is correct, so specifying it correctly is part of -keeping the binding correct at runtime. - -The `extern` block can be extended to cover the entire snappy API: + + + + +`extern` ブロックは他言語ライブラリの中の関数のシグネチャ、この例ではそのプラットフォーム上のC ABIによるもののリストです。 +`#[link(...)]` アトリビュートは、シンボルが解決できるように、リンカに対してsnappyのライブラリをリンクするよう指示するために使われています。 + + + + + + + +他言語関数はアンセーフとみなされるので、それらを呼び出すには、この中に含まれているすべてのものが本当に安全であるということをコンパイラに対して約束するために、 `unsafe {}` で囲まなければなりません。 +Cライブラリは、スレッドセーフでないインターフェイスを公開していることがありますし、ポインタを引数に取る関数のほとんどは、ポインタがダングリングポインタになる可能性を有しているので、すべての入力に対して有効なわけではありません。そして、生ポインタはRustの安全なメモリモデルから外れてしまいます。 + + + + +他言語関数について引数の型を宣言するとき、Rustのコンパイラはその宣言が正しいかどうかを確認することができません。それを正しく指定することは実行時にバインディングを正しく動作させるために必要なことです。 + + +`extern` ブロックはsnappyのAPI全体をカバーするように拡張することができます。 ```no_run # #![feature(libc)] @@ -87,16 +103,23 @@ extern { # fn main() {} ``` -# Creating a safe interface + +# 安全なインターフェイスの作成 -The raw C API needs to be wrapped to provide memory safety and make use of higher-level concepts -like vectors. A library can choose to expose only the safe, high-level interface and hide the unsafe -internal details. + + + +生のC APIは、メモリの安全性を提供し、ベクタのようなもっと高レベルの概念を使うようにラップしなければなりません。 +ライブラリは安全で高レベルなインターフェイスのみを公開するように選択し、アンセーフな内部の詳細を隠すことができます。 -Wrapping the functions which expect buffers involves using the `slice::raw` module to manipulate Rust -vectors as pointers to memory. Rust's vectors are guaranteed to be a contiguous block of memory. The -length is number of elements currently contained, and the capacity is the total size in elements of -the allocated memory. The length is less than or equal to the capacity. + + + + +バッファを期待する関数をラップするには、Rustのベクタをメモリへのポインタとして操作するために `slice::raw` モジュールを使います。 +Rustのベクタは隣接したメモリのブロックであることが保証されています。 +その長さは現在含んでいる要素の数で、容量は割り当てられたメモリの要素の合計のサイズです。 +長さは、容量以下です。 ```rust # #![feature(libc)] @@ -111,17 +134,22 @@ pub fn validate_compressed_buffer(src: &[u8]) -> bool { } ``` -The `validate_compressed_buffer` wrapper above makes use of an `unsafe` block, but it makes the -guarantee that calling it is safe for all inputs by leaving off `unsafe` from the function -signature. + + + +上の `validate_compressed_buffer` ラッパは `unsafe` ブロックを使っていますが、関数のシグネチャを `unsafe` から外すことによって、その呼出しがすべての入力に対して安全であることが保証されています。 -The `snappy_compress` and `snappy_uncompress` functions are more complex, since a buffer has to be -allocated to hold the output too. + + +結果を保持するようにバッファを割り当てなければならないため、 `snappy_compress` 関数と `snappy_uncompress` 関数はもっと複雑です。 -The `snappy_max_compressed_length` function can be used to allocate a vector with the maximum -required capacity to hold the compressed output. The vector can then be passed to the -`snappy_compress` function as an output parameter. An output parameter is also passed to retrieve -the true length after compression for setting the length. + + + + +`snappy_max_compressed_length` 関数は、圧縮後の結果を保持するために必要な最大の容量のベクタを割り当てるために使うことができます。 +そして、そのベクタは結果を受け取るための引数として`snappy_compress`関数に渡されます。 +結果を受け取るための引数は、長さをセットするために、圧縮後の本当の長さを取得するためにも渡されます。 ```rust # #![feature(libc)] @@ -147,8 +175,9 @@ pub fn compress(src: &[u8]) -> Vec { } ``` -Decompression is similar, because snappy stores the uncompressed size as part of the compression -format and `snappy_uncompressed_length` will retrieve the exact buffer size required. + + +snappyは展開後のサイズを圧縮フォーマットの一部として保存していて、 `snappy_uncompressed_length` が必要となるバッファの正確なサイズを取得するため、展開も同様です。 ```rust # #![feature(libc)] @@ -183,31 +212,43 @@ pub fn uncompress(src: &[u8]) -> Option> { } ``` -For reference, the examples used here are also available as a [library on -GitHub](https://github.com/thestinger/rust-snappy). + + +参考のために、ここで使った例は [GitHub上のライブラリ](https://github.com/thestinger/rust-snappy) としても置いておきます。 -# Destructors + +# デストラクタ -Foreign libraries often hand off ownership of resources to the calling code. -When this occurs, we must use Rust's destructors to provide safety and guarantee -the release of these resources (especially in the case of panic). + + + +他言語ライブラリはリソースの所有権を呼出先のコードに手渡してしまうことがあります。 +そういうことが起きる場合には、安全性を提供し、それらのリソースが解放されることを保証するために、Rustのデストラクタを使わなければなりません(特にパニックした場合)。 -For more about destructors, see the [Drop trait](../std/ops/trait.Drop.html). + +デストラクタについて詳しくは、[Dropトレイト](../std/ops/trait.Drop.html)を見てください。 -# Callbacks from C code to Rust functions + +# CのコードからRustの関数へのコールバック -Some external libraries require the usage of callbacks to report back their -current state or intermediate data to the caller. -It is possible to pass functions defined in Rust to an external library. -The requirement for this is that the callback function is marked as `extern` -with the correct calling convention to make it callable from C code. + + + + + +外部のライブラリの中には、現在の状況や中間的なデータを呼出元に報告するためにコールバックを使わなければならないものがあります。 +Rustで定義された関数を外部のライブラリに渡すことは可能です。 +これをするために必要なのは、Cのコードから呼び出すことができるように正しい呼出規則に従って、コールバック関数を `extern` としてマークしておくことです。 -The callback function can then be sent through a registration call -to the C library and afterwards be invoked from there. + + +そして、登録呼出しを通じてコールバック関数をCのライブラリに送ることができるようになり、後でそれらから呼び出すことができるようになります。 -A basic example is: + +基本的な例は次のとおりです。 -Rust code: + +これがRustのコードです。 ```no_run extern fn callback(a: i32) { @@ -223,12 +264,14 @@ extern { fn main() { unsafe { register_callback(callback); - trigger_callback(); // Triggers the callback +# // trigger_callback(); // Triggers the callback + trigger_callback(); // コールバックをトリガーする } } ``` -C code: + +これがCのコードです。 ```c typedef void (*rust_callback)(int32_t); @@ -240,39 +283,49 @@ int32_t register_callback(rust_callback callback) { } void trigger_callback() { - cb(7); // Will call callback(7) in Rust + cb(7); // Rustのcallback(7)を呼び出す } ``` -In this example Rust's `main()` will call `trigger_callback()` in C, -which would, in turn, call back to `callback()` in Rust. + + +この例では、Rustの `main()` がCの `trigger_callback()` を呼び出し、今度はそれが、Rustの `callback()` をコールバックしています。 + +## Rustのオブジェクトを対象にしたコールバック -## Targeting callbacks to Rust objects + + + + +先程の例では、グローバルな関数をCのコードから呼ぶための方法を示してきました。 +しかし、特別なRustのオブジェクトをコールバックの対象にしたいことがあります。 +これは、そのオブジェクトをそれぞれCのオブジェクトのラッパとして表現することで可能になります。 -The former example showed how a global function can be called from C code. -However it is often desired that the callback is targeted to a special -Rust object. This could be the object that represents the wrapper for the -respective C object. + + + + +これは、そのオブジェクトへの生ポインタをCライブラリに渡すことで実現できます。 +そして、CのライブラリはRustのオブジェクトへのポインタをその通知の中に含むことができるようになります。 +これにより、そのコールバックは参照されるRustのオブジェクトにアンセーフな形でアクセスできるようになります。 -This can be achieved by passing an raw pointer to the object down to the -C library. The C library can then include the pointer to the Rust object in -the notification. This will allow the callback to unsafely access the -referenced Rust object. - -Rust code: + +これがRustのコードです。 ```no_run #[repr(C)] struct RustObject { a: i32, - // other members +# // other members + // その他のメンバ } extern "C" fn callback(target: *mut RustObject, a: i32) { println!("I'm called from C with value {0}", a); unsafe { - // Update the value in RustObject with the value received from the callback +# // Update the value in RustObject with the value received from the callback + // コールバックから受け取った値でRustObjectの中の値をアップデートする (*target).a = a; } } @@ -285,7 +338,8 @@ extern { } fn main() { - // Create the object that will be referenced in the callback +# // Create the object that will be referenced in the callback + // コールバックから参照されるオブジェクトを作成する let mut rust_object = Box::new(RustObject { a: 5 }); unsafe { @@ -295,7 +349,8 @@ fn main() { } ``` -C code: + +これがCのコードです。 ```c typedef void (*rust_callback)(void*, int32_t); @@ -309,102 +364,144 @@ int32_t register_callback(void* callback_target, rust_callback callback) { } void trigger_callback() { - cb(cb_target, 7); // Will call callback(&rustObject, 7) in Rust +# // cb(cb_target, 7); // Will call callback(&rustObject, 7) in Rust + cb(cb_target, 7); // Rustのcallback(&rustObject, 7)を呼び出す } ``` -## Asynchronous callbacks - -In the previously given examples the callbacks are invoked as a direct reaction -to a function call to the external C library. -The control over the current thread is switched from Rust to C to Rust for the -execution of the callback, but in the end the callback is executed on the -same thread that called the function which triggered the callback. - -Things get more complicated when the external library spawns its own threads -and invokes callbacks from there. -In these cases access to Rust data structures inside the callbacks is -especially unsafe and proper synchronization mechanisms must be used. -Besides classical synchronization mechanisms like mutexes, one possibility in -Rust is to use channels (in `std::sync::mpsc`) to forward data from the C -thread that invoked the callback into a Rust thread. - -If an asynchronous callback targets a special object in the Rust address space -it is also absolutely necessary that no more callbacks are performed by the -C library after the respective Rust object gets destroyed. -This can be achieved by unregistering the callback in the object's -destructor and designing the library in a way that guarantees that no -callback will be performed after deregistration. - -# Linking - -The `link` attribute on `extern` blocks provides the basic building block for -instructing rustc how it will link to native libraries. There are two accepted -forms of the link attribute today: - + +## 非同期コールバック + + + + + + +先程の例では、コールバックは外部のCライブラリへの関数呼出しに対する直接の反応として呼びだされました。 +実行中のスレッドの制御はコールバックの実行のためにRustからCへ、そしてRustへと切り替わりますが、最後には、コールバックはコールバックを引き起こした関数を呼び出したものと同じスレッドで実行されます。 + + + + + + + + +外部のライブラリが独自のスレッドを生成し、そこからコールバックを呼び出すときには、事態はもっと複雑になります。 +そのような場合、コールバックの中のRustのデータ構造へのアクセスは特にアンセーフであり、適切な同期メカニズムを使わなければなりません。 +ミューテックスのような古典的な同期メカニズムの他にも、Rustではコールバックを呼び出したCのスレッドからRustのスレッドにデータを転送するために( `std::sync::mpsc` の中の)チャネルを使うという手もあります。 + + + + + + + +もし、非同期のコールバックがRustのアドレス空間の中の特別なオブジェクトを対象としていれば、それぞれのRustのオブジェクトが破壊された後、Cのライブラリからそれ以上コールバックが実行されないようにすることが絶対に必要です。 +これは、オブジェクトのデストラクタでコールバックの登録を解除し、登録解除後にコールバックが実行されないようにライブラリを設計することで実現できます。 + + +# リンク + + + + +`extern` ブロックの中の `link` アトリビュートは、rustcに対してネイティブライブラリをどのようにリンクするかを指示するための基本的な構成ブロックです。 +今のところ、2つの形式のlinkアトリビュートが認められています。 + + + * `#[link(name = "foo")]` * `#[link(name = "foo", kind = "bar")]` -In both of these cases, `foo` is the name of the native library that we're -linking to, and in the second case `bar` is the type of native library that the -compiler is linking to. There are currently three known types of native -libraries: - -* Dynamic - `#[link(name = "readline")]` -* Static - `#[link(name = "my_build_dependency", kind = "static")]` -* Frameworks - `#[link(name = "CoreFoundation", kind = "framework")]` - -Note that frameworks are only available on OSX targets. - -The different `kind` values are meant to differentiate how the native library -participates in linkage. From a linkage perspective, the Rust compiler creates -two flavors of artifacts: partial (rlib/staticlib) and final (dylib/binary). -Native dynamic library and framework dependencies are propagated to the final -artifact boundary, while static library dependencies are not propagated at -all, because the static libraries are integrated directly into the subsequent -artifact. - -A few examples of how this model can be used are: - -* A native build dependency. Sometimes some C/C++ glue is needed when writing - some Rust code, but distribution of the C/C++ code in a library format is just - a burden. In this case, the code will be archived into `libfoo.a` and then the - Rust crate would declare a dependency via `#[link(name = "foo", kind = - "static")]`. - - Regardless of the flavor of output for the crate, the native static library - will be included in the output, meaning that distribution of the native static - library is not necessary. - -* A normal dynamic dependency. Common system libraries (like `readline`) are - available on a large number of systems, and often a static copy of these - libraries cannot be found. When this dependency is included in a Rust crate, - partial targets (like rlibs) will not link to the library, but when the rlib - is included in a final target (like a binary), the native library will be - linked in. - -On OSX, frameworks behave with the same semantics as a dynamic library. - -# Unsafe blocks - -Some operations, like dereferencing raw pointers or calling functions that have been marked -unsafe are only allowed inside unsafe blocks. Unsafe blocks isolate unsafety and are a promise to -the compiler that the unsafety does not leak out of the block. - -Unsafe functions, on the other hand, advertise it to the world. An unsafe function is written like -this: + + + + +これらのどちらの形式でも、 `foo` はリンクするネイティブライブラリの名前で、2つ目の形式の `bar` はコンパイラがリンクするネイティブライブラリの種類です。 +3つのネイティブライブラリの種類が知られています。 + + + + +* ダイナミック - `#[link(name = "readline")]` +* スタティック - `#[link(name = "my_build_dependency", kind = "static")]` +* フレームワーク - `#[link(name = "CoreFoundation", kind = "framework")]` + + +フレームワークはOSXターゲットでのみ利用可能であることに注意しましょう。 + + + + + + + + +異なる `kind` の値はリンク時のネイティブライブラリの使われ方の違いを意味します。 +リンクの視点からすると、Rustコンパイラは2種類の生成物を作ります。 +部分生成物(rlib/staticlib)と最終生成物(dylib/binary)です。 +ネイティブダイナミックライブラリとフレームワークの依存関係は最終生成物を作るときまで伝播され解決されますが、スタティックライブラリの依存関係は全く伝えません。なぜなら、スタティックライブラリはその後に続く生成物に直接統合されてしまうからです。 + + +このモデルをどのように使うことができるのかという例は次のとおりです。 + + + + + + +* ネイティブビルドの依存関係。 + ときどき、Rustのコードを書くときにC/C++のグルーが必要になりますが、ライブラリの形式でのC/C++のコードの配布は重荷でしかありません。 + このような場合、 コードは `libfoo.a` にアーカイブされ、それからRustのクレートで `#[link(name = "foo", kind = "static")]` によって依存関係を宣言します。 + + + + + クレートの成果物の種類にかかわらず、ネイティブスタティックライブラリは成果物に含まれます。これは、ネイティブスタティックライブラリの配布は不要だということを意味します。 + + + + + + + +* 通常のダイナミックな依存関係。 + ( `readline` のような)一般的なシステムライブラリは多くのシステムで利用可能となっていますが、それらのライブラリのスタティックなコピーは見付からないことがしばしばあります。 + この依存関係をRustのクレートに含めるときには、(rlibのような)部分生成物のターゲットはライブラリをリンクしませんが、(binaryのような)最終生成物にrlibを含めるときには、ネイティブライブラリはリンクされます。 + + +OSXでは、フレームワークはダイナミックライブラリと同じ意味で振る舞います。 + + +# アンセーフブロック + + + + +生ポインタの参照外しやアンセーフであるとマークされた関数の呼出しなど、いくつかの作業はアンセーフブロックの中でのみ許されます。 +アンセーフブロックはアンセーフ性を隔離し、コンパイラに対してアンセーフ性がブロックの外に漏れ出さないことを約束します。 + + + +一方、アンセーフな関数はそれを全世界に向けて広告します。 +アンセーフな関数はこのように書きます。 ```rust unsafe fn kaboom(ptr: *const i32) -> i32 { *ptr } ``` -This function can only be called from an `unsafe` block or another `unsafe` function. + +この関数は `unsafe` ブロック又は他の `unsafe` な関数からのみ呼び出すことができます。 -# Accessing foreign globals + +# 他言語のグローバル変数へのアクセス -Foreign APIs often export a global variable which could do something like track -global state. In order to access these variables, you declare them in `extern` -blocks with the `static` keyword: + + + +他言語APIはしばしばグローバルな状態を追跡するようなことをするためのグローバル変数をエクスポートします。 +それらの値にアクセスするために、それらを `extern` ブロックの中で `static` キーワードを付けて宣言します。 ```no_run # #![feature(libc)] @@ -421,9 +518,11 @@ fn main() { } ``` -Alternatively, you may need to alter global state provided by a foreign -interface. To do this, statics can be declared with `mut` so we can mutate -them. + + + +あるいは、他言語インターフェイスが提供するグローバルな状態を変更しなければならないこともあるかもしれません。 +これをするために、スタティックな値を変更することができるように `mut` 付きで宣言することができます。 ```no_run # #![feature(libc)] @@ -449,14 +548,20 @@ fn main() { } ``` -Note that all interaction with a `static mut` is unsafe, both reading and -writing. Dealing with global mutable state requires a great deal of care. + + +`static mut` の付いた作用は全て、読込みと書込みの双方についてアンセーフであることに注意しましょう。 +グローバルでミュータブルな状態の扱いには多大な注意が必要です。 -# Foreign calling conventions + +# 他言語呼出規則 -Most foreign code exposes a C ABI, and Rust uses the platform's C calling convention by default when -calling foreign functions. Some foreign functions, most notably the Windows API, use other calling -conventions. Rust provides a way to tell the compiler which convention to use: + + + +他言語で書かれたコードの多くはC ABIをエクスポートしていて、Rustは他言語関数の呼出しのときのデフォルトとしてそのプラットフォーム上のCの呼出規則を使います。 +他言語関数の中には、特にWindows APIですが、他の呼出規則を使うものもあります。 +Rustにはコンパイラに対してどの規則を使うかを教える方法があります。 ```rust # #![feature(libc)] @@ -471,8 +576,10 @@ extern "stdcall" { # fn main() { } ``` -This applies to the entire `extern` block. The list of supported ABI constraints -are: + + +これは `extern` ブロック全体に適用されます。 +サポートされているABIの規則は次のとおりです。 * `stdcall` * `aapcs` @@ -484,56 +591,83 @@ are: * `C` * `win64` -Most of the abis in this list are self-explanatory, but the `system` abi may -seem a little odd. This constraint selects whatever the appropriate ABI is for -interoperating with the target's libraries. For example, on win32 with a x86 -architecture, this means that the abi used would be `stdcall`. On x86_64, -however, windows uses the `C` calling convention, so `C` would be used. This -means that in our previous example, we could have used `extern "system" { ... }` -to define a block for all windows systems, not just x86 ones. - -# Interoperability with foreign code - -Rust guarantees that the layout of a `struct` is compatible with the platform's -representation in C only if the `#[repr(C)]` attribute is applied to it. -`#[repr(C, packed)]` can be used to lay out struct members without padding. -`#[repr(C)]` can also be applied to an enum. - -Rust's owned boxes (`Box`) use non-nullable pointers as handles which point -to the contained object. However, they should not be manually created because -they are managed by internal allocators. References can safely be assumed to be -non-nullable pointers directly to the type. However, breaking the borrow -checking or mutability rules is not guaranteed to be safe, so prefer using raw -pointers (`*`) if that's needed because the compiler can't make as many -assumptions about them. - -Vectors and strings share the same basic memory layout, and utilities are -available in the `vec` and `str` modules for working with C APIs. However, -strings are not terminated with `\0`. If you need a NUL-terminated string for -interoperability with C, you should use the `CString` type in the `std::ffi` -module. - -The [`libc` crate on crates.io][libc] includes type aliases and function -definitions for the C standard library in the `libc` module, and Rust links -against `libc` and `libm` by default. - -# The "nullable pointer optimization" - -Certain types are defined to not be `null`. This includes references (`&T`, -`&mut T`), boxes (`Box`), and function pointers (`extern "abi" fn()`). -When interfacing with C, pointers that might be null are often used. -As a special case, a generic `enum` that contains exactly two variants, one of -which contains no data and the other containing a single field, is eligible -for the "nullable pointer optimization". When such an enum is instantiated -with one of the non-nullable types, it is represented as a single pointer, -and the non-data variant is represented as the null pointer. So -`Option c_int>` is how one represents a nullable -function pointer using the C ABI. - -# Calling Rust code from C - -You may wish to compile Rust code in a way so that it can be called from C. This is -fairly easy, but requires a few things: + + + + + + + +このリストのABIのほとんどは名前のとおりですが、 `system` ABIは少し変わっています。 +この規則はターゲットのライブラリを相互利用するために適切なABIを選択します。 +例えば、x86アーキテクチャのWin32では、使われるABIは `stdcall` になります。 +しかし、x86_64では、Windowsは `C` の呼出規則を使うので、 `C` が使われます。 +先程の例で言えば、 `extern "system" { ... }` を使って、x86のためだけではなく全てのWindowsシステムのためのブロックを定義することができるということです。 + + +# 他言語コードの相互利用 + + + + + +`#[repr(C)]` アトリビュートが適用されている場合に限り、Rustは `struct` のレイアウトとそのプラットフォーム上のCでの表現方法との互換性を保証します。 +`#[repr(C, packed)]` を使えば、パディングなしで構造体のメンバをレイアウトすることができます。 +`#[repr(C)]` は列挙型にも適用することができます。 + + + + + + + + +Rust独自のボックス( `Box` )は包んでいるオブジェクトを指すハンドルとして非ヌルポインタを使います。 +しかし、それらは内部のアロケータによって管理されるため、手で作るべきではありません。 +参照は型を直接指す非ヌルポインタとみなすことが安全にできます。 +しかし、借用チェックやミュータブルについてのルールが破られた場合、安全性は保証されません。生ポインタについてはコンパイラは借用チェックやミュータブルほどには仮定を置かないので、必要なときには、生ポインタ( `*` )を使いましょう。 + + + + + + +ベクタと文字列は基本的なメモリレイアウトを共有していて、 `vec` モジュールと `str` モジュールの中のユーティリティはC APIで扱うために使うことができます。 +ただし、文字列は `\0` で終わりません。 +Cと相互利用するためにNUL終端の文字列が必要であれば、 `std::ffi` モジュールの `CString` 型を使う必要があります。 + + + + +[crates.ioの`libc`クレート][libc] は `libc` モジュール内にCの標準ライブラリの型の別名や関数の定義を含んでいて、Rustは `libc` と `libm` をデフォルトでリンクします。 + + +# 「ヌルになり得るポインタの最適化」 + + + + + + + + + + + +いくつかの型は非 `null` であると定義されています。 +このようなものには、参照( `&T` 、 `&mut T` )、ボックス( `Box` )、そして関数ポインタ( `extern "abi" fn()` )があります。 +Cとのインターフェイスにおいては、ヌルになり得るポインタが使われることがしばしばあります。 +特別な場合として、ジェネリックな `enum` がちょうど2つのバリアントを持ち、そのうちの1つが値を持っていなくてもう1つが単一のフィールドを持っているとき、それは「ヌルになり得るポインタの最適化」の対象になります。 +そのような列挙型が非ヌルの型でインスタンス化されたとき、それは単一のポインタとして表現され、データを持っていない方のバリアントはヌルポインタとして表現されます。 +`Option c_int>` は、C ABIで使われるヌルになり得る関数ポインタの表現方法の1つです。 + + +# CからのRustのコードの呼出し + + + +RustのコードをCから呼び出せる方法でコンパイルしたいときがあるかもしれません。 +これは割と簡単ですが、いくつか必要なことがあります。 ```rust #[no_mangle] @@ -543,17 +677,23 @@ pub extern fn hello_rust() -> *const u8 { # fn main() {} ``` -The `extern` makes this function adhere to the C calling convention, as -discussed above in "[Foreign Calling -Conventions](ffi.html#foreign-calling-conventions)". The `no_mangle` -attribute turns off Rust's name mangling, so that it is easier to link to. + + + + +`extern` は先程「 [他言語呼出規則](ffi.html#foreign-calling-conventions) 」で議論したように、この関数をCの呼出規則に従うようにします。 +`no_mangle` アトリビュートはRustによる名前のマングリングをオフにして、リンクしやすいようにします。 -# FFI and panics + +# FFIとパニック -It’s important to be mindful of `panic!`s when working with FFI. A `panic!` -across an FFI boundary is undefined behavior. If you’re writing code that may -panic, you should run it in another thread, so that the panic doesn’t bubble up -to C: + + + + +FFIを扱うときに `panic!` に注意することは重要です。 +FFIの境界をまたぐ `panic!` の動作は未定義です。 +もしあなたがパニックし得るコードを書いているのであれば、他のスレッドで実行して、パニックがCに波及しないようにすべきです。 ```rust use std::thread; @@ -572,18 +712,22 @@ pub extern fn oh_no() -> i32 { # fn main() {} ``` -# Representing opaque structs + +# オペーク構造体の表現 -Sometimes, a C library wants to provide a pointer to something, but not let you -know the internal details of the thing it wants. The simplest way is to use a -`void *` argument: + + + +ときどき、Cのライブラリが何かのポインタを要求してくるにもかかわらず、その要求されているものの内部的な詳細を教えてくれないことがあります。 +最も単純な方法は `void *` 引数を使うことです。 ```c void foo(void *arg); void bar(void *arg); ``` -We can represent this in Rust with the `c_void` type: + +Rustではこれを `c_void` 型で表現することができます。 ```rust # #![feature(libc)] @@ -596,19 +740,26 @@ extern "C" { # fn main() {} ``` -This is a perfectly valid way of handling the situation. However, we can do a bit -better. To solve this, some C libraries will instead create a `struct`, where -the details and memory layout of the struct are private. This gives some amount -of type safety. These structures are called ‘opaque’. Here’s an example, in C: + + + + +これはその状況に対処するための完全に正当な方法です。 +しかし、もっとよい方法があります。 +これを解決するために、いくつかのCライブラリでは、代わりに `struct` を作っています。そこでは構造体の詳細とメモリレイアウトはプライベートです。 +これは型の安全性をいくらか満たします。 +それらの構造体は「オペーク」と呼ばれます。 +これがCによる例です。 ```c -struct Foo; /* Foo is a structure, but its contents are not part of the public interface */ +struct Foo; /* Fooは構造体だが、その内容は公開インターフェイスの一部ではない */ struct Bar; void foo(struct Foo *arg); void bar(struct Bar *arg); ``` -To do this in Rust, let’s create our own opaque types with `enum`: + +これをRustで実現するために、`enum`で独自のオペーク型を作りましょう。 ```rust pub enum Foo {} @@ -621,7 +772,9 @@ extern "C" { # fn main() {} ``` -By using an `enum` with no variants, we create an opaque type that we can’t -instantiate, as it has no variants. But because our `Foo` and `Bar` types are -different, we’ll get type safety between the two of them, so we cannot -accidentally pass a pointer to `Foo` to `bar()`. + + + + +バリアントなしの `enum` を使って、バリアントがないためにインスタンス化できないオペーク型を作ります。 +しかし、 `Foo` 型と `Bar` 型は異なる型であり、2つものの間の型の安全性を満たすので、 `Foo` のポインタを間違って `bar()` に渡すことはなくなります。 diff --git a/1.6/ja/book/functions.md b/1.6/ja/book/functions.md index 59125259..7d0cc0b2 100644 --- a/1.6/ja/book/functions.md +++ b/1.6/ja/book/functions.md @@ -2,7 +2,7 @@ -Rustのプログラムには全て、少なくとも1つの関数、`main`関数があります。 +Rustのプログラムには全て、少なくとも1つの関数、 `main` 関数があります。 ```rust fn main() { @@ -14,8 +14,8 @@ fn main() { これは評価可能な関数定義の最も単純なものです。 -前に言ったように、`fn`は「これは関数です」ということを示します。この関数には引数がないので、名前と丸括弧が続きます。そして、その本文を表す波括弧が続きます。 -これが`foo`という名前の関数です。 +前に言ったように、 `fn` は「これは関数です」ということを示します。この関数には引数がないので、名前と丸括弧が続きます。そして、その本文を表す波括弧が続きます。 +これが `foo` という名前の関数です。 ```rust fn foo() { @@ -33,7 +33,7 @@ fn print_number(x: i32) { ``` -これが`print_number`を使う完全なプログラムです。 +これが `print_number` を使う完全なプログラムです。 ```rust fn main() { @@ -47,7 +47,7 @@ fn print_number(x: i32) { -見てのとおり、関数の引数は`let`宣言と非常によく似た動きをします。 +見てのとおり、関数の引数は `let` 宣言と非常によく似た動きをします。 引数の名前にコロンに続けて型を追加します。 @@ -69,7 +69,7 @@ fn print_sum(x: i32, y: i32) { -`let`と異なり、あなたは関数の引数の型を宣言 _しなければなりません_ 。 +`let` と異なり、あなたは関数の引数の型を宣言 _しなければなりません_ 。 これは動きません。 ```rust,ignore @@ -109,7 +109,7 @@ fn add_one(x: i32) -> i32 { -Rustの関数はちょうど1つだけの値を返します。そして、ダッシュ(`-`)の後ろに大なりの記号(`>`)を続けた「矢印」の後にその型を宣言します。 +Rustの関数はちょうど1つだけの値を返します。そして、ダッシュ( `-` )の後ろに大なりの記号( `>` )を続けた「矢印」の後にその型を宣言します。 関数の最後の行が何を返すのかを決定します。 ここにセミコロンがないことに気が付くでしょう。 もしそれを追加すると、こうなります。 @@ -155,7 +155,7 @@ Rustは主として式ベースの言語です。 ではその違いは何でしょうか。 式は値を返しますが、文は返しません。 -それが「not all control paths return a value」で終わった理由です。文`x + 1;`は値を返さないからです。 +それが「not all control paths return a value」で終わった理由です。文 `x + 1;` は値を返さないからです。 Rustには2種類の文があります。「宣言文」と「式文」です。 その他の全ては式です。 まずは宣言文について話しましょう。 @@ -171,16 +171,17 @@ x = y = 5 -しかし、Rustでは束縛を導入するための`let`の使用は式では _ありません_ 。 +しかし、Rustでは束縛を導入するための `let` の使用は式では _ありません_ 。 次の例はコンパイルエラーを起こします。 ```ignore -let x = (let y = 5); // expected identifier, found keyword `let` +# // let x = (let y = 5); // expected identifier, found keyword `let` +let x = (let y = 5); // 識別子を期待していましたが、キーワード `let` が見付かりました ``` -ここでコンパイラは次のことを教えています。式の先頭を検出することが期待されていたところ、`let`は式ではなく文の先頭にしかなれないということです。 +ここでコンパイラは次のことを教えています。式の先頭を検出することが期待されていたところ、 `let` は式ではなく文の先頭にしかなれないということです。 @@ -188,13 +189,14 @@ let x = (let y = 5); // expected identifier, found keyword `let` -次のことに注意しましょう。既に束縛されている変数(例えば、`y = 5`)への割当ては、その値が特に役に立つものではなかったとしてもやはり式です。割当てが割り当てられる値(例えば、前の例では`5`)を評価する他の言語とは異なり、Rustでは割当ての値は空のタプル`()`です。なぜなら、割り当てられる値には[単一の所有者](ownership.html)しかおらず、他のどんな値を返したとしても予想外の出来事になってしまうからです。 +次のことに注意しましょう。既に束縛されている変数(例えば、 `y = 5` )への割当ては、その値が特に役に立つものではなかったとしてもやはり式です。割当てが割り当てられる値(例えば、前の例では `5` )を評価する他の言語とは異なり、Rustでは割当ての値は空のタプル `()` です。なぜなら、割り当てられる値には [単一の所有者](ownership.html) しかおらず、他のどんな値を返したとしても予想外の出来事になってしまうからです。 ```rust let mut y = 5; -let x = (y = 6); // x has the value `()`, not `6` +# // let x = (y = 6); // x has the value `()`, not `6` +let x = (y = 6); // xは値 `()` を持っており、 `6` ではありません ``` @@ -224,7 +226,7 @@ fn add_one(x: i32) -> i32 { -この関数は`i32`を返そうとしていますが、セミコロンを付ければ、それは代わりに`()`を返します。 +この関数は `i32` を返そうとしていますが、セミコロンを付ければ、それは代わりに `()` を返します。 Rustはこの挙動がおそらく求めているものではないということを理解するので、前に見たエラーの中で、セミコロンを削除することを提案するのです。 @@ -232,20 +234,21 @@ Rustはこの挙動がおそらく求めているものではないというこ しかし、早期リターンについてはどうでしょうか。 -Rustはそのためのキーワード`return`を持っています。 +Rustはそのためのキーワード `return` を持っています。 ```rust fn foo(x: i32) -> i32 { return x; - // we never run this code! +# // we never run this code! + // このコードは走りません! x + 1 } ``` -`return`を関数の最後の行で使っても動きますが、それはよろしくないスタイルだと考えられています。 +`return` を関数の最後の行で使っても動きますが、それはよろしくないスタイルだと考えられています。 ```rust fn foo(x: i32) -> i32 { @@ -256,7 +259,7 @@ fn foo(x: i32) -> i32 { -あなたがこれまで式ベースの言語を使ったことがなければ、`return`のない前の定義の方がちょっと変に見えるかもしれません。しかし、それは時間とともに直観的に感じられるようになります。 +あなたがこれまで式ベースの言語を使ったことがなければ、 `return` のない前の定義の方がちょっと変に見えるかもしれません。しかし、それは時間とともに直観的に感じられるようになります。 ## ダイバージング関数 @@ -275,13 +278,13 @@ fn diverges() -> ! { -`panic!`は既に見てきた`println!`と同様にマクロです。 -`println!`とは違って、`panic!`は実行中の現在のスレッドを与えられたメッセージとともにクラッシュさせます。 -この関数はクラッシュを引き起こすので、決してリターンしません。そのため、それは「ダイバージ」と読む、「`!`」型を持つのです。 +`panic!` は既に見てきた `println!` と同様にマクロです。 +`println!` とは違って、 `panic!` は実行中の現在のスレッドを与えられたメッセージとともにクラッシュさせます。 +この関数はクラッシュを引き起こすので、決してリターンしません。そのため、それは「ダイバージ」と読む、「 `!` 」型を持つのです。 -もし`diverges()`を呼び出すメイン関数を追加してそれを実行するならば、次のようなものが出力されるでしょう。 +もし `diverges()` を呼び出すメイン関数を追加してそれを実行するならば、次のようなものが出力されるでしょう。 ```text thread ‘
’ panicked at ‘This function never returns!’, hello.rs:2 @@ -289,7 +292,7 @@ thread ‘
’ panicked at ‘This function never returns!’, hello.rs:2 -もしもっと情報を得たいと思うのであれば、`RUST_BACKTRACE`環境変数をセットすることでバックトレースを得ることができます。 +もしもっと情報を得たいと思うのであれば、 `RUST_BACKTRACE` 環境変数をセットすることでバックトレースを得ることができます。 ```text $ RUST_BACKTRACE=1 ./diverges @@ -311,7 +314,7 @@ stack backtrace: ``` -`RUST_BACKTRACE`はCargoの`run`コマンドでも使うことができます。 +`RUST_BACKTRACE` はCargoの `run` コマンドでも使うことができます。 ```text $ RUST_BACKTRACE=1 cargo run @@ -356,7 +359,7 @@ let f: fn(i32) -> i32; -`f`は`i32`を引数として受け取り、`i32`を返す関数を指示する変数束縛です。 +`f` は `i32` を引数として受け取り、 `i32` を返す関数を指示する変数束縛です。 例えばこうです。 ```rust @@ -372,7 +375,7 @@ let f = plus_one; ``` -そして、その関数を呼び出すために`f`を使うことができます。 +そして、その関数を呼び出すために `f` を使うことができます。 ```rust # fn plus_one(i: i32) -> i32 { i + 1 } diff --git a/1.6/ja/book/getting-started.md b/1.6/ja/book/getting-started.md index ab9fe6d3..528544d6 100644 --- a/1.6/ja/book/getting-started.md +++ b/1.6/ja/book/getting-started.md @@ -22,9 +22,9 @@ Rustを使い始める最初のステップはインストールです。 -コマンドを色々提示しますが、それらは全て`$`から始まります。`$`を入力する必要はありません。 -`$`はただコマンドの先頭を示しているだけです。 -これから、Web上でも「`$`で始まるものは一般ユーザで実行し`#`で始まるものは管理者権限で実行する」というルールに従ったチュートリアルや例をよく見ることになります。 +コマンドを色々提示しますが、それらは全て `$` から始まります。 `$` を入力する必要はありません。 +`$` はただコマンドの先頭を示しているだけです。 +これから、Web上でも「 `$` で始まるものは一般ユーザで実行し `#` で始まるものは管理者権限で実行する」というルールに従ったチュートリアルや例をよく見ることになります。 ## プラットフォームのサポート @@ -55,7 +55,7 @@ Rustのサポートレベルは3階級に分かれていて、それぞれ違う * 自動テストがそのプラットフォーム上で走るようセットアップされている -* `rust-lang/rust`レポジトリのmasterブランチへの変更はテストが通ってからされる +* `rust-lang/rust` レポジトリのmasterブランチへの変更はテストが通ってからされる * 公式のリリースがそのプラットフォーム向けに提供される * 使用方法及びビルド方法のドキュメントがある @@ -86,7 +86,7 @@ Rustのサポートレベルは3階級に分かれていて、それぞれ違う * 自動ビルドはセットアップされているがテストは走っていないかもしれない -* `rust-lang/rust`レポジトリのmasterブランチへの変更は **ビルドが** 通ってからされる。 +* `rust-lang/rust` レポジトリのmasterブランチへの変更は **ビルドが** 通ってからされる。 これは標準ライブラリしかコンパイル出来ないものもあれば完全なブートストラップまで出来るものもあることを意味するということに注意してください。 * 公式のリリースがそのプラットフォーム向けに提供される @@ -195,7 +195,7 @@ Continue? (y/N) > ``` -ここで「はい」の意味で`y`を押しましょう。そして以後のプロンプトに従って下さい。 +ここで「はい」の意味で `y` を押しましょう。そして以後のプロンプトに従って下さい。 ## Windowsでのインストール @@ -219,7 +219,7 @@ $ sudo /usr/local/lib/rustlib/uninstall.sh -Windowsのインストーラを使ったなら`.msi`をもう一度実行すればアンインストールのオプションが出てきます。 +Windowsのインストーラを使ったなら `.msi` をもう一度実行すればアンインストールのオプションが出てきます。 ## トラブルシューティング @@ -267,8 +267,8 @@ repair, or remove installation」ページの「Change」を選択し、「Add t インストーラはドキュメントのコピーもローカルにインストールしますので、オフラインで読めます。 -UNIXシステムでは`/usr/local/share/doc/rust`にあります。 -WindowsではRustをインストールした所の`share/doc`ディレクトリにあります。 +UNIXシステムでは `/usr/local/share/doc/rust` にあります。 +WindowsではRustをインストールした所の `share/doc` ディレクトリにあります。 @@ -328,7 +328,7 @@ $ cd hello_world -> 留意: WindowsでかつPowerShellを使っていないのなら `~`は上手く動かないかもしれません。 +> 留意: WindowsでかつPowerShellを使っていないのなら `~` は上手く動かないかもしれません。 > 使っているシェルのドキュメントをあたってみて下さい。 @@ -365,7 +365,7 @@ Hello, world! -Windowsでは`main`を`main.exe`と読み替えて下さい。使っているOSに関わらず、`Hello, world!`の文字列がターミナルに印字されるのを目にする筈です。 +Windowsでは `main` を `main.exe` と読み替えて下さい。使っているOSに関わらず、 `Hello, world!` の文字列がターミナルに印字されるのを目にする筈です。 目にしたなら、おめでとうございます!あなたは正式にRustのプログラムを記述しました。これであなたもRustプログラマです!ようこそ。 @@ -389,20 +389,20 @@ fn main() { -これらの行はRustの *関数* を定義します。`main`関数は特別です。全てのRustプログラムの開始点になります。 -最初の行は「引数を取らず、返り値も返さない関数`main`を宣言します」といっています。 -引数があれば、括弧(`(`と`)`)の中に入りますし、今回はこの関数から何も値を返さないので返り値の型を完全に省略出来ます。 +これらの行はRustの *関数* を定義します。 `main` 関数は特別です。全てのRustプログラムの開始点になります。 +最初の行は「引数を取らず、返り値も返さない関数 `main` を宣言します」といっています。 +引数があれば、括弧(`(` と `)`)の中に入りますし、今回はこの関数から何も値を返さないので返り値の型を完全に省略出来ます。 -さらに、関数の本体部が波括弧(`{`と`}`)で括られていることに留意して下さい。 +さらに、関数の本体部が波括弧(`{` と `}`)で括られていることに留意して下さい。 Rustは全ての関数の本体部に波括弧を要請します。 関数宣言と同じ行に1スペース空けて開き波括弧を置くのが良いスタイルとされます。 -`main()`関数の中では +`main()` 関数の中では ```rust println!("Hello, world!"); @@ -420,9 +420,9 @@ Rustは全ての関数の本体部に波括弧を要請します。 -2つ目の重要な部分は`println!()`の行です。これはRustのメタプログラミング機構、 *[マクロ][macro]* の呼び出しです。 -もし関数を呼び出しているのなら、`println()`のようになります(! がありません)。 -Rustのマクロについては後程詳細に議論しますが、今のところ`!`を見たら普通の関数ではなくマクロを呼び出していることを意味するということだけ知っておいて下さい。 +2つ目の重要な部分は `println!()` の行です。これはRustのメタプログラミング機構、 *[マクロ][macro]* の呼び出しです。 +もし関数を呼び出しているのなら、 `println()` のようになります(! がありません)。 +Rustのマクロについては後程詳細に議論しますが、今のところ `!` を見たら普通の関数ではなくマクロを呼び出していることを意味するということだけ知っておいて下さい。 [macro]: macros.html @@ -431,9 +431,9 @@ Rustのマクロについては後程詳細に議論しますが、今のとこ -次は 文字列の`"Hello, world"`です。 +次は 文字列の `"Hello, world"` です。 システムプログラミング言語では文字列は驚くほど複雑なトピックで、これは *[静的に確保された][statically allocated]* 文字列です。 -文字列をスクリーンに印字してくれる`println!`にこれを引数として渡します。簡単ですね! +文字列をスクリーンに印字してくれる `println!` にこれを引数として渡します。簡単ですね! [statically allocated]: the-stack-and-the-heap.html @@ -442,7 +442,7 @@ Rustのマクロについては後程詳細に議論しますが、今のとこ 件の行はセミコロン(`;`)で終わります。Rustは *[式指向言語][expression-oriented language]* で、ほとんどのものは文ではなく式になります。 -`;`は式が終わり、次の式が始まることを示します。Rustのコードのほとんどの行は`;`で終わります。 +`;` は式が終わり、次の式が始まることを示します。Rustのコードのほとんどの行は `;` で終わります。 [expression-oriented language]: glossary.html#式指向言語 @@ -459,7 +459,7 @@ Rustのマクロについては後程詳細に議論しますが、今のとこ Rustのプログラムを走らせる前に、コンパイルする必要があります。 -Rustのコンパイラはこのように`rustc`と入力してソースファイルの名前を渡してあげることで使えます。 +Rustのコンパイラはこのように `rustc` と入力してソースファイルの名前を渡してあげることで使えます。 ```bash $ rustc main.rs @@ -469,9 +469,9 @@ $ rustc main.rs -CまたはC++のバックグラウンドを持つならこれが`gcc`や`clang`に似ていことに気付くでしょう。 +CまたはC++のバックグラウンドを持つならこれが `gcc` や `clang` に似ていことに気付くでしょう。 コンパイルが成功したら、Rustは実行可能バイナリを吐いている筈です。 -LinuxかOSXなら以下のように`ls`コマンドで確認出来ます。 +LinuxかOSXなら以下のように `ls` コマンドで確認出来ます。 ```bash $ ls @@ -489,8 +489,8 @@ main.exe main.rs -2つのファイルがあるといっています。`.rs`拡張子を持ったソースコードと実行可能ファイル(Windowsでは`main.exe`、それ以外では`main`)。 -ここからあとは`main`または`main.exe`のファイルをこのように実行するだけです。 +2つのファイルがあるといっています。 `.rs` 拡張子を持ったソースコードと実行可能ファイル(Windowsでは `main.exe` 、それ以外では `main` )。 +ここからあとは `main` または `main.exe` のファイルをこのように実行するだけです。 ```bash @@ -499,7 +499,7 @@ $ ./main # あるいはWindowsならmain.exe -もし *main.rs* が「Hello, world!」プログラムなら、これで`Hello, world!`とターミナルに印字することでしょう。 +もし *main.rs* が「Hello, world!」プログラムなら、これで `Hello, world!` とターミナルに印字することでしょう。 @@ -511,7 +511,7 @@ $ ./main # あるいはWindowsならmain.exe もしRubyやPython、JavaScriptなどの動的な言語から来たのならコンパイルと実行が別の手順になっていることに馴れないでしょう。 Rustは、プログラムをコンパイルして、それを別の誰かに渡したら、Rustがなくても動く、 *事前コンパイル* 言語です。 -他方別の誰かに`.rb`や`.py`、`.js`を渡したら(それぞれ)Ruby、PythonあるいはJavaScriptの実装が必要になりますが、コンパイルにも実行にも1つのコマンドで事足ります。 +他方別の誰かに `.rb` や `.py` 、 `.js` を渡したら(それぞれ)Ruby、PythonあるいはJavaScriptの実装が必要になりますが、コンパイルにも実行にも1つのコマンドで事足ります。 全ては言語設計上のトレードオフです。 @@ -519,7 +519,7 @@ Rustは、プログラムをコンパイルして、それを別の誰かに渡 -単純なプログラムなら単に`rustc`でコンパイルすれば十分ですがプロジェクトが大きくなるにつれてプロジェクトの全てのオプションを管理したり他の人やプロジェクトと容易に共有出来るようにしたくなるでしょう。 +単純なプログラムなら単に `rustc` でコンパイルすれば十分ですがプロジェクトが大きくなるにつれてプロジェクトの全てのオプションを管理したり他の人やプロジェクトと容易に共有出来るようにしたくなるでしょう。 次は現実世界のRustプログラムを書く手助けになるCargoというツールを紹介します。 @@ -556,7 +556,7 @@ $ cargo --version -バージョン番号を確認出来たなら、良かった!「`コマンドが見つかりません`」などのエラーが出たなら +バージョン番号を確認出来たなら、良かった!「 `コマンドが見つかりません` 」などのエラーが出たなら Rustをインストールしたシステムのドキュメントを見て、Cargoが別になっているか判断しましょう。 @@ -572,7 +572,7 @@ Hello WorldプログラムをCargoに変換しましょう。 1. ソースファイルを正しいディレクトリに置く -2. 古い実行可能ファイル(Windowsなら`main.exe`、他では`main`)を消し、新しいものを作る +2. 古い実行可能ファイル(Windowsなら `main.exe` 、他では `main`)を消し、新しいものを作る 3. Cargoの設定ファイルを作る @@ -604,15 +604,15 @@ READMEやライセンス情報、他のコードに関係ないものはプロ -では、 *main.rs* を *src* ディレクトリにコピーして、`rustc`でコンパイルして作ったファイルを削除します。 -これまで通り、Windowsなら`main`を`main.exe`に読み替えて下さい。 +では、 *main.rs* を *src* ディレクトリにコピーして、 `rustc` でコンパイルして作ったファイルを削除します。 +これまで通り、Windowsなら `main` を `main.exe` に読み替えて下さい。 -今回の例では実行可能ファイルを作るので`main.rs`の名前を引き続き使います。 -もしライブラリを作りたいなら`lib.rs`という名前にすることになります。 +今回の例では実行可能ファイルを作るので `main.rs` の名前を引き続き使います。 +もしライブラリを作りたいなら `lib.rs` という名前にすることになります。 この規約はCargoでプロジェクトを正しくコンパイルするのに使われていますが、望むなら上書きすることも出来ます。 @@ -620,11 +620,11 @@ READMEやライセンス情報、他のコードに関係ないものはプロ -次に、 *hello_world* ディレクトリ下にファイルを作ります。それを`Cargo.toml`とします。 +次に、 *hello_world* ディレクトリ下にファイルを作ります。それを `Cargo.toml` とします。 -ちゃんと`Cargo.toml`の`C`が大文字になっていることを確認しましょう、そうしないとCargoが設定ファイルと認識出来なくなります。 +ちゃんと `Cargo.toml` の `C` が大文字になっていることを確認しましょう、そうしないとCargoが設定ファイルと認識出来なくなります。 @@ -649,7 +649,7 @@ authors = [ "あなたの名前 " ] -最初の行、`[package]`は下に続く記述がパッケージの設定であることを示します。 +最初の行、 `[package]` は下に続く記述がパッケージの設定であることを示します。 さらなる情報をこのファイルに追加する時には他のセクションを追加することになりますが、今のところパッケージの設定しかしていません。 @@ -677,12 +677,12 @@ Hello, world! ``` -ババーン!全てが上手くいったら、もう一度`Hello, world!`がターミナルに印字される筈です。 +ババーン!全てが上手くいったら、もう一度 `Hello, world!` がターミナルに印字される筈です。 -`cargo build`でプロジェクトをビルドして`./target/debug/hello_world`でそれを実行したのですが、実は次のように`cargo run`一発でそれらを実行出来ます。 +`cargo build` でプロジェクトをビルドして `./target/debug/hello_world` でそれを実行したのですが、実は次のように `cargo run` 一発でそれらを実行出来ます。 ```bash $ cargo run @@ -713,10 +713,10 @@ Cargoはプロジェクトのファイルのどれかが変更されていない -単純なプロジェクトではCargoを使っても単に`rustc`を使うのとさほど変わないでしょうが将来において役に立つでしょう。 +単純なプロジェクトではCargoを使っても単に `rustc` を使うのとさほど変わないでしょうが将来において役に立つでしょう。 特に、クレートを使い始めた時によく当て嵌ります。 複数のクレートで構成された複雑なプロジェクトではCargoにビルドを任せた方がとても簡単になります。 -Cargoを使えば`cargo build`を実行するだけで正しく動いてくれます。 +Cargoを使えば `cargo build` を実行するだけで正しく動いてくれます。 ## リリースビルド @@ -726,7 +726,7 @@ Cargoを使えば`cargo build`を実行するだけで正しく動いてくれ -最終的にプロジェクトのリリース準備が整ったら`cargo build --release`を使うことで最適化を掛けてプロジェクトをコンパイル出来ます。 +最終的にプロジェクトのリリース準備が整ったら `cargo build --release` を使うことで最適化を掛けてプロジェクトをコンパイル出来ます。 最適化を掛けることでRustのコードは速くなりますが、コンパイル時間は長くなります。 こういう訳で、開発向けとユーザへ配布する最終版プログラムを作る時向けの2つの違うプロファイルが存在するのです。 @@ -753,7 +753,7 @@ Cargoは *Cargo.lock* でアプリケーションの依存を追跡します。 -出来ました!ここまでついて来たならCargoで`hello_world`をビルドする所まで出来た筈です。 +出来ました!ここまでついて来たならCargoで `hello_world` をビルドする所まで出来た筈です。 @@ -777,7 +777,7 @@ $ cargo build Cargoで即座に開発を始められる骨組だけのプロジェクトを素早く作ることが出来ます。 -Cargoで新たなプロジェクトを始めるには、`cargo new`をコマンドラインに入力します。 +Cargoで新たなプロジェクトを始めるには、 `cargo new` をコマンドラインに入力します。 ```bash $ cargo new hello_world --bin @@ -786,18 +786,18 @@ $ cargo new hello_world --bin -ライブラリではなく実行可能アプリケーションを作りたいのでこのコマンドは`--bin`を渡しています。 -実行可能ファイルはよく *バイナリ* と呼ばれます(なのでUnixシステムでは`/usr/bin/`に入っています)。 +ライブラリではなく実行可能アプリケーションを作りたいのでこのコマンドは `--bin` を渡しています。 +実行可能ファイルはよく *バイナリ* と呼ばれます(なのでUnixシステムでは `/usr/bin/` に入っています)。 -Cargoは2つのファイルと1つのディレクトリ、`Cargo.toml`と *main.rs* の入った *src* ディレクトリを生成します。 +Cargoは2つのファイルと1つのディレクトリ、 `Cargo.toml` と *main.rs* の入った *src* ディレクトリを生成します。 上で作ったのと全く同じ、見たことのある構成ですね。 -これさえあれば始められます。まず、`Cargo.toml`を開きます。このようになっている筈です。 +これさえあれば始められます。まず、 `Cargo.toml` を開きます。このようになっている筈です。 ```toml [package] @@ -810,11 +810,11 @@ authors = ["あなたの名前 "] -Cargoは引数と`git`の設定を基に *Cargo.toml* に適当な値を埋めます。 -Cargoが`hello_world`ディレクトリを`git`レポジトリとして初期化していることにも気付くでしょう。 +Cargoは引数と `git` の設定を基に *Cargo.toml* に適当な値を埋めます。 +Cargoが `hello_world` ディレクトリを `git` レポジトリとして初期化していることにも気付くでしょう。 -`src/main.rs`の中身はこのようになっている筈です。 +`src/main.rs` の中身はこのようになっている筈です。 ```rust fn main() { diff --git a/1.6/ja/book/glossary.md b/1.6/ja/book/glossary.md index d71ca264..6093665a 100644 --- a/1.6/ja/book/glossary.md +++ b/1.6/ja/book/glossary.md @@ -63,7 +63,7 @@ A type without a statically known size or alignment. ([more info][link]) コンピュータプログラミングに於いて、式は値、定数、変数、演算子、1つの値へと評価される関数の組み合わせです。 -例えば、`2 + (3 * 4)`は値14を返す式です。式が副作用を持ちうることに意味はありません。 +例えば、 `2 + (3 * 4)` は値14を返す式です。式が副作用を持ちうることに意味はありません。 例えば、ある式に含まれる関数がただ値を返す以外にも何か作用をするかもしれません。 diff --git a/1.6/ja/book/guessing-game.md b/1.6/ja/book/guessing-game.md index 7c52e2ce..87ac1320 100644 --- a/1.6/ja/book/guessing-game.md +++ b/1.6/ja/book/guessing-game.md @@ -20,7 +20,7 @@ 新しいプロジェクトを作りましょう。プロジェクトのディレクトリへ行って下さい。 -`hello_world`の時にどのようなディレクトリ構成で、どのように`Cargo.toml`を作る必要があったか覚えてますか? +`hello_world` の時にどのようなディレクトリ構成で、どのように `Cargo.toml` を作る必要があったか覚えてますか? Cargoにはそれらのことをしてくれるコマンドがあるのでした。使いましょう。 ```bash @@ -31,10 +31,10 @@ $ cd guessing_game -`cargo new`にプロジェクトの名前と、そしてライブラリではなくバイナリを作るので`--bin`フラグを渡します。 +`cargo new` にプロジェクトの名前と、そしてライブラリではなくバイナリを作るので `--bin` フラグを渡します。 -生成された`Cargo.toml`を確認しましょう。 +生成された `Cargo.toml` を確認しましょう。 ```toml [package] @@ -50,7 +50,7 @@ Cargoはこれらの情報を環境から取得します。もし合ってなか -最後に、Cargoは「Hello, world!」を生成します。`src/main.rs`を確認しましょう。 +最後に、Cargoは「Hello, world!」を生成します。 `src/main.rs` を確認しましょう。 ```rust @@ -70,14 +70,14 @@ $ cargo build -素晴しい!もう一度`src/main.rs`を開きましょう。全てのコードをこの中に書いていきます。 +素晴しい!もう一度 `src/main.rs` を開きましょう。全てのコードをこの中に書いていきます。 -行動する前に、もう一つCargoのコマンドを紹介させて下さい。`run`です。 -`cargo run`は`cargo build`のようなものですが、生成された実行可能ファイルの実行までします。 +行動する前に、もう一つCargoのコマンドを紹介させて下さい。 `run` です。 +`cargo run` は `cargo build` のようなものですが、生成された実行可能ファイルの実行までします。 試してみましょう。 ```bash @@ -90,7 +90,7 @@ Hello, world! -すごい! `run`コマンドはプロジェクトを細かく回す必要があるときに手頃でしょう。 +すごい! `run` コマンドはプロジェクトを細かく回す必要があるときに手頃でしょう。 今回のゲームがまさにそのようなプロジェクトです。すぐに試してから次の行動に移るの繰り返しをする必要があります。 @@ -100,7 +100,7 @@ Hello, world! とりかかりましょう! 数当てゲームでまずしなければいけないことはプレイヤーに予想値を入力させることです。 -これを`src/main.rs`に書きましょう。 +これを `src/main.rs` に書きましょう。 ```rust,no_run @@ -145,10 +145,10 @@ use std::io; ユーザの入力を取得して結果を出力する必要があります。 -なので`io`標準ライブラリからライブラリが必要になります。 +なので `io` 標準ライブラリからライブラリが必要になります。 Rustが全てのプログラムにデフォルトで読み込むものは少しだけで、[「プレリュード」][prelude]といいます。 -プレリュードになければ、直接`use`しなければいけません。 -2つめの「プレリュード」、[`io`プレリュード][ioprelude]もあり、同様にそれをインポートすると`io`に関連した多数の有用なものがインポートされます。 +プレリュードになければ、直接 `use` しなければいけません。 +2つめの「プレリュード」、[`io` プレリュード][ioprelude]もあり、同様にそれをインポートすると `io` に関連した多数の有用なものがインポートされます。 [prelude]: ../std/prelude/index.html @@ -163,9 +163,9 @@ fn main() { -以前見たように`main()`関数がプログラムのエントリーポイントになります。 -`fn`構文で新たな関数を宣言し、`()`が引数がないことを示し、`{`が関数の本体部の始まりです。 -返り値の型は書いていないので`()`、空の[タプル][tuples]として扱われます。 +以前見たように `main()` 関数がプログラムのエントリーポイントになります。 +`fn` 構文で新たな関数を宣言し、 `()` が引数がないことを示し、 `{` が関数の本体部の始まりです。 +返り値の型は書いていないので `()` 、空の[タプル][tuples]として扱われます。 [tuples]: primitive-types.html#tuples @@ -178,7 +178,7 @@ fn main() { -前に`println!()`が[文字列][strings]をスクリーンに印字する[マクロ][macros]であることを学びました。 +前に `println!()` が[文字列][strings]をスクリーンに印字する[マクロ][macros]であることを学びました。 [macros]: macros.html [strings]: strings.html @@ -204,7 +204,7 @@ let foo = bar; -これは`foo`という名前の束縛を作り、それを値`bar`に束縛します。 +これは `foo` という名前の束縛を作り、それを値 `bar` に束縛します。 多くの言語ではこれは「変数」と呼ばれるものですが、Rustの変数束縛は少しばかり皮を被せてあります。 @@ -213,12 +213,14 @@ let foo = bar; 例えば、束縛はデフォルトで[イミュータブル][immutable] (不変)です。 -なので、この例ではイミュータブルではなくミュータブル(可変)な束縛にするために`mut`を使っているのです。 -`let`は代入の左辺に名前を取る訳ではなくて実際には[パターン][patterns]を受け取ります。 +なので、この例ではイミュータブルではなくミュータブル(可変)な束縛にするために `mut` を使っているのです。 +`let` は代入の左辺に名前を取る訳ではなくて実際には[パターン][patterns]を受け取ります。 後程パターンを使います。簡単なのでもう使えますね。 ```rust +# // let foo = 5; // immutable. let foo = 5; // イミュータブル +# // let mut bar = 5; // mutable let mut bar = 5; // ミュータブル ``` @@ -227,19 +229,19 @@ let mut bar = 5; // ミュータブル -ああ、そして`//`から行末までがコメントです。Rustは[コメント][comments]にある全てのものを無視します。 +ああ、そして `//` から行末までがコメントです。Rustは[コメント][comments]にある全てのものを無視します。 [comments]: comments.html -という訳で`let mut guess`がミュータブルな束縛`guess`を導入することを知りました。 -しかし`=`の反対側、`String::new()`が何であるかを見る必要があります。 +という訳で `let mut guess` がミュータブルな束縛 `guess` を導入することを知りました。 +しかし `=` の反対側、 `String::new()` が何であるかを見る必要があります。 -`String`は文字列型で、標準ライブラリで提供されています。 +`String` は文字列型で、標準ライブラリで提供されています。 [`String`][string]は伸長可能でUTF-8でエンコードされたテキスト片です。 [string]: ../std/string/struct.String.html @@ -248,15 +250,15 @@ let mut bar = 5; // ミュータブル -`::new()`構文は特定の型の「関連関数」なので`::`構文を使っています。 -つまり、これは`String`のインスタンスではなく`String`自体に関連付けられているということです。 +`::new()` 構文は特定の型の「関連関数」なので `::` 構文を使っています。 +つまり、これは `String` のインスタンスではなく `String` 自体に関連付けられているということです。 これを「スタティックメソッド」と呼ぶ言語もあります。 -この関数は新たな空の`String`を作るので`new()`の名付けられています。 -`new()`関数はある種の新たな値を作るのによく使われる名前なので様々な型でこの関数を見るでしょう。 +この関数は新たな空の `String` を作るので `new()` の名付けられています。 +`new()` 関数はある種の新たな値を作るのによく使われる名前なので様々な型でこの関数を見るでしょう。 @@ -279,8 +281,8 @@ io::stdin() -プログラムの最初の行でどのように`std::io`を`use`したかを覚えていますか? -それの関連関数を呼び出しているのです。`use std::io`していないなら`std::io::stdin()`と書くことになります。 +プログラムの最初の行でどのように `std::io` を `use` したかを覚えていますか? +それの関連関数を呼び出しているのです。 `use std::io` していないなら `std::io::stdin()` と書くことになります。 @@ -301,7 +303,7 @@ io::stdin() ここで、ハンドルに対して[`read_line()`][read_line]メソッドを呼んでいます。 [メソッド][method]は関連関数のようなものですが、型自体ではなくインスタンスに対してだけ使えます。 -`read_line()`に1つ引数を渡してもいます。`&mut guess`です。 +`read_line()` に1つ引数を渡してもいます。 `&mut guess` です。 [read_line]: ../std/io/struct.Stdin.html#method.read_line [method]: method-syntax.html @@ -315,20 +317,20 @@ io::stdin() -`guess`がどのように束縛されたか覚えてますか?ミュータブルであると言いました。 -しかしながら`read_line`は`String`を引数に取りません。`&mut String`を取るのです。 +`guess` がどのように束縛されたか覚えてますか?ミュータブルであると言いました。 +しかしながら `read_line` は `String` を引数に取りません。 `&mut String` を取るのです。 Rustには[参照][references]と呼ばれる機能があって、1つのデータに対して複数の参照を持つことが出来、コピーを減らすことが出来ます。 Rustの主要な売りの1つが参照をいかに安全に簡単に使えるかなので、参照は複雑な機能です。 しかしこのプログラムを作り終えるのに今すぐ詳細を知る必要はありません。 -今のところ、`let`と同じように参照はデフォルトでイミュータブルであるということだけ覚えておいて下さい。 -なので`&guess`ではなく`&mut guess`と書く必要があるのです。 +今のところ、 `let` と同じように参照はデフォルトでイミュータブルであるということだけ覚えておいて下さい。 +なので `&guess` ではなく `&mut guess` と書く必要があるのです。 -何故`read_line()`は文字列へのミュータブルな参照を取るのでしょうか? -`read_line()`はユーザが標準入力に打ったものを取得し、それを文字列に入れる役割を果たします。 +何故 `read_line()` は文字列へのミュータブルな参照を取るのでしょうか? +`read_line()` はユーザが標準入力に打ったものを取得し、それを文字列に入れる役割を果たします。 なのでその文字列を引数として受け取り、そして入力文字列を追加するために文字列はミュータブルである必要があるのです。 [references]: references-and-borrowing.html @@ -345,7 +347,7 @@ Rustの主要な売りの1つが参照をいかに安全に簡単に使えるか -メソッドを`.foo()`構文で呼び出す時、改行してスペースを入れても構いません。 +メソッドを `.foo()` 構文で呼び出す時、改行してスペースを入れても構いません。 そうすることで長い行を分割出来ます。 こうすることだって _出来ました_ @@ -361,10 +363,10 @@ Rustの主要な売りの1つが参照をいかに安全に簡単に使えるか ですがこれだと読み辛いです。ですので3つのメソッド呼び出しを3行に分割します。 -`read_line()`については話しましたが`expect`についてはどうでしょう? -さて、`read_line()`がユーザの入力を`&mut String`に入れることには言及しました。 +`read_line()` については話しましたが `expect` についてはどうでしょう? +さて、 `read_line()` がユーザの入力を `&mut String` に入れることには言及しました。 しかし値も返します。 -この場合、標準ライブラリにある汎用の[`Result`][result]であり、そしてそれをサブライブラリに特殊化したバージョンの`io::Result`になります。 +この場合、標準ライブラリにある汎用の[`Result`][result]であり、そしてそれをサブライブラリに特殊化したバージョンの `io::Result` になります。 [ioresult]: ../std/io/type.Result.html [result]: ../std/result/enum.Result.html @@ -375,10 +377,10 @@ Rustの主要な売りの1つが参照をいかに安全に簡単に使えるか -これらの`Result`型の目的は、エラーハンドリング情報をエンコードすることです。 -`Result`型の値には、他の型と同じように、メソッドが定義されています。 -今回は`io::Result`に[`expect()`メソッド][expect]が定義されていて、それが呼び出された値が成功でなければ与えたメッセージと共に[`panic!`][panic]します。 -このような`panic!`はメッセージを表示してプログラムをクラッシュさせます。 +これらの `Result` 型の目的は、エラーハンドリング情報をエンコードすることです。 +`Result` 型の値には、他の型と同じように、メソッドが定義されています。 +今回は `io::Result` に[`expect()`メソッド][expect]が定義されていて、それが呼び出された値が成功でなければ与えたメッセージと共に[`panic!`][panic]します。 +このような `panic!` はメッセージを表示してプログラムをクラッシュさせます。 [expect]: ../std/option/enum.Option.html#method.expect [panic]: error-handling.html @@ -403,7 +405,7 @@ src/main.rs:10 io::stdin().read_line(&mut guess); -Rustは値`Result`を使っていないことを警告します。警告は`io::Result`が持つ特別なアノテーションに由来します。 +Rustは値 `Result` を使っていないことを警告します。警告は `io::Result` が持つ特別なアノテーションに由来します。 Rustはエラーの可能性があるのに処理していないことを教えてくれるのです。 エラーを出さないためには実際にエラー処理を書くのが正しやり方です。 幸運にも、問題があった時にそのままクラッシュさせたいならこの小さな2つのメソッドをそのまま使えます。 @@ -421,8 +423,8 @@ Rustはエラーの可能性があるのに処理していないことを教え -これは入力を保持している文字列を印字します。`{}`はプレースホルダで、引数として`guess`を渡しています。 -複数の`{}`があれば、複数を引数を渡すことになります。 +これは入力を保持している文字列を印字します。 `{}` はプレースホルダで、引数として `guess` を渡しています。 +複数の `{}` があれば、複数を引数を渡すことになります。 ```rust let x = 5; @@ -435,7 +437,7 @@ println!("x and y: {} and {}", x, y); 簡単簡単。 -いずれにせよ、一巡り終えました。これまでのものを`cargo run`で実行出来ます。 +いずれにせよ、一巡り終えました。これまでのものを `cargo run` で実行出来ます。 ```bash $ cargo run @@ -461,17 +463,17 @@ You guessed: 6 次に、秘密の数を生成する必要があります。Rustの標準ライブラリには乱数の機能がまだありません。 -ですが、Rustチームは[`rand`クレート][randcrate]を提供します。 +ですが、Rustチームは[`rand` クレート][randcrate]を提供します。 「クレート」はRustのコードのパッケージです。今まで作ってきたのは実行可能な「バイナリクレート」です。 -`rand`は「ライブラリクレート」で、他のプログラムから使われることを意図したコードが入っています。 +`rand` は「ライブラリクレート」で、他のプログラムから使われることを意図したコードが入っています。 [randcrate]: https://crates.io/crates/rand -外部のクレートを使う時にこそCargoが光ります。`rand`を使う前に`Cargo.toml`を修正する必要があります。 -`Cargo.toml`を開いて、この数行を末尾に追記しましょう。 +外部のクレートを使う時にこそCargoが光ります。 `rand` を使う前に `Cargo.toml` を修正する必要があります。 +`Cargo.toml` を開いて、この数行を末尾に追記しましょう。 ```toml [dependencies] @@ -492,14 +494,14 @@ rand="0.3.0" -`Cargo.toml`の`[dependencies]`(訳注: 依存)セクションは`[package]`セクションに似ています。 +`Cargo.toml` の `[dependencies]` (訳注: 依存)セクションは `[package]` セクションに似ています。 後続の行は次のセクションが始まるまでそのセクションに属します。 Cargoはどの外部クレートのどのバージョンに依存するのかの情報を取得するのにdependenciesセクションを使います。 今回のケースではバージョン`0.3.0`を指定していますが、Cargoは指定されたバージョンと互換性のあるバージョンを理解します。 Cargoはバージョン記述の標準、[セマンティックバージョニング][semver]を理解します。 -上記のようなそのままのバージョンは`^0.3.0`の略記で、「0.3.0と互換性のあるもの」という意味です。 -正確に`0.3.0`だけを使いたいなら`rand="=0.3.0"`(等号が2つあることに注意して下さい)と書きます。 -そして最新版を使いたいなら`*`を使います。また、バージョンの範囲を使うことも出来ます。 +上記のようなそのままのバージョンは `^0.3.0` の略記で、「0.3.0と互換性のあるもの」という意味です。 +正確に `0.3.0` だけを使いたいなら `rand="=0.3.0"` (等号が2つあることに注意して下さい)と書きます。 +そして最新版を使いたいなら `*` を使います。また、バージョンの範囲を使うことも出来ます。 [Cargoのドキュメント][cargodoc]にさらなる詳細があります。 [semver]: http://semver.org @@ -536,12 +538,12 @@ Crates.ioはRustのエコシステムに居る人が他人が使うためにオ -レジストリをアップデートした後にCargoは`[dependencies]`を確認し、まだダウンロードしていないものをダウンロードします。 -今回のケースでは`rand`に依存するとだけ書いてますが`libc`も取得されています。これは`rand`が動作するのに`libc`に依存するためです。 +レジストリをアップデートした後にCargoは `[dependencies]` を確認し、まだダウンロードしていないものをダウンロードします。 +今回のケースでは `rand` に依存するとだけ書いてますが `libc` も取得されています。これは `rand` が動作するのに `libc` に依存するためです。 これらのダウンロードが終わったら、それらのコンパイル、そしてプロジェクトのコンパイルをします。 -もう一度`cargo build`を走らせると、異なった出力になります。 +もう一度 `cargo build` を走らせると、異なった出力になります。 ```bash $ cargo build @@ -552,7 +554,7 @@ $ cargo build そうです、何も出力がありません!Cargoはプロジェクトがビルドされていて、依存もビルドされていることを知っているのでそれらのことをする必要がないのです。 -何もすることがなければそのまま終了します。もし`src/main.rs`を少し変更して保存したら、次のような行を目にするはずです。 +何もすることがなければそのまま終了します。もし `src/main.rs` を少し変更して保存したら、次のような行を目にするはずです。 ```bash $ cargo build @@ -564,9 +566,9 @@ $ cargo build -Cargoには`rand`の`0.3.x`を使うと伝えたので、それが書かれた時点での最新版、`v0.3.8`を取得しました。 -ですが来週`v0.3.9`が出て、重要なバグフィクスがされたらどうなるのでしょう? -バグフィクスを取り込むのは重要ですが、`0.3.9`にコードが動かなくなるようなリグレッションがあったらどうしましょう? +Cargoには `rand` の `0.3.x` を使うと伝えたので、それが書かれた時点での最新版、 `v0.3.8` を取得しました。 +ですが来週 `v0.3.9` が出て、重要なバグフィクスがされたらどうなるのでしょう? +バグフィクスを取り込むのは重要ですが、 `0.3.9` にコードが動かなくなるようなリグレッションがあったらどうしましょう? @@ -577,11 +579,11 @@ Cargoには`rand`の`0.3.x`を使うと伝えたので、それが書かれた -この問題への回答はプロジェクトのディレクトリにある`Cargo.lock`です。 -プロジェクトを最初にビルドした時に、Cargoは基準を満たす全てのバージョンを探索し、`Cargo.lock`ファイルに書き出します。 -その後のビルドではCargoはまず`Cargo.lock`ファイルがあるか確認し、再度バージョンを探索することなく、そこで指定されたバージョンを使います。 +この問題への回答はプロジェクトのディレクトリにある `Cargo.lock` です。 +プロジェクトを最初にビルドした時に、Cargoは基準を満たす全てのバージョンを探索し、 `Cargo.lock` ファイルに書き出します。 +その後のビルドではCargoはまず `Cargo.lock` ファイルがあるか確認し、再度バージョンを探索することなく、そこで指定されたバージョンを使います。 これで自動的に再現性のあるビルドが手に入ります。 -言い換えると、明示的にアップグレードしない限り我々は`0.3.8`を使い続けますし、ロックファイルのおかげでコードを共有する人も`0.3.8`を使い続けます。 +言い換えると、明示的にアップグレードしない限り我々は `0.3.8` を使い続けますし、ロックファイルのおかげでコードを共有する人も `0.3.8` を使い続けます。 @@ -590,11 +592,11 @@ Cargoには`rand`の`0.3.x`を使うと伝えたので、それが書かれた -`v0.3.9`を使いたい時はどうすればいいのでしょうか? -Cargoには「ロックを無視して、指定したバージョンを満たす全ての最新版を探しなさい。もし出来たらそれをロックファイルに書きなさい」を意味する別のコマンド、`update`があります。 -しかし、デフォルトではCargoは`0.3.0`より大きく、`0.4.0`より小さいバージョンを探しにいきます。 -`0.4.x`より大きなバージョンを使いたいなら直接`Cargo.toml`を更新する必要があります。 -そうしたら、次に`cargo build`をする時に、Cargoはインデックスをアップデートして`rand`への制約を再度評価します。 +`v0.3.9` を使いたい時はどうすればいいのでしょうか? +Cargoには「ロックを無視して、指定したバージョンを満たす全ての最新版を探しなさい。もし出来たらそれをロックファイルに書きなさい」を意味する別のコマンド、 `update` があります。 +しかし、デフォルトではCargoは `0.3.0` より大きく、 `0.4.0` より小さいバージョンを探しにいきます。 +`0.4.x` より大きなバージョンを使いたいなら直接 `Cargo.toml` を更新する必要があります。 +そうしたら、次に `cargo build` をする時に、Cargoはインデックスをアップデートして `rand` への制約を再度評価します。 @@ -607,7 +609,7 @@ Cargoのお陰でライブラリの再利用は本当に簡単になりますし [doccratesio]: http://doc.crates.io/crates-io.html -`rand`を実際に _使う_ ところに進みましょう。次のステップはこれです。 +`rand` を実際に _使う_ ところに進みましょう。次のステップはこれです。 ```rust,ignore extern crate rand; @@ -645,17 +647,17 @@ fn main() { -まず最初に変更したのは最初の行です。`extern crate rand`となっています。 -`rand`を`[dependencies]`に宣言したので、`extern crate`でそれを使うことをRustに伝えれます。 -これはまた、`use rand;`とするのと同じこともしますので、`rand`にあるものは`rand::`と前置すれば使えるようになります。 +まず最初に変更したのは最初の行です。 `extern crate rand` となっています。 +`rand` を `[dependencies]` に宣言したので、 `extern crate` でそれを使うことをRustに伝えれます。 +これはまた、 `use rand;` とするのと同じこともしますので、 `rand` にあるものは `rand::` と前置すれば使えるようになります。 -次に、もう1行`use`を追加しました。`use rand::Rng`です。 -すぐに、とあるメソッドを使うのですが、それが動作するには`Rng`がスコープに入っている必要があるのです。 +次に、もう1行 `use` を追加しました。 `use rand::Rng` です。 +すぐに、とあるメソッドを使うのですが、それが動作するには `Rng` がスコープに入っている必要があるのです。 基本的な考え方はこうです: メソッドは「トレイト」と呼ばれるのもで定義されており、メソッドが動作するにはそのトレイトがスコープにある必要があるのです。 詳しくは[トレイト][traits]セクションを読んで下さい。 @@ -676,10 +678,10 @@ fn main() { -`rand::thread_rng()`を使って現在いる[スレッド][concurrency]にローカルな乱数生成器のコピーを取得しています。 -上で`use rand::Rnd`したので生成器は`gen_range()`メソッドを使えます。 +`rand::thread_rng()` を使って現在いる[スレッド][concurrency]にローカルな乱数生成器のコピーを取得しています。 +上で `use rand::Rnd` したので生成器は `gen_range()` メソッドを使えます。 このメソッドは2つの引数を取り、それらの間にある数を生成します。 -下限は含みますが、上限は含まないので1から100までの数を生成するには`1`と`101`を渡す必要があります。 +下限は含みますが、上限は含まないので1から100までの数を生成するには `1` と `101` を渡す必要があります。 [concurrency]: concurrency.html @@ -766,7 +768,7 @@ fn main() { -いくか新しいことがあります。まず、新たに`use`が増えました。`std::cmp::Ordering`をスコープに導入します。 +いくか新しいことがあります。まず、新たに `use` が増えました。 `std::cmp::Ordering` をスコープに導入します。 そして、末尾にそれを使うコードが5行増えてます。 @@ -783,10 +785,10 @@ match guess.cmp(&secret_number) { -`cmp()`は比較可能なものに対しならなんでも呼べて、引数に比較したい対象の参照を取ります。 -`cmp()`は先程`use`した`Ordering`を返します。 -[`match`][match]文を使って正確に`Ordering`のどれであるかを判断しています。 -`Ordering`は[`enum`][enum] (訳注: 列挙型)で、enumは「enumeration(訳注: 列挙)」の略です。 +`cmp()` は比較可能なものに対しならなんでも呼べて、引数に比較したい対象の参照を取ります。 +`cmp()` は先程 `use` した `Ordering` を返します。 +[`match`][match]文を使って正確に `Ordering` のどれであるかを判断しています。 +`Ordering` は[`enum`][enum] (訳注: 列挙型)で、enumは「enumeration(訳注: 列挙)」の略です。 このようなものです。 ```rust @@ -802,16 +804,16 @@ enum Foo { -この定義だと、`Foo`のに属するものは`Foo::Bar`あるいは`Foo::Baz`です。 -`::`を使って`enum`のバリアントの名前空間を指示します。 +この定義だと、 `Foo` のに属するものは `Foo::Bar` あるいは `Foo::Baz` です。 +`::` を使って `enum` のバリアントの名前空間を指示します。 -[`Ordering`][ordering]`enum`は3つのバリアントを持ちます。`Less`、`Equal`そして`Greater`です。 -`match`文ではある型の値を取って、それぞれの可能な値に対する「腕」を作れます。 -`Ordering`には3種類あるので、3つの腕を作っています。 +[`Ordering`][ordering] `enum` は3つのバリアントを持ちます。 `Less` 、 `Equal` そして `Greater` です。 +`match` 文ではある型の値を取って、それぞれの可能な値に対する「腕」を作れます。 +`Ordering` には3種類あるので、3つの腕を作っています。 ```rust,ignore match guess.cmp(&secret_number) { @@ -825,8 +827,8 @@ match guess.cmp(&secret_number) { -`Less`なら`Too small!`を、`Greater`なら`Too big!`を、`Equal`なら`You win!`を印字します。 -`match`はとても便利で、Rustでよく使われます。 +`Less` なら `Too small!` を、 `Greater` なら `Too big!` を、 `Equal` なら `You win!` を印字します。 +`match` はとても便利で、Rustでよく使われます。 これはコンパイルが通らないと言いました。試してみましょう。 @@ -859,12 +861,12 @@ Could not compile `guessing_game`. ふぅ!大きなエラーです。核心になっているのは「型の不一致」です。 Rustには強い静的な型システムがあります。しかし型推論も持っています。 -`let guess = String::new()`と書いた時、Rustは`guess`が文字列である筈だと推論出来るのでわざわざ型を書かなくてもよいのです。 -`secret_number`には、は1から100までの数字を持っている数値型、32bit数の`i32`、あるいは符号なし32bit数の`u32`、あるいは64bit不動小数点数`f64`あるいはそれ以外、様々な型がありえます。 -これまで、それは問題ではありませんでしたので、Rustは`i32`をデフォルトとしてました。 -しかしながらここで、`guess`と`secret_number`の比較の仕方が分かりません。 +`let guess = String::new()` と書いた時、Rustは `guess` が文字列である筈だと推論出来るのでわざわざ型を書かなくてもよいのです。 +`secret_number` には、は1から100までの数字を持っている数値型、32bit数の `i32` 、あるいは符号なし32bit数の `u32` 、あるいは64bit不動小数点数 `f64` あるいはそれ以外、様々な型がありえます。 +これまで、それは問題ではありませんでしたので、Rustは `i32` をデフォルトとしてました。 +しかしながらここで、 `guess` と `secret_number` の比較の仕方が分かりません。 これらは同じ型である必要があります。 -究極には入力として読み取った`String`を比較のために実数の型にしたいです。 +究極には入力として読み取った `String` を比較のために実数の型にしたいです。 それは3行追加すれば出来ます。 新しいプログラムです。 @@ -916,13 +918,13 @@ fn main() { -ちょっと待って下さい、既に`guess`を定義してありますよね? -してあります、が、Rustでは以前の`guess`の定義を新しいもので「隠す」ことが出来ます(訳注: このように隠すことをシャドーイングといいます)。 -まさにこのように、最初`String`であった`guess`を`u32`に変換したい、というような状況でよく使われます。 -シャドーイングのおかげで`guess_str`と`guess`のように別々の名前を考える必要はなくなり、`guess`の名前を再利用出来ます。 +ちょっと待って下さい、既に `guess` を定義してありますよね? +してあります、が、Rustでは以前の `guess` の定義を新しいもので「隠す」ことが出来ます(訳注: このように隠すことをシャドーイングといいます)。 +まさにこのように、最初 `String` であった `guess` を `u32` に変換したい、というような状況でよく使われます。 +シャドーイングのおかげで `guess_str` と `guess` のように別々の名前を考える必要はなくなり、 `guess` の名前を再利用出来ます。 -`guess`を先に書いたような値に束縛します。 +`guess` を先に書いたような値に束縛します。 ```rust,ignore guess.trim().parse() @@ -940,17 +942,17 @@ guess.trim().parse() -ここでは、`guess`は古い`guess`、入力を保持している`String`の`guess`です。 -`String`の`trim()`メソッドは文字列の最初と最後にある空白を取り除きます。 -`read_line()`を満たすには「リターン」キーを押す必要があるのでこれは重要です。 -つまり、`5`と入力してリターンを押したら、`guess`は`5\n`のようになっています。 -`\n`「は改行」、エンターキーを表しています。`trim()`で`5`だけを残してこれを取り除けます。 -[文字列の`parse()`メソッド][parse]は文字列を何かの数値へとパースします。 +ここでは、 `guess` は古い `guess` 、入力を保持している `String` の `guess` です。 +`String` の `trim()` メソッドは文字列の最初と最後にある空白を取り除きます。 +`read_line()` を満たすには「リターン」キーを押す必要があるのでこれは重要です。 +つまり、 `5` と入力してリターンを押したら、 `guess` は `5\n` のようになっています。 +`\n` 「は改行」、エンターキーを表しています。 `trim()` で `5` だけを残してこれを取り除けます。 +[文字列の `parse()` メソッド][parse]は文字列を何かの数値へとパースします。 様々な数値をパース出来るので、Rustに正確にどの型の数値が欲しいのかを伝える必要があります。 -なので、`let guess: u32`なのです。 -`guess`の後のコロン(`:`)は型注釈を付けようとしていることをRustに伝えます。 -`u32`は符号なし32bit整数です。 -Rustには[様々なビルトインの数値型][number]がありますが、今回は`u32`を選びました。 +なので、 `let guess: u32` なのです。 +`guess` の後のコロン(`:`)は型注釈を付けようとしていることをRustに伝えます。 +`u32` は符号なし32bit整数です。 +Rustには[様々なビルトインの数値型][number]がありますが、今回は `u32` を選びました。 小さな正整数にはちょうどいいデフォルトの選択肢です。 [parse]: ../std/primitive.str.html#method.parse @@ -960,9 +962,9 @@ Rustには[様々なビルトインの数値型][number]がありますが、今 -`read_line()`と同じように、`parse()`の呼び出しでもエラーが起き得ます。 -文字列に`A %`が含まれていたらどうなるでしょう?それは数値には変換出来ません。 -なので、`read_line()`と同じように`expect()`を使ってエラーがあったらクラッシュするようにします。 +`read_line()` と同じように、 `parse()` の呼び出しでもエラーが起き得ます。 +文字列に `A %` が含まれていたらどうなるでしょう?それは数値には変換出来ません。 +なので、 `read_line()` と同じように `expect()` を使ってエラーがあったらクラッシュするようにします。 プログラムを試してみましょう。 @@ -994,7 +996,7 @@ Too big! #ループ -`loop`キーワードで無限ループが出来ます。入れてみましょう。 +`loop` キーワードで無限ループが出来ます。入れてみましょう。 ```rust,ignore extern crate rand; @@ -1036,7 +1038,7 @@ fn main() { そして試してみましょう。でも待って下さい、無限ループを追加しませんでした? そうです。 -`parse()`に関する議論を覚えてますか?数字でない答えを入力すると`panic!`して終了するのでした。 +`parse()` に関する議論を覚えてますか?数字でない答えを入力すると `panic!` して終了するのでした。 やってみましょう。 ```bash @@ -1064,7 +1066,7 @@ thread '
' panicked at 'Please type a number!' -おっ!`quit`で確かに終了しました。他の数字でないものでも同じことです。 +おっ! `quit` で確かに終了しました。他の数字でないものでも同じことです。 でもこれは控え目に言っても最適とは言えません。 まず、ゲームに勝ったら本当に終了するようにしましょう。 @@ -1112,8 +1114,8 @@ fn main() { -`You win!`の後に`break`を加えることで、ゲームに勝った時にループを抜けます。 -ループを抜けることは同時に、それが`main()`の最後の要素なので、プログラムが終了することも意味します。 +`You win!` の後に `break` を加えることで、ゲームに勝った時にループを抜けます。 +ループを抜けることは同時に、それが `main()` の最後の要素なので、プログラムが終了することも意味します。 もう1つ調整をします。数値でない入力をした時に、終了したくはありません、無視したいです。 それはこのように出来ます。 @@ -1182,11 +1184,11 @@ let guess: u32 = match guess.trim().parse() { 「‘actually handle the returned value'. The returned value by `parse()`...」だったんだと思って訳しました --> これが「エラーならクラッシュ」から「実際に返値のエラーをハンドルする」への一般的な移行の仕方です。 -`parse()`の返す値は`Ordering`と同じような`enum`ですが、今回はそれぞれのバリアントにデータが関連付いています。 -`Ok`は成功で、`Err`は失敗です。それぞれには追加の情報もあります。パースに成功した整数、あるいはエラーの種類です。 -このケースでは、`Ok(num)`に対して`match`していて、それで`Ok`に内包された値を`num`という名前に設定しており、右側でそのまま返しています。 -`Err`の場合、エラーの種類は気にしにないので、名前ではなく`_`を使います。 -これはエラーを無視していて、`continue`で`loop`の次の繰り返しに進みます。 +`parse()` の返す値は `Ordering` と同じような `enum` ですが、今回はそれぞれのバリアントにデータが関連付いています。 +`Ok` は成功で、 `Err` は失敗です。それぞれには追加の情報もあります。パースに成功した整数、あるいはエラーの種類です。 +このケースでは、 `Ok(num)` に対して `match` していて、それで `Ok` に内包された値を `num` という名前に設定しており、右側でそのまま返しています。 +`Err` の場合、エラーの種類は気にしにないので、名前ではなく `_` を使います。 +これはエラーを無視していて、 `continue` で `loop` の次の繰り返しに進みます。 これで良いはずです。試しましょう! @@ -1271,5 +1273,5 @@ fn main() { この最初のプロジェクトで色々なものを見せました。 -`let`、`match`、メソッド、関連関数、外部クレートの使い方、などなど。 +`let` 、 `match` 、メソッド、関連関数、外部クレートの使い方、などなど。 次のプロジェクトではさらに色々見せます。 diff --git a/1.6/ja/book/inline-assembly.md b/1.6/ja/book/inline-assembly.md index 7659c4ff..2ac36231 100644 --- a/1.6/ja/book/inline-assembly.md +++ b/1.6/ja/book/inline-assembly.md @@ -1,29 +1,43 @@ -% Inline Assembly +% インラインアセンブリ + -For extremely low-level manipulations and performance reasons, one -might wish to control the CPU directly. Rust supports using inline -assembly to do this via the `asm!` macro. The syntax roughly matches -that of GCC & Clang: + + + + +極めて低レベルな技巧やパフォーマンス上の理由から、CPUを直接コントロールしたいと思う人もいるでしょう。 +Rustはそのような処理を行うためにインラインアセンブリを `asm!` マクロによってサポートしています。 +インラインアセンブリの構文はGCCやClangのものとおおまかに一致しています。 ```ignore -asm!(assembly template - : output operands - : input operands - : clobbers - : options +# // asm!(assembly template +asm!(アセンブリのテンプレート +# // : output operands + : 出力オペランド +# // : input operands + : 入力オペランド +# // : clobbers + : 破壊されるデータ +# // : options + : オプション ); ``` -Any use of `asm` is feature gated (requires `#![feature(asm)]` on the -crate to allow) and of course requires an `unsafe` block. + + +`asm` のいかなる利用もフィーチャーゲートの対象です(利用するには `#![feature(asm)]` がクレートに必要になります)、 +そしてもちろん `unsafe` ブロックも必要です。 -> **Note**: the examples here are given in x86/x86-64 assembly, but -> all platforms are supported. + + +> **メモ**: ここでの例はx86/x86-64のアセンブリで示されますが、すべてのプラットフォームがサポートされています。 -## Assembly template + +## アセンブリテンプレート -The `assembly template` is the only required parameter and must be a -literal string (i.e. `""`) + + +`アセンブリテンプレート` のみが要求されるパラメータであり、文字列リテラル (例: "") である必要があります。 ```rust #![feature(asm)] @@ -35,7 +49,8 @@ fn foo() { } } -// other platforms +# // other platforms +// その他のプラットフォーム #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] fn foo() { /* ... */ } @@ -46,10 +61,12 @@ fn main() { } ``` -(The `feature(asm)` and `#[cfg]`s are omitted from now on.) + +以後は、 `feature(asm)` と `#[cfg]` は省略して示します。 -Output operands, input operands, clobbers and options are all optional -but you must add the right number of `:` if you skip them: + + +出力オペランド、入力オペランド、破壊されるデータ、オプションはすべて省略可能ですが、省略する場合は `:` を正しい数書く必要が有ります。 ```rust # #![feature(asm)] @@ -63,7 +80,8 @@ asm!("xor %eax, %eax" # } } ``` -Whitespace also doesn't matter: + +空白も必要ではありません: ```rust # #![feature(asm)] @@ -73,11 +91,14 @@ asm!("xor %eax, %eax" ::: "{eax}"); # } } ``` -## Operands + +## オペランド -Input and output operands follow the same format: `: -"constraints1"(expr1), "constraints2"(expr2), ..."`. Output operand -expressions must be mutable lvalues, or not yet assigned: + + + +入力と出力のオペランドは、 `: "制約1"(式1), "制約2"(式2), ...` というフォーマットに従います。 +出力オペランドの式は変更可能な左辺値か、アサインされていない状態でなければなりません。 ```rust # #![feature(asm)] @@ -100,11 +121,13 @@ fn main() { } ``` -If you would like to use real operands in this position, however, -you are required to put curly braces `{}` around the register that -you want, and you are required to put the specific size of the -operand. This is useful for very low level programming, where -which register you use is important: + + + + + +もし本当のオペランドをここで利用したい場合、 波括弧 `{}` で利用したいレジスタの周りを囲む必要があり、また、オペランドの特有のサイズを置く必要があります。 +これは、どのレジスタを利用するかが重要になる低レベルなプログラミングで有用です。 ```rust # #![feature(asm)] @@ -116,44 +139,63 @@ result # } ``` -## Clobbers + +## 破壊されるデータ -Some instructions modify registers which might otherwise have held -different values so we use the clobbers list to indicate to the -compiler not to assume any values loaded into those registers will -stay valid. + + + + +幾つかのインストラクションは異なる値を持っている可能性のあるレジスタを変更する事があります、 +そのため、コンパイラがそれらのレジスタに格納された値が処理後にも有効であると思わないように、 +破壊されるデータのリストを利用します。 ```rust # #![feature(asm)] # #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] # fn main() { unsafe { -// Put the value 0x200 in eax -asm!("mov $$0x200, %eax" : /* no outputs */ : /* no inputs */ : "{eax}"); +# // Put the value 0x200 in eax +// eaxに0x200を格納します +# // asm!("mov $$0x200, %eax" : /* no outputs */ : /* no inputs */ : "{eax}"); +asm!("mov $$0x200, %eax" : /* 出力なし */ : /* 入力無し */ : "{eax}"); # } } ``` -Input and output registers need not be listed since that information -is already communicated by the given constraints. Otherwise, any other -registers used either implicitly or explicitly should be listed. - -If the assembly changes the condition code register `cc` should be -specified as one of the clobbers. Similarly, if the assembly modifies -memory, `memory` should also be specified. - -## Options - -The last section, `options` is specific to Rust. The format is comma -separated literal strings (i.e. `:"foo", "bar", "baz"`). It's used to -specify some extra info about the inline assembly: - -Current valid options are: - -1. *volatile* - specifying this is analogous to - `__asm__ __volatile__ (...)` in gcc/clang. -2. *alignstack* - certain instructions expect the stack to be - aligned a certain way (i.e. SSE) and specifying this indicates to - the compiler to insert its usual stack alignment code -3. *intel* - use intel syntax instead of the default AT&T. + + + +入力と出力のレジスタは変更される可能性があることが制約によってすでに伝わっているためにリストに載せる必要はありません。 +それ以外では、その他の暗黙的、明示的に利用されるレジスタをリストに載せる必要があります。 + + + + +もしアセンブリが条件コードを変更する場合レジスタ `cc` も破壊されるデータのリストに指定する必要があります。 +同様に、もしアセンブリがメモリを変更する場合 `memory` もリストに指定する必要があります。 + + +## オプション + + + + +最後のセクション、 `options` はRust特有のものです。 +`options` の形式は、コンマで区切られた文字列リテラルのリスト(例: `:"foo", "bar", "baz"`)です。 +これはインラインアセンブリについての追加の情報を指定するために利用されます: + + +現在有効なオプションは以下の通りです: + + + + + + + +1. *volatile* - このオプションを指定することは、gcc/clangで `__asm__ __volatile__ (...)` を指定することと類似しています。 +2. *alignstack* - いくつかのインストラクションはスタックが決まった方式(例: SSE)でアラインされていることを期待しています、 + このオプションを指定することはコンパイラに通常のスタックをアラインメントするコードの挿入を指示します。 +3. *intel* - デフォルトのAT&T構文の代わりにインテル構文を利用することを意味しています。 ```rust # #![feature(asm)] @@ -167,11 +209,14 @@ println!("eax is currently {}", result); # } ``` -## More Information + +## さらなる情報 -The current implementation of the `asm!` macro is a direct binding to [LLVM's -inline assembler expressions][llvm-docs], so be sure to check out [their -documentation as well][llvm-docs] for more information about clobbers, -constraints, etc. + + + + +現在の `asm!` マクロの実装は [LLVMのインラインアセンブリ表現][llvm-docs] への直接的なバインディングです、 +そのため破壊されるデータのリストや、制約、その他の情報について [LLVMのドキュメント][llvm-docs] を確認してください。 [llvm-docs]: http://llvm.org/docs/LangRef.html#inline-assembler-expressions diff --git a/1.6/ja/book/lifetimes.md b/1.6/ja/book/lifetimes.md index 82830119..0afbcf53 100644 --- a/1.6/ja/book/lifetimes.md +++ b/1.6/ja/book/lifetimes.md @@ -15,7 +15,7 @@ * キーとなる概念、 [所有権][ownership] * [借用][borrowing] 、そしてそれらに関連する機能、「参照」 -* 今読んでいる、 ライフタイム +* 今読んでいる、ライフタイム diff --git a/1.6/ja/book/loops.md b/1.6/ja/book/loops.md index 68bb49d2..fa641732 100644 --- a/1.6/ja/book/loops.md +++ b/1.6/ja/book/loops.md @@ -1,10 +1,15 @@ -% Loops +% ループ + -Rust currently provides three approaches to performing some kind of iterative activity. They are: `loop`, `while` and `for`. Each approach has its own set of uses. + +なんらかの繰り返しを伴う処理に対して、Rust言語は3種類のアプローチ: `loop`, `while`, `for` を提供します。 +各アプローチにはそれぞれの使い道があります。 ## loop -The infinite `loop` is the simplest form of loop available in Rust. Using the keyword `loop`, Rust provides a way to loop indefinitely until some terminating statement is reached. Rust's infinite `loop`s look like this: + +Rustで使えるループなかで最もシンプルな形式が、無限 `loop` です。Rustのキーワード `loop` によって、 +何らかの終了状態に到達するまでずっとループし続ける手段を提供します。Rustの無限 `loop` はこのように: ```rust,ignore loop { @@ -14,7 +19,8 @@ loop { ## while -Rust also has a `while` loop. It looks like this: + +Rustには `while` ループもあります。このように: ```rust let mut x = 5; // mut x: i32 @@ -31,32 +37,42 @@ while !done { } ``` -`while` loops are the correct choice when you’re not sure how many times -you need to loop. + + +何回ループする必要があるか明らかではない状況で、`while` ループは正しい選択肢です。 -If you need an infinite loop, you may be tempted to write this: + +無限ループの必要があるとき、次のように書きたくなるかもしれません: ```rust,ignore while true { ``` -However, `loop` is far better suited to handle this case: + +しかし、こういった場合には `loop` の方がずっと適しています。 ```rust,ignore loop { ``` -Rust’s control-flow analysis treats this construct differently than a `while -true`, since we know that it will always loop. In general, the more information -we can give to the compiler, the better it can do with safety and code -generation, so you should always prefer `loop` when you plan to loop -infinitely. + + + + + +Rustの制御フロー解析では、必ずループすると知っていることから、これを `while true` とは異なる構造として扱います。 +一般に、コンパイラへ与える情報量が多いほど、安全性が高くより良いコード生成につながるため、 +無限にループするつもりなら常に `loop` を使うべきです。 + ## for -The `for` loop is used to loop a particular number of times. Rust’s `for` loops -work a bit differently than in other systems languages, however. Rust’s `for` -loop doesn’t look like this “C-style” `for` loop: + + + + +特定の回数だけループするときには `for` ループを使います。しかし、Rustの `for` ループは他のシステムプログラミング言語のそれとは少し異なる働きをします。 +Rustの `for` ループは、次のような「Cスタイル」 `for` ループとは似ていません: ```c for (x = 0; x < 10; x++) { @@ -64,7 +80,8 @@ for (x = 0; x < 10; x++) { } ``` -Instead, it looks like this: + +代わりに、このように書きます: ```rust for x in 0..10 { @@ -72,7 +89,8 @@ for x in 0..10 { } ``` -In slightly more abstract terms, + +もう少し抽象的な用語を使うと、 ```ignore for var in expression { @@ -80,29 +98,41 @@ for var in expression { } ``` -The expression is an item that can be converted into an [iterator] using -[`IntoIterator`]. The iterator gives back a series of elements. Each element is -one iteration of the loop. That value is then bound to the name `var`, which is -valid for the loop body. Once the body is over, the next value is fetched from -the iterator, and we loop another time. When there are no more values, the `for` -loop is over. + + + + + + +式(expression)は[`IntoIterator`]を用いて[イテレータ][iterator]へと変換可能なアイテムです。 +イテレータは要素の連なりを返します。それぞれの要素がループの1回の反復になります。 +その値は名前 `var` に束縛されて、ループ本体にて有効になります。いったんループ本体を抜けると、 +次の値がイテレータから取り出され、次のループ処理を行います。それ以上の値が存在しない時は、 +`for` ループは終了します。 [iterator]: iterators.html [`IntoIterator`]: ../std/iter/trait.IntoIterator.html -In our example, `0..10` is an expression that takes a start and an end position, -and gives an iterator over those values. The upper bound is exclusive, though, -so our loop will print `0` through `9`, not `10`. + + + +例示では、`0..10` が開始位置と終了位置をとる式であり、同範囲の値を返すイテレータを与えます。 +上界はその値自身を含まないため、このループは `0` から `9` までを表示します。 `10` ではありません。 -Rust does not have the “C-style” `for` loop on purpose. Manually controlling -each element of the loop is complicated and error prone, even for experienced C -developers. + + + +Rustでは意図的に「Cスタイル」 `for` ループを持ちません。経験豊富なC開発者でさえ、 +ループの各要素を手動制御することは複雑であり、また間違いを犯しやすいのです。 -### Enumerate + +### 列挙 -When you need to keep track of how many times you already looped, you can use the `.enumerate()` function. + +ループ中で何回目の繰り返しかを知る必要があるなら、 `.enumerate()` 関数が使えます。 -#### On ranges: + +#### レンジを対象に: ```rust for (i,j) in (5..10).enumerate() { @@ -110,7 +140,8 @@ for (i,j) in (5..10).enumerate() { } ``` -Outputs: + +出力: ```text i = 0 and j = 5 @@ -120,9 +151,11 @@ i = 3 and j = 8 i = 4 and j = 9 ``` -Don't forget to add the parentheses around the range. + +レンジを括弧で囲うのを忘れないで下さい。 -#### On iterators: + +#### イテレータを対象に: ```rust # let lines = "hello\nworld".lines(); @@ -131,7 +164,8 @@ for (linenumber, line) in lines.enumerate() { } ``` -Outputs: + +出力: ```text 0: Content of line one @@ -140,9 +174,11 @@ Outputs: 3: Content of line four ``` -## Ending iteration early + +## 反復の早期終了 -Let’s take a look at that `while` loop we had earlier: + +さきほどの `while` ループを見てみましょう: ```rust let mut x = 5; @@ -159,11 +195,14 @@ while !done { } ``` -We had to keep a dedicated `mut` boolean variable binding, `done`, to know -when we should exit out of the loop. Rust has two keywords to help us with -modifying iteration: `break` and `continue`. + + + +ループをいつ終了すべきか知るため、ここでは専用の `mut` なboolean変数束縛 `done` を用いました。 +Rustには反復の変更を手伝う2つキーワード: `break` と `continue` があります。 -In this case, we can write the loop in a better way with `break`: + +この例では、 `break` を使ってループを記述した方が良いでしょう: ```rust let mut x = 5; @@ -177,10 +216,14 @@ loop { } ``` -We now loop forever with `loop` and use `break` to break out early. Issuing an explicit `return` statement will also serve to terminate the loop early. + +ここでは `loop` による永久ループと `break` による早期脱出を使っています。 +明示的な `return` 文の発行でもループの早期終了になります。 -`continue` is similar, but instead of ending the loop, goes to the next -iteration. This will only print the odd numbers: + + +`continue` も似ていますが、ループを終了させるのではなく、次の反復へと進めます。 +これは奇数だけを表示するでしょう: ```rust for x in 0..10 { @@ -190,21 +233,28 @@ for x in 0..10 { } ``` -## Loop labels - -You may also encounter situations where you have nested loops and need to -specify which one your `break` or `continue` statement is for. Like most -other languages, by default a `break` or `continue` will apply to innermost -loop. In a situation where you would like to a `break` or `continue` for one -of the outer loops, you can use labels to specify which loop the `break` or - `continue` statement applies to. This will only print when both `x` and `y` are - odd: + +## ループラベル + + + + + + + + +入れ子のループがあり、`break` や `continue` 文がどのループに対応するか指定する必要がある、 +そんな状況に出会うこともあるでしょう。大抵の他言語と同様に、 `break` や `continue` は最内ループに適用されるのがデフォルトです。 +外側のループに `break` や `continue` を使いたいという状況では、 `break` や `continue` 文の適用先を指定するラベルを使えます。 +これは `x` と `y` 両方が奇数のときだけ表示を行います: ```rust 'outer: for x in 0..10 { 'inner: for y in 0..10 { - if x % 2 == 0 { continue 'outer; } // continues the loop over x - if y % 2 == 0 { continue 'inner; } // continues the loop over y +# // if x % 2 == 0 { continue 'outer; } // continues the loop over x + if x % 2 == 0 { continue 'outer; } // x のループを継続 +# // if y % 2 == 0 { continue 'inner; } // continues the loop over y + if y % 2 == 0 { continue 'inner; } // y のループを継続 println!("x: {}, y: {}", x, y); } } diff --git a/1.6/ja/book/macros.md b/1.6/ja/book/macros.md index f7f27858..fe494982 100644 --- a/1.6/ja/book/macros.md +++ b/1.6/ja/book/macros.md @@ -1,37 +1,62 @@ -% Macros - -By now you’ve learned about many of the tools Rust provides for abstracting and -reusing code. These units of code reuse have a rich semantic structure. For -example, functions have a type signature, type parameters have trait bounds, -and overloaded functions must belong to a particular trait. - -This structure means that Rust’s core abstractions have powerful compile-time -correctness checking. But this comes at the price of reduced flexibility. If -you visually identify a pattern of repeated code, you may find it’s difficult -or cumbersome to express that pattern as a generic function, a trait, or -anything else within Rust’s semantics. - -Macros allow us to abstract at a syntactic level. A macro invocation is -shorthand for an "expanded" syntactic form. This expansion happens early in -compilation, before any static checking. As a result, macros can capture many -patterns of code reuse that Rust’s core abstractions cannot. - -The drawback is that macro-based code can be harder to understand, because -fewer of the built-in rules apply. Like an ordinary function, a well-behaved -macro can be used without understanding its implementation. However, it can be -difficult to design a well-behaved macro! Additionally, compiler errors in -macro code are harder to interpret, because they describe problems in the -expanded code, not the source-level form that developers use. - -These drawbacks make macros something of a "feature of last resort". That’s not -to say that macros are bad; they are part of Rust because sometimes they’re -needed for truly concise, well-abstracted code. Just keep this tradeoff in -mind. - -# Defining a macro - -You may have seen the `vec!` macro, used to initialize a [vector][vector] with -any number of elements. +% マクロ + + + + + + +Rustが提供している多くのコードの再利用や抽象化に利用できるツールを学びました。 +それらのコードの再利用のユニットは豊富な意味論的構造を持っています。 +例えば、関数は型シグネチャ、型パラメータはトレイト境界、オーバーロードされた関数はトレイトに所属していなければならない等です。 + + + + + + +このような構造はRustのコアの抽象化が強力なコンパイル時の正確性のチェックを持っているという事を意味しています。 +しかし、それは柔軟性の減少というコストを払っています。 +もし、視覚的に繰り返しているコードのパターンを発見した時に、 +それらをジェネリックな関数やトレイトや、他のRustのセマンティクスとして表現することが困難であると気がつくかもしれません。 + + + + + +マクロは構文レベルでの抽象化をすることを可能にします。 +マクロ呼出は「展開された」構文への短縮表現です。 +展開はコンパイルの初期段階、すべての静的なチェックが実行される前に行われます。 +その結果として、マクロはRustのコアの抽象化では不可能な多くのパターンのコードの再利用を可能としています。 + + + + + + + + +マクロベースのコードの欠点は、組み込みルールの少なさに由来するそのコードの理解のしづらさです。 +普通の関数と同じように、良いマクロはその実装について理解しなくても使うことができます。 +しかしながら、そのような良いマクロを設計するのは困難です! +加えて、マクロコード中のコンパイルエラーは開発者が書いたソールレベルではなく、 +展開した結果のコードの中の問題について書かれているために、とても理解しづらいです。 + + + + + + +これらの欠点はマクロを「最終手段となる機能」にしています。 +これは、マクロが良くないものだと言っているわけではありません、マクロはRustの一部です、 +なぜならばマクロを使うことで簡潔になったり、適切な抽象化が可能になる場面がしばしば存在するからです。 +ただ、このトレードオフを頭に入れておいて欲しいのです。 + + +# マクロを定義する + + + +`vec!` マクロを見たことがあるでしょう、 [ベクタ][vector] を任意の要素で初期化するために使われていました。 [vector]: vectors.html @@ -40,8 +65,10 @@ let x: Vec = vec![1, 2, 3]; # assert_eq!(x, [1, 2, 3]); ``` -This can’t be an ordinary function, because it takes any number of arguments. -But we can imagine it as syntactic shorthand for + + +`vec!` は通常の関数として定義することはできません、なぜなら `vec!` は任意の個数の引数を取るためです。 +しかし、 `vec!` を以下のコードの構文上の短縮形であると考えることができます: ```rust let x: Vec = { @@ -54,10 +81,12 @@ let x: Vec = { # assert_eq!(x, [1, 2, 3]); ``` -We can implement this shorthand, using a macro: [^actual] + +このような短縮形をマクロ: [^actual] を用いることで実装することができます -[^actual]: The actual definition of `vec!` in libcollections differs from the - one presented here, for reasons of efficiency and reusability. + + +[^actual]: `vec!` のlibcollectionsにおける実際の実装と、ここで示したコードは効率性や再利用性のために異なります。 ```rust macro_rules! vec { @@ -76,41 +105,57 @@ macro_rules! vec { # } ``` -Whoa, that’s a lot of new syntax! Let’s break it down. + +ワオ!たくさんの新しい構文が現れました!細かく見ていきましょう。 ```ignore macro_rules! vec { ... } ``` -This says we’re defining a macro named `vec`, much as `fn vec` would define a -function named `vec`. In prose, we informally write a macro’s name with an -exclamation point, e.g. `vec!`. The exclamation point is part of the invocation -syntax and serves to distinguish a macro from an ordinary function. + + + + +これは、新しいマクロ `vec` を定義していることを意味しています、`vec` という関数を定義するときに `fn vec` と書くのと同じです。 +非公式ですが、実際には、マクロ名をエクスクラメーションマーク(!) と共に記述します、例えば: `vec!` のように示します。 +エクスクラメーションマークはマクロ呼び出しの構文の一部で、マクロと通常の関数の区別をつけるためのものです。 -## Matching + +## マッチング -The macro is defined through a series of rules, which are pattern-matching -cases. Above, we had + + +マクロは、幾つかのパターンマッチのケースを利用したルールに従って定義されています、 +上のコード中では、以下の様なパターンが見られました: ```ignore ( $( $x:expr ),* ) => { ... }; ``` -This is like a `match` expression arm, but the matching happens on Rust syntax -trees, at compile time. The semicolon is optional on the last (here, only) -case. The "pattern" on the left-hand side of `=>` is known as a ‘matcher’. -These have [their own little grammar] within the language. + + + + +これは `match` 式の腕に似ていますが、Rustの構文木に対してコンパイル時にマッチします。 +セミコロンはケースの末尾でだけ使うことのでき、省略可能です。 +`=>` の左辺にある「パターン」は「マッチャー」として知られています。 +マッチャーは [小さなマッチャー独自の構文][their own little grammar] を持っています。 [their own little grammar]: ../reference.html#macros -The matcher `$x:expr` will match any Rust expression, binding that syntax tree -to the ‘metavariable’ `$x`. The identifier `expr` is a ‘fragment specifier’; -the full possibilities are enumerated later in this chapter. -Surrounding the matcher with `$(...),*` will match zero or more expressions, -separated by commas. + + + + + +マッチャー `$x:expr` は任意のRustの式にマッチし、マッチした構文木を「メタ変数」 `$x` に束縛します。 +識別子 `expr` は「フラグメント指定子」です。全てのフラグメント指定子の一覧はこの章で後ほど紹介します。 +マッチャーを `$(...),*` で囲むと0個以上のコンマで句切られた式にマッチします。 -Aside from the special matcher syntax, any Rust tokens that appear in a matcher -must match exactly. For example, + + +特別なマッチャー構文は別にして、マッチャー中に登場するその他の任意のトークンはそれ自身に正確にマッチする必要があります。 +例えば: ```rust macro_rules! foo { @@ -123,29 +168,36 @@ fn main() { } ``` -will print + +上のコードは以下の様な出力をします ```text mode Y: 3 ``` -With + +また、以下のようなコードでは ```rust,ignore foo!(z => 3); ``` -we get the compiler error + +以下の様なコンパイルエラーが発生します ```text error: no rules expected the token `z` ``` -## Expansion + +## 展開 -The right-hand side of a macro rule is ordinary Rust syntax, for the most part. -But we can splice in bits of syntax captured by the matcher. From the original -example: + + + +マクロルールの右辺は大部分が通常のRustの構文です。 +しかし、マッチャーによってキャプチャされた構文を繋げる事ができます。 +最初に示した `vec!` の例を見てみましょう: ```ignore $( @@ -153,17 +205,24 @@ $( )* ``` -Each matched expression `$x` will produce a single `push` statement in the -macro expansion. The repetition in the expansion proceeds in "lockstep" with -repetition in the matcher (more on this in a moment). - -Because `$x` was already declared as matching an expression, we don’t repeat -`:expr` on the right-hand side. Also, we don’t include a separating comma as -part of the repetition operator. Instead, we have a terminating semicolon -within the repeated block. - -Another detail: the `vec!` macro has *two* pairs of braces on the right-hand -side. They are often combined like so: + + + +`$x` にマッチしたそれぞれの式はマクロ展開中に `push` 文を生成します。 +マクロ展開中の繰り返しはマッチャー中の繰り返しと足並みを揃えて実行されます(これについてはもう少し説明します)。 + + + + + +`$x` が既に式にマッチすると宣言されているために、`=>` の右辺では `:expr` を繰り返しません。 +また、区切りのコンマは繰り返し演算子の一部には含めません。 +そのかわり、繰り返しブロックをセミコロンを用いて閉じます。 + + + +そのほかの詳細としては: `vec!` マクロは *2つ* の括弧のペアを右辺に含みます。 +それらの括弧はよく以下のように合せられます: ```ignore macro_rules! foo { @@ -173,30 +232,46 @@ macro_rules! foo { } ``` -The outer braces are part of the syntax of `macro_rules!`. In fact, you can use -`()` or `[]` instead. They simply delimit the right-hand side as a whole. - -The inner braces are part of the expanded syntax. Remember, the `vec!` macro is -used in an expression context. To write an expression with multiple statements, -including `let`-bindings, we use a block. If your macro expands to a single -expression, you don’t need this extra layer of braces. - -Note that we never *declared* that the macro produces an expression. In fact, -this is not determined until we use the macro as an expression. With care, you -can write a macro whose expansion works in several contexts. For example, -shorthand for a data type could be valid as either an expression or a pattern. - -## Repetition - -The repetition operator follows two principal rules: - -1. `$(...)*` walks through one "layer" of repetitions, for all of the `$name`s - it contains, in lockstep, and -2. each `$name` must be under at least as many `$(...)*`s as it was matched - against. If it is under more, it’ll be duplicated, as appropriate. - -This baroque macro illustrates the duplication of variables from outer -repetition levels. + + +外側の括弧は `macro_rules!` 構文の一部です。事実、`()` や `[]` をかわりに使うことができます。 +括弧は単純に右辺を区切るために利用されています。 + + + + + +内側の括弧は展開結果の一部です。 +`vec!` マクロは式を必要としているコンテキストで利用されていることを思いだしてください。 +複数の文や、 `let` 束縛を含む式を書きたいときにはブロックを利用します。 +もし、マクロが単一の式に展開されるときは、追加の括弧は必要ありません。 + + + + + +マクロが式を生成すると *宣言* した事はないという点に注意してください。 +事実、それはマクロを式として利用するまでは決定されません。 +注意深くすれば、複数のコンテキストで適切に展開されるマクロを書く事ができます。 +例えば、データ型の短縮形は、式としてもパターンとしても正しく動作します。 + + +## 繰り返し + + +繰り返し演算子は以下の2つの重要なルールに従います: + + + + + +1. `$(...)*` は繰り返しの一つの「レイヤー」上で動作し、 レイヤーが含んでいる `$name` について足並みを揃えて動作します。 +2. それぞれの `$name` はマッチしたときと同じ個数の `$(...)*` の内側になければなりません。 + もし更に多くの `$(...)*` の中に表われた際には適切に複製されます。 + + + +以下の複雑なマクロは一つ外の繰り返しのレベルから値を複製している例です: ```rust macro_rules! o_O { @@ -218,20 +293,30 @@ fn main() { } ``` -That’s most of the matcher syntax. These examples use `$(...)*`, which is a -"zero or more" match. Alternatively you can write `$(...)+` for a "one or -more" match. Both forms optionally include a separator, which can be any token -except `+` or `*`. - -This system is based on + + + + +上のコードはほとんどのマッチャーの構文を利用しています。 +この例では0個以上にマッチする `$(...)*` を利用しています、 +1つ以上にマッチさせたい場合は `$(...)+` を代りに利用する事ができます。 +また、どちらも補助的に区切りを指定する事ができます。区切りには、 `+` と `*` 以外の任意のトークンを指定することが可能です。 + + + + +このシステムは: "[Macro-by-Example](https://www.cs.indiana.edu/ftp/techreports/TR206.pdf)" -(PDF link). +(PDFリンク) に基づいています。 -# Hygiene + +# 健全性 -Some languages implement macros using simple text substitution, which leads to -various problems. For example, this C program prints `13` instead of the -expected `25`. + + + +いくつかの言語に組込まれているマクロは単純なテキストの置換を用いています、しかしこれは多くの問題を発生させます。 +例えば、以下のC言語のプログラムは期待している `25` の代りに `13` と出力します: ```text #define FIVE_TIMES(x) 5 * x @@ -242,10 +327,13 @@ int main() { } ``` -After expansion we have `5 * 2 + 3`, and multiplication has greater precedence -than addition. If you’ve used C macros a lot, you probably know the standard -idioms for avoiding this problem, as well as five or six others. In Rust, we -don’t have to worry about it. + + + + +展開した結果は `5 * 2 + 3` となり、乗算は加算よりも優先度が高くなります。 +もしC言語のマクロを頻繁に利用しているなら、この問題を避けるためのイディオムを5、6個は知っているでしょう。 +Rustではこのような問題を恐れる必要はありません。 ```rust macro_rules! five_times { @@ -257,11 +345,14 @@ fn main() { } ``` -The metavariable `$x` is parsed as a single expression node, and keeps its -place in the syntax tree even after substitution. + + +メタ変数 `$x` は一つの式の頂点としてパースされ、構文木上の位置は置換されたあとも保存されます。 -Another common problem in macro systems is ‘variable capture’. Here’s a C -macro, using [a GNU C extension] to emulate Rust’s expression blocks. + + +他のマクロシステムで良くみられる問題は、「変数のキャプチャ」です。 +以下のC言語のマクロは [GNU C拡張][a GNU C extension] をRustの式のブロックをエミュレートするために利用しています。 [a GNU C extension]: https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html @@ -274,14 +365,16 @@ macro, using [a GNU C extension] to emulate Rust’s expression blocks. }) ``` -Here’s a simple use case that goes terribly wrong: + +以下はこのマクロを利用したときにひどい事になる単純な利用例です: ```text const char *state = "reticulating splines"; LOG(state) ``` -This expands to + +このコードは以下のように展開されます ```text const char *state = "reticulating splines"; @@ -291,10 +384,13 @@ if (state > 0) { } ``` -The second variable named `state` shadows the first one. This is a problem -because the print statement should refer to both of them. + + +2番目の変数 `state` は1つめの `state` を隠してしまいます。 +この問題は、print文が両方の変数を参照する必要があるために起こります。 -The equivalent Rust macro has the desired behavior. + +Rustにおける同様のマクロは期待する通りの動作をします。 ```rust # fn get_log_state() -> i32 { 3 } @@ -313,16 +409,22 @@ fn main() { } ``` -This works because Rust has a [hygienic macro system]. Each macro expansion -happens in a distinct ‘syntax context’, and each variable is tagged with the -syntax context where it was introduced. It’s as though the variable `state` -inside `main` is painted a different "color" from the variable `state` inside -the macro, and therefore they don’t conflict. + + + + + +このマクロはRustが [健全なマクロシステム][hygienic macro system] を持っているためです。 +それぞれのマクロ展開は分離された「構文コンテキスト」で行なわれ、 +それぞれの変数はその変数が導入された構文コンテキストでタグ付けされます。 +これは、 `main` 中の `state` がマクロの中の `state` とは異なる「色」で塗られているためにコンフリクトしないという風に考える事ができます。 [hygienic macro system]: https://en.wikipedia.org/wiki/Hygienic_macro -This also restricts the ability of macros to introduce new bindings at the -invocation site. Code such as the following will not work: + + +この健全性のシステムはマクロが新しい束縛を呼出時に導入する事を制限します。 +以下のようなコードは動作しません: ```rust,ignore macro_rules! foo { @@ -335,8 +437,10 @@ fn main() { } ``` -Instead you need to pass the variable name into the invocation, so it’s tagged -with the right syntax context. + + +代りに変数名を呼出時に渡す必要があります、 +呼出時に渡す事で正しい構文コンテキストでタグ付けされます。 ```rust macro_rules! foo { @@ -349,8 +453,10 @@ fn main() { } ``` -This holds for `let` bindings and loop labels, but not for [items][items]. -So the following code does compile: + + +このルールは `let` 束縛やループについても同様ですが、 [アイテム][items] については適用されません。 +そのため、以下のコードはコンパイルが通ります: ```rust macro_rules! foo { @@ -365,12 +471,15 @@ fn main() { [items]: ../reference.html#items -# Recursive macros + +# 再帰的マクロ -A macro’s expansion can include more macro invocations, including invocations -of the very same macro being expanded. These recursive macros are useful for -processing tree-structured input, as illustrated by this (simplistic) HTML -shorthand: + + + + +マクロの展開は、展開中のマクロ自身も含めたその他のマクロ呼出しを含んでいることが可能です。 +そのような再帰的なマクロは、以下の(単純化した)HTMLの短縮形のような、木構造を持つ入力の処理に便利です: ```rust # #![allow(unused_must_use)] @@ -404,173 +513,263 @@ fn main() { } ``` -# Debugging macro code - -To see the results of expanding macros, run `rustc --pretty expanded`. The -output represents a whole crate, so you can also feed it back in to `rustc`, -which will sometimes produce better error messages than the original -compilation. Note that the `--pretty expanded` output may have a different -meaning if multiple variables of the same name (but different syntax contexts) -are in play in the same scope. In this case `--pretty expanded,hygiene` will -tell you about the syntax contexts. - -`rustc` provides two syntax extensions that help with macro debugging. For now, -they are unstable and require feature gates. - -* `log_syntax!(...)` will print its arguments to standard output, at compile - time, and "expand" to nothing. - -* `trace_macros!(true)` will enable a compiler message every time a macro is - expanded. Use `trace_macros!(false)` later in expansion to turn it off. - -# Syntactic requirements - -Even when Rust code contains un-expanded macros, it can be parsed as a full -[syntax tree][ast]. This property can be very useful for editors and other -tools that process code. It also has a few consequences for the design of -Rust’s macro system. + +# マクロをデバッグする + + + + + + + + +マクロの展開結果を見るには、 `rustc --pretty expanded` を実行して下さい。 +出力結果はクレートの全体を表しています、そのため出力結果を再び `rustc` に与えることができます、 +そのようにすると時々、直接コンパイルした場合よりもより良いエラーメッセージを得ることができます。 +しかし、 `--pretty expanded` は同じ名前の変数(構文コンテキストは異なる)が同じスコープに複数存在する場合、 +出力結果のコード自体は、元のコードと意味が変わってくる場合があります。 +そのようになってしまう場合、 `--pretty expanded,hygiene` のようにすることで、構文コンテキストについて知ることができます。 + + + +`rustc` はマクロのデバッグを補助する2つの構文拡張を提供しています。 +今のところは、それらの構文は不安定であり、フィーチャーゲートを必要としています。 + + + +* `log_syntax!(...)` は与えられた引数をコンパイル時に標準入力に出力し、展開結果は何も生じません。 + + + +* `trace_macros!(true)` はマクロが展開されるたびにコンパイラがメッセージを出力するように設定できます、 + `trace_macros!(false)` を展開の終わりごろに用いることで、メッセージの出力をオフにできます。 + + +# 構文的な要求 + + + + + +Rustのコードに展開されていないマクロが含まれていても、 [構文木][ast] としてパースすることができます。 +このような特性はテキストエディタや、その他のコードを処理するツールにとって非常に便利です。 +また、このような特性はRustのマクロシステムの設計にも影響を及ぼしています。 [ast]: glossary.html#abstract-syntax-tree -One consequence is that Rust must determine, when it parses a macro invocation, -whether the macro stands in for - -* zero or more items, -* zero or more methods, -* an expression, -* a statement, or -* a pattern. - -A macro invocation within a block could stand for some items, or for an -expression / statement. Rust uses a simple rule to resolve this ambiguity. A -macro invocation that stands for items must be either - -* delimited by curly braces, e.g. `foo! { ... }`, or -* terminated by a semicolon, e.g. `foo!(...);` - -Another consequence of pre-expansion parsing is that the macro invocation must -consist of valid Rust tokens. Furthermore, parentheses, brackets, and braces -must be balanced within a macro invocation. For example, `foo!([)` is -forbidden. This allows Rust to know where the macro invocation ends. - -More formally, the macro invocation body must be a sequence of ‘token trees’. -A token tree is defined recursively as either - -* a sequence of token trees surrounded by matching `()`, `[]`, or `{}`, or -* any other single token. - -Within a matcher, each metavariable has a ‘fragment specifier’, identifying -which syntactic form it matches. - -* `ident`: an identifier. Examples: `x`; `foo`. -* `path`: a qualified name. Example: `T::SpecialA`. -* `expr`: an expression. Examples: `2 + 2`; `if true { 1 } else { 2 }`; `f(42)`. -* `ty`: a type. Examples: `i32`; `Vec<(char, String)>`; `&T`. -* `pat`: a pattern. Examples: `Some(t)`; `(17, 'a')`; `_`. -* `stmt`: a single statement. Example: `let x = 3`. -* `block`: a brace-delimited sequence of statements. Example: - `{ log(error, "hi"); return 12; }`. -* `item`: an [item][item]. Examples: `fn foo() { }`; `struct Bar;`. -* `meta`: a "meta item", as found in attributes. Example: `cfg(target_os = "windows")`. -* `tt`: a single token tree. - -There are additional rules regarding the next token after a metavariable: - -* `expr` variables may only be followed by one of: `=> , ;` -* `ty` and `path` variables may only be followed by one of: `=> , : = > as` -* `pat` variables may only be followed by one of: `=> , = if in` -* Other variables may be followed by any token. - -These rules provide some flexibility for Rust’s syntax to evolve without -breaking existing macros. - -The macro system does not deal with parse ambiguity at all. For example, the -grammar `$($t:ty)* $e:expr` will always fail to parse, because the parser would -be forced to choose between parsing `$t` and parsing `$e`. Changing the -invocation syntax to put a distinctive token in front can solve the problem. In -this case, you can write `$(T $t:ty)* E $e:exp`. + + +一つの影響としては、マクロ呼出をパースした時、マクロが以下のどれを意味しているかを判定する必要があります: + + + + + + +* 0個以上のアイテム +* 0個以上のメソッド +* 式 +* 文 +* パターン + + + + +ブロック中でのマクロ呼出は、幾つかのアイテムや、一つの式 / 文 に対応します。 +Rustはこの曖昧性を判定するためにRustは単純なルールを利用します。 +アイテムに対応しているマクロ呼出は以下のどちらかでなければなりません + + + +* 波括弧で区切られている 例: `foo! { ... }` +* セミコロンで終了している 例: `foo!(...);` + + + + + +その他の展開前にパース可能である事による制約はマクロ呼出は正しいRustトークンで構成されている必要があるというものです。 +そのうえ、括弧や、角カッコ、波括弧はマクロ呼出し中でバランスしてなければなりません。 +例えば: `foo!([)` は禁止されています。 +これによってRustはマクロ呼出しがどこで終わっているかを知ることができます。 + + + +もっと厳密に言うと、マクロ呼出しの本体は「トークンの木」のシーケンスである必要があります。 +トークンの木は以下のいずれかの条件により再帰的に定義されています + + + +* マッチャー、 `()` 、 `[]` または `{}` で囲まれたトークンの木、あるいは、 +* その他の単一のトークン + + + +マッチャー内部ではそれぞれのメタ変数はマッチする構文を指定する「フラグメント指定子」を持っています。 + + + + + + + + + + + + +* `ident`: 識別子。 例: `x`; `foo` +* `path`: 修飾された名前。例: `T::SpecialA` +* `expr`: 式。 例: `2 + 2`; `if true { 1 } else { 2 }`; `f(42)` +* `ty`: 型。 例: `i32`; `Vec<(char, String)>`; `&T` +* `pat`: パターン。 例: `Some(t)`; `(17, 'a')`; `_` +* `stmt`: 単一の文。 例: `let x = 3` +* `block`: 波括弧で区切られた文のシーケンス。 例: `{ log(error, "hi"); return 12 }` +* `item`: [アイテム][item]。 例: `fn foo() { }`; `struct Bar;` +* `meta`: アトリビュートで見られるような「メタアイテム」。 例: `cfg(target_os = "windows")` +* `tt`: 単一のトークンの木 + + +またメタ変数の次のトークンについて以下のルールが存在します: + + + + + +* `expr` 変数は `=> , ;` のどれか一つのみが次に現れます +* `ty` と `path` 変数は `=> , : = > as` のどれか一つのみが次に現れます +* `pat` 変数は `=> , = if in` のどれか一つのみが次に現れます +* その他の変数は任意のトークンが次に現れます + + + +これらのルールは既存のマクロを破壊すること無くRustの構文を拡張するための自由度を与えます。 + + + + + + +マクロシステムはパースの曖昧さについてな何も対処しません。 +例えば、 `$($t:ty)* $e:expr` は常にパースが失敗します、 +なぜならパーサーは `$t` をパースするか、 `$e` をパースするかを選ぶことを強制されるためです。 +呼出構文を変更して識別可能なトークンを先頭につけることでこの問題は回避することができます。 +そのようにする場合、例えば `$(T $t:ty)* E $e:exp` のように書くことができます。 [item]: ../reference.html#items -# Scoping and macro import/export - -Macros are expanded at an early stage in compilation, before name resolution. -One downside is that scoping works differently for macros, compared to other -constructs in the language. - -Definition and expansion of macros both happen in a single depth-first, -lexical-order traversal of a crate’s source. So a macro defined at module scope -is visible to any subsequent code in the same module, which includes the body -of any subsequent child `mod` items. - -A macro defined within the body of a single `fn`, or anywhere else not at -module scope, is visible only within that item. - -If a module has the `macro_use` attribute, its macros are also visible in its -parent module after the child’s `mod` item. If the parent also has `macro_use` -then the macros will be visible in the grandparent after the parent’s `mod` -item, and so forth. - -The `macro_use` attribute can also appear on `extern crate`. In this context -it controls which macros are loaded from the external crate, e.g. + +# スコープとマクロのインポート/エクスポート + + + + +マクロはコンパイルの早い段階、名前解決が行われる前に展開されます。 +一つの悪い側面としては、言語中のその他の構造とは異なり、マクロではスコープが少し違って動作するということです。 + + + + + + +マクロの定義と展開はクレートの字面上の順序どおりに単一の深さ優先探索で行われます。 +そのため、モジュールスコープで定義されたマクロは、 +後続する子供の `mod` アイテムも含む、同じモジュール中のコードから見えます。 + + + +`fn` の本体の中やその他のモジュールのスコープでない箇所で定義されたマクロはそのアイテム中でしか見えません。 + + + + + +もし、モジュールが `macro_use` アトリビュートを持っていた場合、 +それらのマクロは子供の `mod` アイテムの後で、親モジュールからも見えます。 +もし親モジュールが同様に `macro_use` アトリビュートを持っていた場合、 親の親モジュールから親の `mod` アイテムが終わった後に見えます。 +その後についても同様です。 + + + +また、 `macro_use` アトリビュートは `extern create` の上でも利用することができます。 +そのようにした場合、 `macro_use` アトリビュートは外部のクレートからどのマクロをロードするのかを指定します。 +以下がその例です: ```rust,ignore #[macro_use(foo, bar)] extern crate baz; ``` -If the attribute is given simply as `#[macro_use]`, all macros are loaded. If -there is no `#[macro_use]` attribute then no macros are loaded. Only macros -defined with the `#[macro_export]` attribute may be loaded. + + + +もしアトリビュートが単純に `#[macro_use]` という形で指定されていた場合、全てのマクロがロードされます。 +もし、 `#[macro_use]` が指定されていなかった場合、 `#[macro_export]` アトリビュートとともに定義されているマクロ以外は、 +どのマクロもロードされません。 -To load a crate’s macros without linking it into the output, use `#[no_link]` -as well. + + +クレートのマクロを出力にリンクさせずにロードするには、 `#[no_link]` を利用して下さい。 -An example: + +一例としては: ```rust macro_rules! m1 { () => (()) } -// visible here: m1 +# // // visible here: m1 +// ここで見えるのは: m1 mod foo { - // visible here: m1 +# // // visible here: m1 + // ここで見えるのは: m1 #[macro_export] macro_rules! m2 { () => (()) } - // visible here: m1, m2 +# // // visible here: m1, m2 + // ここで見えるのは: m1、m2 } -// visible here: m1 +# // // visible here: m1 +// ここで見えるのは: m1 macro_rules! m3 { () => (()) } -// visible here: m1, m3 +# // // visible here: m1, m3 +// ここで見えるのは: m1、m3 #[macro_use] mod bar { - // visible here: m1, m3 +# // // visible here: m1, m3 + // ここで見えるのは: m1、m3 macro_rules! m4 { () => (()) } - // visible here: m1, m3, m4 +# // // visible here: m1, m3, m4 + // ここで見えるのは: m1、m3、m4 } -// visible here: m1, m3, m4 +# // // visible here: m1, m3, m4 +// ここで見えるのは: m1、m3、m4 # fn main() { } ``` -When this library is loaded with `#[macro_use] extern crate`, only `m2` will -be imported. + + +ライブラリが `#[macro_use]` と共に外部のクレートをロードした場合、 `m2` だけがインポートされます。 -The Rust Reference has a [listing of macro-related -attributes](../reference.html#macro-related-attributes). + + +Rustのリファレンスは [マクロに関連するアトリビュートの一覧](../reference.html#macro-related-attributes) を掲載しています。 -# The variable `$crate` + +# `$crate` 変数 -A further difficulty occurs when a macro is used in multiple crates. Say that -`mylib` defines + + +さらなる困難はマクロが複数のクレートで利用された時に発生します。 +`mylib` が以下のように定義されているとしましょう ```rust pub fn increment(x: u32) -> u32 { @@ -589,15 +788,23 @@ macro_rules! inc_b { # fn main() { } ``` -`inc_a` only works within `mylib`, while `inc_b` only works outside the -library. Furthermore, `inc_b` will break if the user imports `mylib` under -another name. - -Rust does not (yet) have a hygiene system for crate references, but it does -provide a simple workaround for this problem. Within a macro imported from a -crate named `foo`, the special macro variable `$crate` will expand to `::foo`. -By contrast, when a macro is defined and then used in the same crate, `$crate` -will expand to nothing. This means we can write + + + +`inc_a` は `mylib` の中でだけ動作します、かたや `inc_b` は `mylib` の外部でだけ動作します。 +さらにいえば、 `inc_b` はユーザーが `mylib` を異なる名前でインポートした際には動作しません。 + + + + + + +Rustは(まだ)健全なクレートの参照の仕組みを持っていません、 +しかし、この問題に対する簡単な対処方法を提供しています。 +`foo`というクレートからインポートされたマクロ中において、 +特別なマクロ変数 `$create` は `::foo` に展開されます。 +対照的に、マクロが同じクレートの中で定義され利用された場合、 +`$create` は何にも展開されません。これはつまり以下のように書けることを意味しています: ```rust #[macro_export] @@ -607,23 +814,33 @@ macro_rules! inc { # fn main() { } ``` -to define a single macro that works both inside and outside our library. The -function name will expand to either `::increment` or `::mylib::increment`. + + +これは、ライブラリの中でも外でも動作するマクロを定義しています。 +関数の名前は `::increment` または `::mylib::increment` に展開されます。 + + + + + +このシステムを簡潔で正しく保つために、 `#[macro_use] extern crate ...` はクレートのルートにしか登場せず、 +`mod` の中には現れません。これは `$crate` が単一の識別子を持つことを確実にします。 -To keep this system simple and correct, `#[macro_use] extern crate ...` may -only appear at the root of your crate, not inside `mod`. This ensures that -`$crate` is a single identifier. -# The deep end + +# 最難関部 -The introductory chapter mentioned recursive macros, but it did not give the -full story. Recursive macros are useful for another reason: Each recursive -invocation gives you another opportunity to pattern-match the macro’s -arguments. + + + + +入門のチャプターで再帰的なマクロについて言及しました、しかしそのチャプターでは詳細について話していませんでした。 +再帰的なマクロが便利な他の理由は、それぞれの再帰的な呼出はマクロに与えられた引数にたいしてパターンマッチを行える可能性を与えてくれることです。 -As an extreme example, it is possible, though hardly advisable, to implement -the [Bitwise Cyclic Tag](https://esolangs.org/wiki/Bitwise_Cyclic_Tag) automaton -within Rust’s macro system. + + + +極端な例としては、 望ましくはありませんが、 [Bitwise Cyclic Tag](https://esolangs.org/wiki/Bitwise_Cyclic_Tag) のオートマトンをRustのマクロで実装する事が可能です。 ```rust macro_rules! bct { @@ -643,23 +860,29 @@ macro_rules! bct { (1, $p:tt, $($ps:tt),* ; $($ds:tt),*) => (bct!($($ps),*, 1, $p ; $($ds),*)); - // halt on empty data string +# // // halt on empty data string + // 空のデータ文字列で停止します ( $($ps:tt),* ; ) => (()); } ``` -Exercise: use macros to reduce duplication in the above definition of the -`bct!` macro. + + +演習: マクロを使って上の `bct!` マクロの定義の重複している部分を減らしてみましょう。 -# Common macros + +# よく見られるマクロ -Here are some common macros you’ll see in Rust code. + +以下は、Rustコード中でよく見られるマクロたちです。 ## panic! -This macro causes the current thread to panic. You can give it a message -to panic with: + + +このマクロは現在のスレッドをパニック状態にします。 +パニック時のメッセージを指定することができます。 ```rust,no_run panic!("oh no!"); @@ -667,33 +890,44 @@ panic!("oh no!"); ## vec! -The `vec!` macro is used throughout the book, so you’ve probably seen it -already. It creates `Vec`s with ease: + + +`vec!` マクロはこの本のなかで使われてきましたので、 すでに見たことがあるでしょう。 +`vec!` マクロは `Vec` を簡単に作成できます: ```rust let v = vec![1, 2, 3, 4, 5]; ``` -It also lets you make vectors with repeating values. For example, a hundred -zeroes: + + +また、値の繰り返しのベクタを作成することも可能です。 +たとえば、以下は100個の0を含むベクタの例です: ```rust let v = vec![0; 100]; ``` -## assert! and assert_eq! + +## assert! と assert_eq! -These two macros are used in tests. `assert!` takes a boolean. `assert_eq!` -takes two values and checks them for equality. `true` passes, `false` `panic!`s. -Like this: + + + +この2つのマクロはテスト時に利用されています。 +`assert!` は真偽値を引数に取ります。 +`assert_eq!` は2つの等価性をチェックする値を引数に取ります。 +`true` ならばパスし、 `false` だった場合 `panic!` を起こします: ```rust,no_run -// A-ok! +# // // A-ok! +// Okです! assert!(true); assert_eq!(5, 3 + 2); -// nope :( +# // // nope :( +// 駄目だぁ :( assert!(5 < 3); assert_eq!(5, 3); @@ -701,9 +935,13 @@ assert_eq!(5, 3); ## try! -`try!` is used for error handling. It takes something that can return a -`Result`, and gives `T` if it’s a `Ok`, and `return`s with the -`Err(E)` if it’s that. Like this: + + + +`try!` はエラーハンドリングのために利用されています。 +`try!` は `Result` を返す何らかの物を引数に取り、もし `Result` が `Ok` だった場合 `T` を返し、 +そうでなく `Err(E)` だった場合はそれを `return` します。 +例えば以下のように利用します: ```rust,no_run use std::fs::File; @@ -715,7 +953,8 @@ fn foo() -> std::io::Result<()> { } ``` -This is cleaner than doing this: + +このコードは以下のコードよりも綺麗です: ```rust,no_run use std::fs::File; @@ -734,7 +973,8 @@ fn foo() -> std::io::Result<()> { ## unreachable! -This macro is used when you think some code should never execute: + +このマクロはあるコードが絶対に実行されるべきでないと考えている時に利用します。 ```rust if false { @@ -742,9 +982,11 @@ if false { } ``` -Sometimes, the compiler may make you have a different branch that you know -will never, ever run. In these cases, use this macro, so that if you end -up wrong, you’ll get a `panic!` about it. + + + +時々、コンパイラーによって絶対に呼び出されるはずがないと考えているブランチを作成することになる時があります。 +そういった時には、このマクロを利用しましょう、そうすることでもし何か誤ってしまった時に、 `panic!` で知ることができます。 ```rust let x: Option = None; @@ -757,17 +999,27 @@ match x { ## unimplemented! -The `unimplemented!` macro can be used when you’re trying to get your functions -to typecheck, and don’t want to worry about writing out the body of the -function. One example of this situation is implementing a trait with multiple -required methods, where you want to tackle one at a time. Define the others -as `unimplemented!` until you’re ready to write them. - -# Procedural macros - -If Rust’s macro system can’t do what you need, you may want to write a -[compiler plugin](compiler-plugins.html) instead. Compared to `macro_rules!` -macros, this is significantly more work, the interfaces are much less stable, -and bugs can be much harder to track down. In exchange you get the -flexibility of running arbitrary Rust code within the compiler. Syntax -extension plugins are sometimes called ‘procedural macros’ for this reason. + + + + + +`unimplemented!` マクロはもし関数の本体の実装はしていないが、型チェックだけは行いたいという時に利用します。 +このような状況の一つの例としては複数のメソッドを必要としているトレイトのメソッドの一つを実装しようと試みている時などです。 +残りのメソッドたちの実装に取り掛かれるようになるまで `unimplemented!` として定義しましょう。 + + +# 手続きマクロ + + + + + + + +もしRustのマクロシステムでは必要としていることができない場合、 +[コンパイラプラグイン](compiler-plugins.html) を代わりに書きたくなるでしょう。 +コンパイラプラグインは `macro_rules!` マクロとくらべて、更に多くの作業が必要になり、 +インタフェースはかなり不安定であり、バグはさらに追跡が困難になります。 +引き換えに、任意のコードをコンパイラ中で実行できるという自由度を得ることができます。 +構文拡張プラグインがしばしば「手続きマクロ」と呼ばれるのはこのためです。 diff --git a/1.6/ja/book/match.md b/1.6/ja/book/match.md index 113e2188..751a8094 100644 --- a/1.6/ja/book/match.md +++ b/1.6/ja/book/match.md @@ -1,9 +1,13 @@ -% Match +% マッチ + -Often, a simple [`if`][if]/`else` isn’t enough, because you have more than two -possible options. Also, conditions can get quite complex. Rust -has a keyword, `match`, that allows you to replace complicated `if`/`else` -groupings with something more powerful. Check it out: + + + + +しばしば、2つ以上の可能な処理が存在するためや、分岐条件が非常に複雑になるために単純な [`if`][if]/`else` では充分でない場合があります。 +Rustにはキーワード `match` が存在し、複雑な `if`/`else` のグループをさらに強力なもので置き換えられます。 +以下の例を見てみましょう: ```rust let x = 5; @@ -20,32 +24,49 @@ match x { [if]: if.html -`match` takes an expression and then branches based on its value. Each ‘arm’ of -the branch is of the form `val => expression`. When the value matches, that arm’s -expression will be evaluated. It’s called `match` because of the term ‘pattern -matching’, which `match` is an implementation of. There’s an [entire section on -patterns][patterns] that covers all the patterns that are possible here. + + + + + +`match` は一つの式とその式の値に基づく複数のブランチを引数に取ります。 +一つ一つの「腕」は `val => expression` という形式を取ります。 +値がマッチした時に、対応する腕の式が評価されます。 +このような式が `match` と呼ばれるのは「パターンマッチ」に由来します。 +可能なすべてのパターンについて説明した、[パターンの説明のために書かれたセクション][patterns] が存在します。 [patterns]: patterns.html -So what’s the big advantage? Well, there are a few. First of all, `match` -enforces ‘exhaustiveness checking’. Do you see that last arm, the one with the -underscore (`_`)? If we remove that arm, Rust will give us an error: + + + +`match` を使う利点は何でしょうか? いくつか有りますが、 +まず一つ目としては `match` をつかうことで、「網羅性検査」が実施されます。 +上のコードで、最後のアンダースコア( `_` )を用いている腕があるのがわかりますか? +もし、その腕を削除した場合、Rustは以下の様なエラーを発生させます: ```text error: non-exhaustive patterns: `_` not covered ``` -In other words, Rust is trying to tell us we forgot a value. Because `x` is an -integer, Rust knows that it can have a number of different values – for -example, `6`. Without the `_`, however, there is no arm that could match, and -so Rust refuses to compile the code. `_` acts like a ‘catch-all arm’. If none -of the other arms match, the arm with `_` will, and since we have this -catch-all arm, we now have an arm for every possible value of `x`, and so our -program will compile successfully. - -`match` is also an expression, which means we can use it on the right-hand -side of a `let` binding or directly where an expression is used: + + + + + + + +言い換えると、Rustは値を忘れていることを伝えようとしているのです。 +なぜなら `x` は整数であるため、Rustは `x` は多くの異なる値を取ることができることを知っています。 +例えば、 `6` などがそれにに当たります。 +もし `_` がなかった場合、 `6` にマッチする腕が存在しない事になります、そのためRustはコンパイルを通しません。 +`_` は「全てキャッチする腕」のように振る舞います。 +もし他の腕がどれもマッチしなかった場合、 `_` の腕が実行されることになります、 +この「全てキャッチする腕」が存在するため、 `x` が取り得るすべての値について対応する腕が存在することになり、コンパイルが成功します。 + + + +`match` は式でも有ります、これはつまり `let` 束縛の右側や式が使われているところで利用することができるということを意味しています。 ```rust let x = 5; @@ -60,12 +81,15 @@ let number = match x { }; ``` -Sometimes it’s a nice way of converting something from one type to another. + +`match` はしばしば、ある型からある型へ変換するための良い手段になりまうす。 -# Matching on enums + +# 列挙型に対するマッチ -Another important use of the `match` keyword is to process the possible -variants of an enum: + + +`match` の他の重要な利用方法としては列挙型のバリアントを処理することがあります: ```rust enum Message { @@ -89,12 +113,16 @@ fn process_message(msg: Message) { } ``` -Again, the Rust compiler checks exhaustiveness, so it demands that you -have a match arm for every variant of the enum. If you leave one off, it -will give you a compile-time error unless you use `_`. - -Unlike the previous uses of `match`, you can’t use the normal `if` -statement to do this. You can use the [`if let`][if-let] statement, -which can be seen as an abbreviated form of `match`. + + + +繰り返しになりますが、Rustコンパイラは網羅性のチェックを行い、列挙型のすべてのバリアントに対して、マッチする腕が存在することを要求します。 +もし、一つでもマッチする腕のないバリアントを残している場合、 `_` を用いなければコンパイルエラーが発生します。 + + + + +上で説明した値に対する `match` の利用とは異なり、列挙型のバリアントに基いた分岐に `if` を用いることはできません。 +列挙型のバリアントに基いた分岐に [`if let`][if-let] 文を用いることが可能です、 `if let` を `match` の短縮形と捉えることができます。 [if-let]: if-let.html diff --git a/1.6/ja/book/nightly-rust.md b/1.6/ja/book/nightly-rust.md index 0578fbf8..a2bce04c 100644 --- a/1.6/ja/book/nightly-rust.md +++ b/1.6/ja/book/nightly-rust.md @@ -1,20 +1,24 @@ % Nightly Rust + -Rust provides three distribution channels for Rust: nightly, beta, and stable. -Unstable features are only available on nightly Rust. For more details on this -process, see ‘[Stability as a deliverable][stability]’. + + + +Rustにはnightly、beta、stableという3種類の配布用チャネルがあります。不安定なフィーチャはnightlyのRustでのみ使えます。詳細は「 [配布物の安定性][stability] 」をご覧ください。 [stability]: http://blog.rust-lang.org/2014/10/30/Stability.html -To install nightly Rust, you can use `rustup.sh`: + +nightlyのRustをインストールするには `rustup.sh` を使って以下のようにします。 ```bash $ curl -s https://static.rust-lang.org/rustup.sh | sh -s -- --channel=nightly ``` -If you're concerned about the [potential insecurity][insecurity] of using `curl -| sh`, please keep reading and see our disclaimer below. And feel free to -use a two-step version of the installation and examine our installation script: + + + +もし `curl | sh` の使用による [潜在的な危険性][insecurity] が気になる場合は、この後の注意書きまで読み進めてください。また、以下のように2段階のインストール方法を用い、インストールスクリプトを精査しても構いません。 ```bash $ curl -f -L https://static.rust-lang.org/rustup.sh -O @@ -23,75 +27,91 @@ $ sh rustup.sh --channel=nightly [insecurity]: http://curlpipesh.tumblr.com -If you're on Windows, please download either the [32-bit installer][win32] or -the [64-bit installer][win64] and run it. + + +Windowsの場合は [32bit版インストーラ][win32] あるいは [64bit版インストーラ][win64] をダウンロードして実行してください。 [win32]: https://static.rust-lang.org/dist/rust-nightly-i686-pc-windows-gnu.msi [win64]: https://static.rust-lang.org/dist/rust-nightly-x86_64-pc-windows-gnu.msi -## Uninstalling + +## アンインストール -If you decide you don't want Rust anymore, we'll be a bit sad, but that's okay. -Not every programming language is great for everyone. Just run the uninstall -script: + + + +もしRustが不要だと判断した場合、残念ですが仕方がありません。万人に気に入られるプログラミング言語ばかりとは限らないのです。アンインストールするには以下を実行します。 ```bash $ sudo /usr/local/lib/rustlib/uninstall.sh ``` -If you used the Windows installer, just re-run the `.msi` and it will give you -an uninstall option. + + +Windows用のインストーラを使用した場合は、 `.msi` を再実行しアンインストールオプションを選択してください。 -Some people, and somewhat rightfully so, get very upset when we tell you to -`curl | sh`. Basically, when you do this, you are trusting that the good -people who maintain Rust aren't going to hack your computer and do bad things. -That's a good instinct! If you're one of those people, please check out the -documentation on [building Rust from Source][from-source], or [the official -binary downloads][install-page]. + + + + + + +`curl | sh` を行うように書いたことについて、(当然のことですが)戸惑った方がいるかもしれません。基本的に `curl | sh` を行うということは、Rustをメンテナンスしている善良な人々がコンピュータのハッキングなど何か悪いことをしたりしないと信用する、ということです。ですので戸惑った方はよい直感を持っているといえます。そのような方は [ソースコードからのRustビルド][from-source] あるいは [公式バイナリのダウンロード][install-page] を確認してください。 [from-source]: https://github.com/rust-lang/rust#building-from-source [install-page]: https://www.rust-lang.org/install.html -Oh, we should also mention the officially supported platforms: + +ここで公式にサポートするプラットフォームについても述べておきます。 -* Windows (7, 8, Server 2008 R2) -* Linux (2.6.18 or later, various distributions), x86 and x86-64 -* OSX 10.7 (Lion) or greater, x86 and x86-64 + + + +* Windows (7、8、Server 2008 R2) +* Linux (2.6.18以上の各ディストリビューション)、x86 及び x86-64 +* OSX 10.7 (Lion)以上、x86 及び x86-64 -We extensively test Rust on these platforms, and a few others, too, like -Android. But these are the ones most likely to work, as they have the most -testing. + + + +Rustではこれらのプラットフォームの他、Androidなどいくつかのプラットフォームについても幅広いテストが行われています。しかし、後者については(訳注:実環境での使用実績が少ないという意味で)テストし尽くされているとは言えず、ほとんどの場合動くだろう、という状態です。 -Finally, a comment about Windows. Rust considers Windows to be a first-class -platform upon release, but if we're honest, the Windows experience isn't as -integrated as the Linux/OS X experience is. We're working on it! If anything -does not work, it is a bug. Please let us know if that happens. Each and every -commit is tested against Windows just like any other platform. + + + + + +最後にWindowsについてです。RustはWindowsをリリースする上での1級プラットフォームだと考えています。しかし、正直なところ、Windowsでの使い勝手はLinux/OS Xのそれと同等というわけではありません。(そうなるように努力しています!) もしうまく動かないことがあれば、それはバグですのでお知らせください。全てのコミットは他のプラットフォームと同様にWindowsに対してもテストされています。 -If you've got Rust installed, you can open up a shell, and type this: + +Rustのインストールが終われば、シェルを開いて以下のように入力してください。 ```bash $ rustc --version ``` -You should see the version number, commit hash, commit date and build date: + +バージョン番号、コミットハッシュ、コミット日時、ビルド日時が表示されるはずです。 ```bash rustc 1.0.0-nightly (f11f3e7ba 2015-01-04) (built 2015-01-06) ``` -If you did, Rust has been installed successfully! Congrats! - -This installer also installs a copy of the documentation locally, so you can -read it offline. On UNIX systems, `/usr/local/share/doc/rust` is the location. -On Windows, it's in a `share/doc` directory, inside wherever you installed Rust -to. - -If not, there are a number of places where you can get help. The easiest is -[the #rust IRC channel on irc.mozilla.org][irc], which you can access through -[Mibbit][mibbit]. Click that link, and you'll be chatting with other Rustaceans -(a silly nickname we call ourselves), and we can help you out. Other great -resources include [the user’s forum][users], and [Stack Overflow][stackoverflow]. + +これでRustのインストールはうまくいきました!おめでとう! + + + + + +インストーラはドキュメントのローカルコピーもインストールするので、オフラインでも読むことが出来ます。UNIXシステムでは `/usr/local/share/doc/rust` に、WindowsではRustをインストールしたディレクトリの `share\doc` ディレクトリに配置されます。 + + + + + + +もし上手くいかないなら様々な場所で助けを得られます。最も簡単なのは [Mibbit][mibbit] からアクセス出来る [irc.mozilla.orgにある#rustチャネル][irc] です。リンクをクリックしたら他のRustacean達(我々のことをふざけてこう呼ぶのです)にチャットで助けを求めることができます。他には [ユーザフォーラム][users] や [Stack Overflow][stackoverflow] などがあります。 [irc]: irc://irc.mozilla.org/#rust [mibbit]: http://chat.mibbit.com/?server=irc.mozilla.org&channel=%23rust diff --git a/1.6/ja/book/operators-and-overloading.md b/1.6/ja/book/operators-and-overloading.md index e53664ee..46bd64ee 100644 --- a/1.6/ja/book/operators-and-overloading.md +++ b/1.6/ja/book/operators-and-overloading.md @@ -1,11 +1,15 @@ -% Operators and Overloading +% 演算子とオーバーロード + -Rust allows for a limited form of operator overloading. There are certain -operators that are able to be overloaded. To support a particular operator -between types, there’s a specific trait that you can implement, which then -overloads the operator. + + + + +Rustは制限された形式での演算子オーバーロードを提供しており、オーバーロード可能な演算子がいくつか存在します。 +型同士の間の演算子をサポートするためのトレイトが存在し、それらを実装することで演算子をオーバーロードすることができます。 -For example, the `+` operator can be overloaded with the `Add` trait: + +例えば、 `+` の演算子は `Add` トレイトを利用することでオーバーロードすることができます: ```rust use std::ops::Add; @@ -34,17 +38,23 @@ fn main() { } ``` -In `main`, we can use `+` on our two `Point`s, since we’ve implemented -`Add` for `Point`. + + +`main` 中で、2つの `Point` に対して `+` を使うことができます、 +これは `Point` に対して `Add` を実装したためです。 -There are a number of operators that can be overloaded this way, and all of -their associated traits live in the [`std::ops`][stdops] module. Check out its -documentation for the full list. + + + +同じ方法でオーバーロード可能な演算子が多数あります、 +それらに対応したトレイトは [`std::ops`][stdops] モジュール内に存在します。 +全てのオーバーロード可能な演算子と対応するトレイトについては [`std::ops`][stdops] のドキュメントを読んで確認して下さい。 [stdops]: ../std/ops/index.html -Implementing these traits follows a pattern. Let’s look at [`Add`][add] in more -detail: + + +それらのトレイトの実装はパターンに従います。 [`Add`][add] トレイトを詳しく見ていきましょう: ```rust # mod foo { @@ -58,9 +68,11 @@ pub trait Add { [add]: ../std/ops/trait.Add.html -There’s three types in total involved here: the type you `impl Add` for, `RHS`, -which defaults to `Self`, and `Output`. For an expression `let z = x + y`, `x` -is the `Self` type, `y` is the RHS, and `z` is the `Self::Output` type. + + + +関連する3つの型が存在します: `impl Add` を実装するもの、 デフォルトが `Self` の `RHS`、 そして `Output` 。 +例えば、式 `let z = x + y` においては `x` は `Self` 型 `y` は RHS、 `z` は `Self::Output` 型となります。 ```rust # struct Point; @@ -69,23 +81,28 @@ impl Add for Point { type Output = f64; fn add(self, rhs: i32) -> f64 { - // add an i32 to a Point and get an f64 +# // // add an i32 to a Point and get an f64 + // i32をPointに加算しf64を返す # 1.0 } } ``` -will let you do this: + +上のコードによって以下の様に書けるようになります: ```rust,ignore let p: Point = // ... let x: f64 = p + 2i32; ``` -# Using operator traits in generic structs + +# オペレータトレイトをジェネリック構造体で使う -Now that we know how operator traits are defined, we can define our `HasArea` -trait and `Square` struct from the [traits chapter][traits] more generically: + + +オペレータトレイトがどのように定義されているかについて学びましたので、 +[トレイトについての章][traits] の `HasArea` トレイトと `Square` 構造体をさらに一般的に定義することができます: [traits]: traits.html @@ -120,16 +137,22 @@ fn main() { } ``` -For `HasArea` and `Square`, we just declare a type parameter `T` and replace -`f64` with it. The `impl` needs more involved modifications: + + +`HasArea` と `Square` について、型パラメータ `T` を宣言し `f64` で置換しました。 +`impl` はさらに関連するモディフィケーションを必要とします: ```ignore impl HasArea for Square where T: Mul + Copy { ... } ``` -The `area` method requires that we can multiply the sides, so we declare that -type `T` must implement `std::ops::Mul`. Like `Add`, mentioned above, `Mul` -itself takes an `Output` parameter: since we know that numbers don't change -type when multiplied, we also set it to `T`. `T` must also support copying, so -Rust doesn't try to move `self.side` into the return value. + + + + + +`area` メソッドは辺を掛けることが可能なことを必要としています。 +そのため型 `T` が `std::ops::Mul` を実装していなければならないと宣言しています。 +上で説明した `Add` と同様に、`Mul` は `Output` パラメータを取ります: 数値を掛け算した時に型が変わらないことを知っていますので、 `Output` も `T` と設定します。 +また `T` は、Rustが `self.side` を返り値にムーブするのを試みないようにコピーをサポートしている必要があります。 diff --git a/1.6/ja/book/ownership.md b/1.6/ja/book/ownership.md index 4a415268..72619028 100644 --- a/1.6/ja/book/ownership.md +++ b/1.6/ja/book/ownership.md @@ -15,8 +15,8 @@ * 今読んでいる、所有権 -* [借用][borrowing]、そしてそれらに関連する機能、「参照」 -* 借用のもう一歩進んだ概念、[ライフタイム][lifetimes] +* [借用][borrowing] 、そしてそれらに関連する機能、「参照」 +* 借用のもう一歩進んだ概念、 [ライフタイム][lifetimes] @@ -67,7 +67,7 @@ Rustはそれらの目標をたくさんの「ゼロコスト抽象化」を通 -Rustでは[変数束縛][bindings]は所有物を持ちます。つまり、それらはそれらが束縛されているものの「所有権を持つ」ということです。 +Rustでは [変数束縛][bindings] は所有物を持ちます。つまり、それらはそれらが束縛されているものの「所有権を持つ」ということです。 これは束縛がスコープから外れるとき、Rustは束縛されているリソースを解放するだろうということを意味します。 例えばこうです。 @@ -82,9 +82,9 @@ fn foo() { -`v`がスコープに入るとき、新しい[`Vec`][vect]が作られます。 -この場合、ベクタも3つの要素のために[ヒープ][heap]に空間を割り当てます。 -`foo()`の最後で`v`がスコープから外れるとき、Rustはベクタに関連するもの全てを取り除くでしょう。それがヒープ割当てのメモリであってもです。 +`v` がスコープに入るとき、新しい [`Vec`][vect] が作られます。 +この場合、ベクタも3つの要素のために [ヒープ][heap] に空間を割り当てます。 +`foo()` の最後で `v` がスコープから外れるとき、Rustはベクタに関連するもの全てを取り除くでしょう。それがヒープ割当てのメモリであってもです。 これはスコープの最後で決定的に起こります。 [vect]: ../std/vec/struct.Vec.html @@ -107,7 +107,7 @@ let v2 = v; ``` -しかし、もし後で`v`を使おうとすると、エラーが出ます。 +しかし、もし後で `v` を使おうとすると、エラーが出ます。 ```rust,ignore let v = vec![1, 2, 3]; @@ -172,12 +172,12 @@ let v2 = v; -最初の行はベクタオブジェクト`v`とそれの含むデータのためのメモリを割り当てます。 -ベクタオブジェクトは[スタック][sh]に保存され、[ヒープ][sh]に保存された内容(`[1, 2, 3]`)へのポインタを含みます。 -`v`を`v2`にムーブするとき、それは`v2`のためにそのポインタのコピーを作ります。 +最初の行はベクタオブジェクト `v` とそれの含むデータのためのメモリを割り当てます。 +ベクタオブジェクトは [スタック][sh] に保存され、 [ヒープ][sh] に保存された内容( `[1, 2, 3]` )へのポインタを含みます。 +`v` を `v2` にムーブするとき、それは `v2` のためにそのポインタのコピーを作ります。 それは、ヒープ上のベクタの内容へのポインタが2つあることを意味します。 それはデータ競合を持ち込むことでRustの安全性保証に違反するでしょう。 -そのため、Rustはムーブを終えた後の`v`の使用を禁止するのです。 +そのため、Rustはムーブを終えた後の `v` の使用を禁止するのです。 [sh]: the-stack-and-the-heap.html @@ -188,7 +188,7 @@ let v2 = v; そのため、それは最初に思ったほど非効率ではないかもしれません。 -## `Copy`型 +## `Copy` 型 @@ -196,7 +196,7 @@ let v2 = v; 所有権が他の束縛に転送されるとき、元の束縛を使うことができないということを証明しました。 -しかし、この挙動を変更する[トレイト][traits]があります。それは`Copy`と呼ばれます。 +しかし、この挙動を変更する [トレイト][traits] があります。それは `Copy` と呼ばれます。 トレイトについてはまだ議論していませんが、とりあえずそれらを挙動を追加するある型への注釈として考えることができます。 例えばこうです。 @@ -212,17 +212,17 @@ println!("v is: {}", v); -この場合、`v`は`i32`で、それは`Copy`トレイトを実装します。 -これはちょうどムーブと同じように、`v`を`v2`に割り当てるとき、データのコピーが作られるということを意味します。 -しかし、ムーブと違って後でまだ`v`を使うことができます。 -これは`i32`がどこか別の場所へのポインタを持たず、コピーが完全コピーだからです。 +この場合、 `v` は `i32` で、それは `Copy` トレイトを実装します。 +これはちょうどムーブと同じように、 `v` を `v2` に割り当てるとき、データのコピーが作られるということを意味します。 +しかし、ムーブと違って後でまだ `v` を使うことができます。 +これは `i32` がどこか別の場所へのポインタを持たず、コピーが完全コピーだからです。 -全てのプリミティブ型は`Copy`トレイトを実装しているので、推測どおりそれらの所有権は「所有権ルール」に従ってはムーブしません。 -例として、次の2つのコードスニペットはコンパイルが通ります。なぜなら、`i32`型と`bool`型は`Copy`トレイトを実装するからです。 +全てのプリミティブ型は `Copy` トレイトを実装しているので、推測どおりそれらの所有権は「所有権ルール」に従ってはムーブしません。 +例として、次の2つのコードスニペットはコンパイルが通ります。なぜなら、 `i32` 型と `bool` 型は `Copy` トレイトを実装するからです。 ```rust fn main() { @@ -252,7 +252,7 @@ fn change_truth(x: bool) -> bool { -もし`Copy`トレイトを実装していない型を使っていたならば、ムーブした値を使おうとしたため、コンパイルエラーが出ていたでしょう。 +もし `Copy` トレイトを実装していない型を使っていたならば、ムーブした値を使おうとしたため、コンパイルエラーが出ていたでしょう。 ```text error: use of moved value: `a` @@ -262,7 +262,7 @@ println!("{}", a); -独自の`Copy`型を作る方法は[トレイト][traits]セクションで議論するでしょう。 +独自の `Copy` 型を作る方法は [トレイト][traits] セクションで議論するでしょう。 [traits]: traits.html diff --git a/1.6/ja/book/primitive-types.md b/1.6/ja/book/primitive-types.md index e0215015..aeb2272b 100644 --- a/1.6/ja/book/primitive-types.md +++ b/1.6/ja/book/primitive-types.md @@ -13,8 +13,8 @@ Rust言語は「プリミティブ」であると考えられるかなりの数 # ブーリアン型 -Rustには`bool`と名付けられた組込みのブーリアン型があります。 -それは`true`と`false`という2つの値を持ちます。 +Rustには `bool` と名付けられた組込みのブーリアン型があります。 +それは `true` と `false` という2つの値を持ちます。 ```rust let x = true; @@ -23,13 +23,13 @@ let y: bool = false; ``` -ブーリアンの一般的な使い方は、[`if`条件][if]の中で用いるものです。 +ブーリアンの一般的な使い方は、 [`if` 条件][if] の中で用いるものです。 [if]: if.html -`bool`のさらなるドキュメントは[標準ライブラリのドキュメントの中][bool]で見付けることができます。 +`bool` のさらなるドキュメントは [標準ライブラリのドキュメントの中][bool] で見付けることができます。 [bool]: ../std/primitive.bool.html @@ -38,8 +38,8 @@ let y: bool = false; -`char`型は1つのユニコードのスカラ値を表現します。 -`char`はシングルクオート(`'`)で作ることができます。 +`char` 型は1つのユニコードのスカラ値を表現します。 +`char` はシングルクオート( `'` )で作ることができます。 ```rust let x = 'x'; @@ -48,11 +48,11 @@ let two_hearts = '💕'; -`char`が1バイトである他の言語と異なり、これはRustの`char`が1バイトではなく4バイトであるということを意味します。 +`char` が1バイトである他の言語と異なり、これはRustの `char` が1バイトではなく4バイトであるということを意味します。 -`char`のさらなるドキュメントは[標準ライブラリのドキュメントの中][char]で見付けることができます。 +`char` のさらなるドキュメントは [標準ライブラリのドキュメントの中][char] で見付けることができます。 [char]: ../std/primitive.char.html @@ -67,16 +67,17 @@ Rustにはいくつかのカテゴリの中にたくさんの種類の数値型 それらの型はカテゴリとサイズという2つの部分から成ります。 -例えば、`u16`はサイズ16ビットで符号なしの型です。 +例えば、 `u16` はサイズ16ビットで符号なしの型です。 ビット数を大きくすれば、より大きな数値を扱うことができます。 もし数値リテラルがその型を推論させるものを何も持たないのであれば、以下のとおりデフォルトになります。 ```rust -let x = 42; // x has type i32 - -let y = 1.0; // y has type f64 +# // let x = 42; // x has type i32 +let x = 42; // xはi32型を持つ +# // let y = 1.0; // y has type f64 +let y = 1.0; // yはf64型を持つ ``` @@ -109,16 +110,16 @@ let y = 1.0; // y has type f64 整数型には符号ありと符号なしという2つの種類があります。 違いを理解するために、サイズ4ビットの数値を考えましょう。 -符号あり4ビット整数は`-8`から`+7`までの数値を保存することができます。 +符号あり4ビット整数は `-8` から `+7` までの数値を保存することができます。 符号ありの数値は「2の補数表現」を使います。 -符号なし4ビット整数は、マイナスを保存する必要がないため、`0`から`+15`までの値を保存することができます。 +符号なし4ビット整数は、マイナスを保存する必要がないため、 `0` から `+15` までの値を保存することができます。 -符号なし(訳注:unsigned)型はそれらのカテゴリに`u`を使い、符号あり型は`i`を使います。 -`i`は「整数(訳注:integer)」の頭文字です。 -そのため、`u8`は8ビット符号なし数値、`i8`は8ビット符号あり数値です。 +符号なし(訳注:unsigned)型はそれらのカテゴリに `u` を使い、符号あり型は `i` を使います。 +`i` は「整数(訳注:integer)」の頭文字です。 +そのため、 `u8` は8ビット符号なし数値、 `i8` は8ビット符号あり数値です。 ## 固定長型 @@ -127,8 +128,8 @@ let y = 1.0; // y has type f64 固定長型はそれらの表現の中に特定のビット数を持ちます。 -指定することのできるビット長は`8`、`16`、`32`、`64`です。 -そのため、`u32`は符号なし32ビット整数、`i64`は符号あり64ビット整数です。 +指定することのできるビット長は `8` 、 `16` 、 `32` 、 `64` です。 +そのため、 `u32` は符号なし32ビット整数、 `i64` は符号あり64ビット整数です。 ## 可変長型 @@ -138,14 +139,14 @@ let y = 1.0; // y has type f64 Rustはそのサイズが実行しているマシンのポインタのサイズに依存する型も提供します。 それらの型はカテゴリとして「size」を使い、符号ありと符号なしの種類があります。 -これが`isize`と`usize`という2つの型を作ります。 +これが `isize` と `usize` という2つの型を作ります。 ## 浮動小数点型 -Rustは`f32`と`f64`という2つの浮動小数点型を持ちます。 +Rustは `f32` と `f64` という2つの浮動小数点型を持ちます。 それらはIEEE-754単精度及び倍精度小数点数に対応します。 @@ -166,21 +167,21 @@ let mut m = [1, 2, 3]; // m: [i32; 3] -配列は`[T; N]`という型を持ちます。 -この`T`記法については[ジェネリクスのセクションの中][generics]で話します。 -`N`は配列の長さのためのコンパイル時の定数です。 +配列は `[T; N]` という型を持ちます。 +この `T` 記法については [ジェネリクスのセクションの中][generics] で話します。 +`N` は配列の長さのためのコンパイル時の定数です。 配列の各要素を同じ値で初期化するための省略表現があります。 -この例では、`a`の各要素は`0`で初期化されます。 +この例では、 `a` の各要素は `0` で初期化されます。 ```rust let a = [0; 20]; // a: [i32; 20] ``` -配列`a`の要素の個数は`a.len()`で得ることができます。 +配列 `a` の要素の個数は `a.len()` で得ることができます。 ```rust let a = [1, 2, 3]; @@ -203,14 +204,14 @@ println!("The second name is: {}", names[1]); -添字はほとんどのプログラミング言語と同じように0から始まります。そのため、最初の名前は`names[0]`で2つ目の名前は`names[1]`です。 -前の例は`The second name is: Brian`とプリントします。 +添字はほとんどのプログラミング言語と同じように0から始まります。そのため、最初の名前は `names[0]` で2つ目の名前は `names[1]` です。 +前の例は `The second name is: Brian` とプリントします。 もし配列に含まれない添字を使おうとすると、エラーが出ます。配列アクセスは実行時に境界チェックを受けます。 他のシステムプログラミング言語では、そのような誤ったアクセスは多くのバグの源となります。 -`array`のさらなるドキュメントは[標準ライブラリのドキュメントの中][array]で見付けることができます。 +`array` のさらなるドキュメントは [標準ライブラリのドキュメントの中][array] で見付けることができます。 [array]: ../std/primitive.array.html @@ -234,25 +235,27 @@ println!("The second name is: {}", names[1]); -様々なものからスライスを作るためには`&`と`[]`の組合せを使うことができます。 -`&`はスライスが参照と同じであることを示し、`[]`はレンジを持ち、スライスの長さを定義します。 +様々なものからスライスを作るためには `&` と `[]` の組合せを使うことができます。 +`&` はスライスが参照と同じであることを示し、 `[]` はレンジを持ち、スライスの長さを定義します。 ```rust let a = [0, 1, 2, 3, 4]; -let complete = &a[..]; // A slice containing all of the elements in a -let middle = &a[1..4]; // A slice of a: just the elements 1, 2, and 3 +# // let complete = &a[..]; // A slice containing all of the elements in a +let complete = &a[..]; // aに含まれる全ての要素を持つスライス +# // let middle = &a[1..4]; // A slice of a: just the elements 1, 2, and 3 +let middle = &a[1..4]; // 1、2、3のみを要素に持つaのスライス ``` -スライスは型`&[T]`を持ちます。 -[ジェネリクス][generics]をカバーするときにその`T`について話すでしょう。 +スライスは型 `&[T]` を持ちます。 +[ジェネリクス][generics] をカバーするときにその `T` について話すでしょう。 [generics]: generics.html -`slice`のさらなるドキュメントは[標準ライブラリのドキュメントの中][slice]で見付けることができます。 +`slice` のさらなるドキュメントは [標準ライブラリのドキュメントの中][slice] で見付けることができます。 [slice]: ../std/primitive.slice.html @@ -262,8 +265,8 @@ let middle = &a[1..4]; // A slice of a: just the elements 1, 2, and 3 -Rustの`str`型は最もプリミティブな文字列型です。 -[サイズ不定型][dst]のように、それはそれ自体で非常に便利なものではありませんが、[`&str`][strings]のように参照の後ろに置かれたときに便利になります。 +Rustの `str` 型は最もプリミティブな文字列型です。 +[サイズ不定型][dst] のように、それはそれ自体で非常に便利なものではありませんが、 [`&str`][strings] のように参照の後ろに置かれたときに便利になります。 そのため、それはそのまま置いておきましょう。 [dst]: unsized-types.html @@ -271,7 +274,7 @@ Rustの`str`型は最もプリミティブな文字列型です。 -`str`のさらなるドキュメントは[標準ライブラリのドキュメントの中][str]で見付けることができます。 +`str` のさらなるドキュメントは [標準ライブラリのドキュメントの中][str] で見付けることができます。 [str]: ../std/primitive.str.html @@ -302,13 +305,13 @@ let x: (i32, &str) = (1, "hello"); 見てのとおり、タプルの型はタプルとちょうど同じように見えます。しかし、各位置には値ではなく型名が付いています。 -注意深い読者は、タプルが異なる型の値を含んでいることにも気が付くでしょう。このタプルには`i32`と`&str`が入っています。 +注意深い読者は、タプルが異なる型の値を含んでいることにも気が付くでしょう。このタプルには `i32` と `&str` が入っています。 システムプログラミング言語では、文字列は他の言語よりも少し複雑です。 -今のところ、`&str`を *文字列スライス* と読むだけにしましょう。それ以上のことは後で学ぶでしょう。 +今のところ、 `&str` を *文字列スライス* と読むだけにしましょう。それ以上のことは後で学ぶでしょう。 -もしそれらの持っている型と[アリティ][arity]が同じであれば、あるタプルを他のタプルに割り当てることができます。 +もしそれらの持っている型と [アリティ][arity] が同じであれば、あるタプルを他のタプルに割り当てることができます。 タプルの長さが同じであれば、それらのタプルのアリティは同じです。 [arity]: glossary.html#arity @@ -336,10 +339,10 @@ println!("x is {}", x); -[前に][let]`let`文の左辺は単なる束縛の割当てよりももっと強力だと言ったときのことを覚えていますか。 +[前に][let]`let` 文の左辺は単なる束縛の割当てよりももっと強力だと言ったときのことを覚えていますか。 ここで説明します。 -`let`の左辺にはパターンを書くことができ、もしそれが右辺とマッチしたならば、複数の束縛を一度に割り当てることができます。 -この場合、`let`が「分配束縛」、つまりタプルを「分解して」、要素を3つの束縛に割り当てます。 +`let` の左辺にはパターンを書くことができ、もしそれが右辺とマッチしたならば、複数の束縛を一度に割り当てることができます。 +この場合、 `let` が「分配束縛」、つまりタプルを「分解して」、要素を3つの束縛に割り当てます。 [let]: variable-bindings.html @@ -351,8 +354,10 @@ println!("x is {}", x); コンマを付けることで要素1のタプルを丸括弧の中の値と混同しないように明示することができます。 ```rust -(0,); // single-element tuple -(0); // zero in parentheses +# // (0,); // single-element tuple + (0,); // 1要素のタプル +# // (0); // zero in parentheses + (0); // 丸括弧に囲まれたゼロ ``` @@ -373,11 +378,11 @@ println!("x is {}", x); -配列のインデックスと同じように、それは0から始まります。しかし、配列のインデックスと異なり、それは`[]`ではなく`.`を使います。 +配列のインデックスと同じように、それは0から始まります。しかし、配列のインデックスと異なり、それは `[]` ではなく `.` を使います。 -タプルのさらなるドキュメントは[標準ライブラリのドキュメントの中][tuple]で見付けることができます。 +タプルのさらなるドキュメントは [標準ライブラリのドキュメントの中][tuple] で見付けることができます。 [tuple]: ../std/primitive.tuple.html @@ -396,4 +401,4 @@ let x: fn(i32) -> i32 = foo; -この場合、`x`は`i32`を受け取り`i32`を戻す関数への「関数ポインタ」です。 +この場合、 `x` は `i32` を受け取り `i32` を戻す関数への「関数ポインタ」です。 diff --git a/1.6/ja/book/raw-pointers.md b/1.6/ja/book/raw-pointers.md index 679f5489..8df82f6d 100644 --- a/1.6/ja/book/raw-pointers.md +++ b/1.6/ja/book/raw-pointers.md @@ -1,36 +1,48 @@ -% Raw Pointers +% 生ポインタ + -Rust has a number of different smart pointer types in its standard library, but + +Rustは標準ライブラリに異なるスマートポインタの型を幾つか用意していますが、更に特殊な型が2つあります。Rustの安全性の多くはコンパイル時のチェックに依るものですが、生ポインタを用いるとそういった保証が得られないため [unsafe][unsafe] です。 -`*const T` and `*mut T` are called ‘raw pointers’ in Rust. Sometimes, when + +`*const T` と `*mut T` はRustにおいて「生ポインタ」と呼ばれます。時々、ある種ののライブラリを書く際に、あなたは何らかの理由でRustが行う安全性の保証を避けなければならないこともあります。このようなケースでは、ユーザに安全なインターフェースを提供しつつ、ライブラリの実装に生ポインタを使用できます。例えば、 `*` ポインタはエイリアスとして振る舞うこともできるので、所有権を共有する型を書くのに用いたり、スレッドセーフな共有メモリ型でさえも実装できます。( `Rc` と `Arc` 型は完全にRustのみで実装されています) + + +以下は覚えておくべき生ポインタとその他のポインタ型との違いです。 + + + + + +- 有効なメモリを指していることが保証されないどころか、nullでないことも保証されない( `Box` と `&` では保証される) +- `Box` とは異なり、自動的な後処理が一切行われないため、手動のリソース管理が必要 +- plain-old-dataであるため、Rustコンパイラはuse-after-freeのようなバグから保護できない +- `&` と異なり、ライフタイムの機能が無効化されるため、コンパイラはダングリングポインタを推論できない +- また、 `*const T` を直接介した変更は拒むが、それ以外のエイリアシングやミュータビリティに関する保証はない -# Basics -Creating a raw pointer is perfectly safe: + +# 基本 + + +生ポインタを作成すること自体は絶対に安全です。 ```rust let x = 5; @@ -40,7 +52,9 @@ let mut y = 10; let raw_mut = &mut y as *mut i32; ``` -However, dereferencing one is not. This won’t work: + +しかしながら参照外しは安全ではありません。以下は動作しないでしょう。 + ```rust,ignore let x = 5; @@ -49,7 +63,8 @@ let raw = &x as *const i32; println!("raw points at {}", *raw); ``` -It gives this error: + +このコードは以下のエラーが発生します。 ```text error: dereference of raw pointer requires unsafe function or block [E0133] @@ -57,8 +72,9 @@ error: dereference of raw pointer requires unsafe function or block [E0133] ^~~~ ``` -When you dereference a raw pointer, you’re taking responsibility that it’s not -pointing somewhere that would be incorrect. As such, you need `unsafe`: + +生ポインタを参照外しする時、ポインタが間違った場所を指していないことに対して責任を負うことになります。そういう時は、 `unsafe` を付けなければなりません。 ```rust let x = 5; @@ -69,43 +85,51 @@ let points_at = unsafe { *raw }; println!("raw points at {}", points_at); ``` -For more operations on raw pointers, see [their API documentation][rawapi]. + +生ポインタの操作に関する詳細は、 [APIドキュメント][rawapi] を参照してください。 [unsafe]: unsafe.html [rawapi]: ../std/primitive.pointer.html # FFI -Raw pointers are useful for FFI: Rust’s `*const T` and `*mut T` are similar to + +生ポインタはFFIを使う際に役立ちます。Rustの `*const T` と `*mut T` はそれぞれC言語の `const T*` と `T*` に似ているからです。これの使い方に関する詳細は、 [FFIの章][ffi] を参照してください。 [ffi]: ffi.html -# References and raw pointers + +# 参照と生ポインタ -At runtime, a raw pointer `*` and a reference pointing to the same piece of + +実行時において、同じデータを指す生ポインタ `*` と参照は内部的に同一です。事実、 `unsafe` 外の安全なコードにおいて `&T` 参照は `*const T` 生ポインタへ暗黙的に型強制されますし、 `mut` の場合でも同様です。(これら型強制は、それぞれ `value as *const T` と `value as *mut T` のように、明示的に行うこともできます。) -Going the opposite direction, from `*const` to a reference `&`, is not safe. A + +逆に、 `*const` から 参照 `&` へ遡るのは安全ではありません。 `&T` は常に有効であるため、最低でも `*const T` は型 `T` の有効な実体を指さなければならないのです。その上、ポインタは参照のエイリアシングとミュータビリティの規則も満たす必要があります。コンパイラはあらゆる参照についてこれらの性質が真であると仮定しており、その生成方法に依らず適用するため、生ポインタからのいかなる変換も、参照先の値が上記の性質を満たすと表明していることになります。プログラマがこのことを保証 *しなければならない* のです。 -The recommended method for the conversion is: + +おすすめの変換の方法は以下のとおりです。 ```rust -// explicit cast +# // explicit cast +// 明示的キャスト let i: u32 = 1; let p_imm: *const u32 = &i as *const u32; -// implicit coercion +# // implicit coercion +// 暗黙的キャスト let mut m: u32 = 2; let p_mut: *mut u32 = &mut m; @@ -115,7 +139,8 @@ unsafe { } ``` -The `&*x` dereferencing style is preferred to using a `transmute`. The latter + +`&*x` 参照外し方式は `transmute` を用いるよりも好ましいです。後者は必要以上に強力ですから、より用途が限定されている操作の方が間違って使いにくいでしょう。例えば、前者の方法は `x` がポインタである必要があります。( `transmute` とは異なります) diff --git a/1.6/ja/book/references-and-borrowing.md b/1.6/ja/book/references-and-borrowing.md index 051dd0e2..f81578f0 100644 --- a/1.6/ja/book/references-and-borrowing.md +++ b/1.6/ja/book/references-and-borrowing.md @@ -14,9 +14,9 @@ -* キーとなる概念、[所有権][ownership] +* キーとなる概念、 [所有権][ownership] * 今読んでいる、借用 -* 借用のもう一歩進んだ概念、[ライフタイム][lifetimes] +* 借用のもう一歩進んだ概念、 [ライフタイム][lifetimes] @@ -66,7 +66,7 @@ Rustはそれらの目標をたくさんの「ゼロコスト抽象化」を通 -[所有権][ownership]セクションの最後に、このような感じの厄介な関数に出会いました。 +[所有権][ownership] セクションの最後に、このような感じの厄介な関数に出会いました。 ```rust fn foo(v1: Vec, v2: Vec) -> (Vec, Vec, i32) { @@ -114,16 +114,16 @@ let answer = foo(&v1, &v2); -引数として`Vec`を使う代わりに、参照、つまり`&Vec`を使います。 -そして、`v1`と`v2`を直接渡す代わりに、`&v1`と`&v2`を渡します。 -`&T`型は「参照」と呼ばれ、それは、リソースを所有するのではなく、所有権を借用します。 +引数として `Vec` を使う代わりに、参照、つまり `&Vec` を使います。 +そして、 `v1` と `v2` を直接渡す代わりに、 `&v1` と `&v2` を渡します。 +`&T` 型は「参照」と呼ばれ、それは、リソースを所有するのではなく、所有権を借用します。 何かを借用した束縛はそれがスコープから外れるときにリソースを割当解除しません。 -これは`foo()`の呼出しの後に元の束縛を再び使うことができることを意味します。 +これは `foo()` の呼出しの後に元の束縛を再び使うことができることを意味します。 参照は束縛とちょうど同じようにイミュータブルです。 -これは`foo()`の中ではベクタは全く変更できないことを意味します。 +これは `foo()` の中ではベクタは全く変更できないことを意味します。 ```rust,ignore fn foo(v: &Vec) { @@ -152,7 +152,7 @@ v.push(5); -参照には2つ目の種類、`&mut T`があります。 +参照には2つ目の種類、 `&mut T` があります。 「ミュータブルな参照」によって借用しているリソースを変更することができるようになります。 例は次のとおりです。 @@ -168,24 +168,24 @@ println!("{}", x); -これは`6`をプリントするでしょう。 -`y`を`x`へのミュータブルな参照にして、それから`y`の指示先に1を足します。 -`x`も`mut`とマークしなければならないことに気付くでしょう。 +これは `6` をプリントするでしょう。 +`y` を `x` へのミュータブルな参照にして、それから `y` の指示先に1を足します。 +`x` も `mut` とマークしなければならないことに気付くでしょう。 そうしないと、イミュータブルな値へのミュータブルな借用ということになってしまい、使うことができなくなってしまいます。 -アスタリスク(`*`)を`y`の前に追加して、それを`*y`にしたことにも気付くでしょう。これは、`y`が`&mut`参照だからです。 +アスタリスク( `*` )を `y` の前に追加して、それを `*y` にしたことにも気付くでしょう。これは、 `y` が `&mut` 参照だからです。 参照の内容にアクセスするためにもそれらを使う必要があるでしょう。 -それ以外は、`&mut`参照は普通の参照と全く同じです。 +それ以外は、 `&mut` 参照は普通の参照と全く同じです。 しかし、2つの間には、そしてそれらがどのように相互作用するかには大きな違いが _あります_ 。 -前の例で何かが怪しいと思ったかもしれません。なぜなら、`{`と`}`を使って追加のスコープを必要とするからです。 +前の例で何かが怪しいと思ったかもしれません。なぜなら、 `{` と `}` を使って追加のスコープを必要とするからです。 もしそれらを削除すれば、次のようなエラーが出ます。 ```text @@ -220,8 +220,8 @@ fn main() { -* リソースに対する1つ以上の参照(`&T`) -* ただ1つのミュータブルな参照(`&mut T`) +* リソースに対する1つ以上の参照( `&T` ) +* ただ1つのミュータブルな参照( `&mut T` ) @@ -237,7 +237,7 @@ fn main() { 書込みを行わないのであれば、参照は好きな数だけ使うことができます。 -`&mut`は同時に1つしか持つことができないので、データ競合は起き得ません。 +`&mut` は同時に1つしか持つことができないので、データ競合は起き得ません。 これがRustがデータ競合をコンパイル時に回避する方法です。もしルールを破れば、そのときはエラーが出るでしょう。 @@ -270,7 +270,7 @@ error: cannot borrow `x` as immutable because it is also borrowed as mutable -なぜなら、これはルールに違反しているからです。つまり、`x`を指示する`&mut T`を持つので、`&T`を作ることは許されないのです。 +なぜなら、これはルールに違反しているからです。つまり、 `x` を指示する `&mut T` を持つので、 `&T` を作ることは許されないのです。 どちらか1つです。 メモはこの問題についての考え方のヒントを示します。 @@ -287,7 +287,7 @@ fn main() { 言い換えると、ミュータブルな借用は先程の例の残りの間ずっと保持されるということです。 -必要なものは、`println!`を呼び出し、イミュータブルな借用を作ろうとする _前に_ 終わるミュータブルな借用です。 +必要なものは、 `println!` を呼び出し、イミュータブルな借用を作ろうとする _前に_ 終わるミュータブルな借用です。 Rustでは借用はその有効なスコープと結び付けられます。 そしてスコープはこのように見えます。 @@ -309,7 +309,7 @@ println!("{}", x); // -+ - ここでxを借用しようとする ``` -スコープは衝突します。`y`がスコープにある間は、`&x`を作ることができません。 +スコープは衝突します。 `y` がスコープにある間は、 `&x` を作ることができません。 そして、波括弧を追加するときはこうなります。 @@ -367,7 +367,7 @@ for i in &v { これは1から3までをプリントアウトします。 ベクタに対して繰り返すとき、要素への参照だけを受け取ります。 -そして、`v`はそれ自体イミュータブルとして借用され、それは繰返しを行っている間はそれを変更できないことを意味します。 +そして、 `v` はそれ自体イミュータブルとして借用され、それは繰返しを行っている間はそれを変更できないことを意味します。 ```rust,ignore let mut v = vec![1, 2, 3]; @@ -398,7 +398,7 @@ for i in &v { ``` -`v`はループによって借用されるので、それを変更することはできません。 +`v` はループによって借用されるので、それを変更することはできません。 ### 解放後の使用 @@ -449,8 +449,8 @@ statement 0 at 4:18 -言い換えると、`y`は`x`が存在するスコープの中でだけ有効だということです。 -`x`がなくなるとすぐに、それを指示することは不正になります。 +言い換えると、 `y` は `x` が存在するスコープの中でだけ有効だということです。 +`x` がなくなるとすぐに、それを指示することは不正になります。 そのように、エラーは借用が「十分長く生存していない」ことを示します。なぜなら、それが正しい期間有効ではないからです。 @@ -494,4 +494,4 @@ statement 1 at 3:14 -前の例では、`y`は`x`より前に宣言されています。それは、`y`が`x`より長く生存することを意味し、それは許されません。 +前の例では、 `y` は `x` より前に宣言されています。それは、 `y` が `x` より長く生存することを意味し、それは許されません。 diff --git a/1.6/ja/book/release-channels.md b/1.6/ja/book/release-channels.md index 1e203c65..f0087f28 100644 --- a/1.6/ja/book/release-channels.md +++ b/1.6/ja/book/release-channels.md @@ -1,52 +1,65 @@ -% Release Channels +% リリースチャネル + -The Rust project uses a concept called ‘release channels’ to manage releases. -It’s important to understand this process to choose which version of Rust -your project should use. + + + +Rustプロジェクトではリリースを管理するために「リリースチャネル」という考え方を採用しています。どのバージョンのRustを使用するか決めるためには、この考え方を理解することが重要になります。 -# Overview + +# 概要 -There are three channels for Rust releases: + +Rustのリリースには以下の3つのチャネルがあります。 * Nightly * Beta * Stable -New nightly releases are created once a day. Every six weeks, the latest -nightly release is promoted to ‘Beta’. At that point, it will only receive -patches to fix serious errors. Six weeks later, the beta is promoted to -‘Stable’, and becomes the next release of `1.x`. - -This process happens in parallel. So every six weeks, on the same day, -nightly goes to beta, beta goes to stable. When `1.x` is released, at -the same time, `1.(x + 1)-beta` is released, and the nightly becomes the -first version of `1.(x + 2)-nightly`. - -# Choosing a version - -Generally speaking, unless you have a specific reason, you should be using the -stable release channel. These releases are intended for a general audience. - -However, depending on your interest in Rust, you may choose to use nightly -instead. The basic tradeoff is this: in the nightly channel, you can use -unstable, new Rust features. However, unstable features are subject to change, -and so any new nightly release may break your code. If you use the stable -release, you cannot use experimental features, but the next release of Rust -will not cause significant issues through breaking changes. - -# Helping the ecosystem through CI - -What about beta? We encourage all Rust users who use the stable release channel -to also test against the beta channel in their continuous integration systems. -This will help alert the team in case there’s an accidental regression. - -Additionally, testing against nightly can catch regressions even sooner, and so -if you don’t mind a third build, we’d appreciate testing against all channels. - -As an example, many Rust programmers use [Travis](https://travis-ci.org/) to -test their crates, which is free for open source projects. Travis [supports -Rust directly][travis], and you can use a `.travis.yml` file like this to -test on all channels: + + + + +新しいnightlyリリースは毎日作られます。6週間ごとに、最新のnightlyリリースが「Beta」に格上げされます。これ以降は深刻なエラーを修正するパッチのみが受け付けられます。さらに6週間後、betaは「Stable」に格上げされ、次の「1.x」リリースになります。 + + + + + +このプロセスは並行して行われます。つまり6週間毎の同じ日に、nightlyはbetaに、betaはstableになります。「1.x」がリリースされると同時に「1.(x + 1)-beta」がリリースされ、nightlyは「1.(x + 2)-nightly」の最初のバージョンになる、ということです。 + + +# バージョンを選ぶ + + + +一般的に言って、特別な理由がなければstableリリースチャネルを使うべきです。このリリースは一般のユーザ向けになっています。 + + + + + + + +しかしRustに特に関心のある方は、代わりにnightlyを選んでも構いません。基本的な交換条件は次の通りです。nightlyチャネルを選ぶと不安定で新しいフィーチャを使うことができます。しかし、不安定なフィーチャは変更されやすく、新しいnightlyリリースでソースコードが動かなくなってしまうかもしれません。stableリリースを使えば、実験的なフィーチャを使うことはできませんが、Rustのバージョンが上がっても破壊的な変更によるトラブルは起きないでしょう。 + + +# CIによるエコシステム支援 + + + + +betaとはどういうチャネルでしょうか?stableリリースチャネルを使う全てのユーザは、継続的インテグレーションシステムを使ってbetaリリースに対してもテストすることを推奨しています。こうすることで、突発的なリグレッションに備えることができます。 + + + +さらに、nightlyに対してもテストすることでより早くリグレッションを捉えることができます。もし差し支えなければ、この3つ目のビルドを含めた全てのチャネルに対してテストしてもらえると嬉しいです。 + + + + + +例えば、多くのRustプログラマが [Travis](https://travis-ci.org/) をクレートのテストに使っています。(このサービスはオープンソースプロジェクトについては無料で使えます) Travisは [Rustを直接サポート][travis] しており、「`.travis.yml`」に以下のように書くことですべてのチャネルに対するテストを行うことができます。 ```yaml language: rust @@ -62,7 +75,8 @@ matrix: [travis]: http://docs.travis-ci.com/user/languages/rust/ -With this configuration, Travis will test all three channels, but if something -breaks on nightly, it won’t fail your build. A similar configuration is -recommended for any CI system, check the documentation of the one you’re -using for more details. + + + + +この設定で、Travisは3つ全てのチャネルに対してテストを行いますが、nightlyで何かおかしくなったとしてもビルドが失敗にはなりません。他のCIシステムでも同様の設定をお勧めします。詳細はお使いのシステムのドキュメントを参照してください。 diff --git a/1.6/ja/book/structs.md b/1.6/ja/book/structs.md index d18b9570..c1744517 100644 --- a/1.6/ja/book/structs.md +++ b/1.6/ja/book/structs.md @@ -4,7 +4,7 @@ -`struct`はより複雑なデータ型を作る方法の1つです。例えば、もし私たちが2次元空間の座標に関する計算を行っているとして、`x`と`y`、両方の値が必要になるでしょう。 +`struct` はより複雑なデータ型を作る方法の1つです。例えば、もし私たちが2次元空間の座標に関する計算を行っているとして、 `x` と `y` 、両方の値が必要になるでしょう。 ```rust let origin_x = 0; @@ -12,7 +12,7 @@ let origin_y = 0; ``` -`struct`でこれら2つを1つのデータ型にまとめることができます。 +`struct` でこれら2つを1つのデータ型にまとめることができます。 ```rust struct Point { @@ -30,20 +30,20 @@ fn main() { -ここで多くの情報が出てきましたから、順番に見ていきましょう。まず、`struct`キーワードを使って構造体とその名前を宣言しています。慣習により、構造体は初めが大文字のキャメルケースで記述しています。`PointInSpace`であり、`Point_In_Space`ではありません。 +ここで多くの情報が出てきましたから、順番に見ていきましょう。まず、 `struct` キーワードを使って構造体とその名前を宣言しています。慣習により、構造体は初めが大文字のキャメルケースで記述しています。 `PointInSpace` であり、 `Point_In_Space` ではありません。 -いつものように、`let`で`struct`のインスタンスを作ることができますが、ここでは`key: value`スタイルの構文でそれぞれのフィールドに値をセットしています。順序は元の宣言と同じである必要はありません。 +いつものように、 `let` で `struct` のインスタンスを作ることができますが、ここでは `key: value` スタイルの構文でそれぞれのフィールドに値をセットしています。順序は元の宣言と同じである必要はありません。 -最後に、作成された構造体のフィールドは名前を持つため、`origin.x`というようにドット表記でアクセスできます。 +最後に、作成された構造体のフィールドは名前を持つため、 `origin.x` というようにドット表記でアクセスできます。 -Rustの他の束縛のように、`struct`が持つ値はイミュータブルがデフォルトです。`mut`を使うと値をミュータブルにできます。 +Rustの他の束縛のように、 `struct` が持つ値はイミュータブルがデフォルトです。 `mut` を使うと値をミュータブルにできます。 ```rust struct Point { @@ -61,7 +61,7 @@ fn main() { ``` -これは`The point is at (5, 0)`と出力されます。 +これは `The point is at (5, 0)` と出力されます。 @@ -92,8 +92,10 @@ fn main() { point.x = 5; +# // let point = point; // this new binding can’t change now let point = point; // この新しい束縛でここから変更できなくなります +# // point.y = 6; // this causes an error point.y = 6; // これはエラーになります } ``` @@ -103,7 +105,7 @@ fn main() { -`struct`の初期化時には、値の一部を他の構造体からコピーしたいことを示す`..`を含めることができます。例えば、 +`struct` の初期化時には、値の一部を他の構造体からコピーしたいことを示す `..` を含めることができます。例えば、 ```rust struct Point3d { @@ -137,7 +139,7 @@ let point = Point3d { z: 1, x: 2, .. origin }; -Rustには「タプル構造体」と呼ばれる、[タプル][tuple]と`struct`のハイブリットのようなデータ型があります。タプル構造体自体には名前がありますが、そのフィールドには名前がありません。 +Rustには「タプル構造体」と呼ばれる、[タプル][tuple]と `struct` のハイブリットのようなデータ型があります。タプル構造体自体には名前がありますが、そのフィールドには名前がありません。 ```rust struct Color(i32, i32, i32); @@ -158,7 +160,7 @@ let origin = Point(0, 0, 0); -ほとんどの場合タプル構造体よりも`struct`を使ったほうが良いです。`Color`や`Point`はこのようにも書けます。 +ほとんどの場合タプル構造体よりも `struct` を使ったほうが良いです。 `Color` や `Point` はこのようにも書けます。 ```rust struct Color { @@ -176,7 +178,7 @@ struct Point { -今、私たちはフィールドの位置ではなく実際のフィールドの名前を持っています。良い名前は重要で、`struct`を使うということは、実際に名前を持っているということです。 +今、私たちはフィールドの位置ではなく実際のフィールドの名前を持っています。良い名前は重要で、 `struct` を使うということは、実際に名前を持っているということです。 > 訳注: 原文を元に噛み砕くと、「タプルはフィールドの並びによって区別され、構造体はフィールドの名前によって区別されます。これはタプルと構造体の最たる違いであり、構造体を持つことは名前を付けられたデータの集まりを持つことに等しいため、構造体における名前付けは重要です。」といった所でしょうか。 @@ -198,13 +200,13 @@ println!("length is {} inches", integer_length); -上記の通り、`let`を使って分解することで、標準のタプルと同じように内部の整数型を取り出すことができます。 -このケースでは`let Inches(integer_length)`が`integer_length`へ`10`を束縛します。 +上記の通り、 `let` を使って分解することで、標準のタプルと同じように内部の整数型を取り出すことができます。 +このケースでは `let Inches(integer_length)` が `integer_length` へ `10` を束縛します。 # Unit-like 構造体 -あなたは全くメンバを持たない`struct`を定義できます。 +あなたは全くメンバを持たない `struct` を定義できます。 ```rust struct Electron; @@ -215,7 +217,7 @@ let x = Electron; -空のタプルである`()`は時々`unit`と呼ばれ、それに似ていることからこのような構造体を`unit-like`と呼んでいます。タプル構造体のように、これは新しい型を定義します。 +空のタプルである `()` は時々 `unit` と呼ばれ、それに似ていることからこのような構造体を `unit-like` と呼んでいます。タプル構造体のように、これは新しい型を定義します。 -これは単体でもごくまれに役立ちます(もっとも、時々型をマーク代わりとして役立てる程度です)が、他の機能と組み合わせることにより便利になります。例えば、ライブラリはあなたにイベントを処理できる特定の[トレイト][trait]が実装されたストラクチャの作成を要求するかもしれません。もしそのストラクチャの中に保存すべき値が何もなければ、あなたはダミーのデータを作成する必要はなく、ただunit-likeな`struct`を作るだけで良いのです。 +これは単体でもごくまれに役立ちます(もっとも、時々型をマーク代わりとして役立てる程度です)が、他の機能と組み合わせることにより便利になります。例えば、ライブラリはあなたにイベントを処理できる特定の[トレイト][trait]が実装されたストラクチャの作成を要求するかもしれません。もしそのストラクチャの中に保存すべき値が何もなければ、あなたはダミーのデータを作成する必要はなく、ただunit-likeな `struct` を作るだけで良いのです。 [trait]: traits.html diff --git a/1.6/ja/book/testing.md b/1.6/ja/book/testing.md index 32f0d689..c396b6a9 100644 --- a/1.6/ja/book/testing.md +++ b/1.6/ja/book/testing.md @@ -1,27 +1,39 @@ -% Testing - -> Program testing can be a very effective way to show the presence of bugs, but -> it is hopelessly inadequate for showing their absence. -> -> Edsger W. Dijkstra, "The Humble Programmer" (1972) - -Let's talk about how to test Rust code. What we will not be talking about is -the right way to test Rust code. There are many schools of thought regarding -the right and wrong way to write tests. All of these approaches use the same -basic tools, and so we'll show you the syntax for using them. - -# The `test` attribute - -At its simplest, a test in Rust is a function that's annotated with the `test` -attribute. Let's make a new project with Cargo called `adder`: +% テスト + + + + + + +> プログラムのテストはバグの存在を示すためには非常に効率的な方法ですが、バグの不存在を示すためには絶望的に不十分です。 +> エドガー・W・ダイクストラ、『謙虚なプログラマ』(1972) + + + + + +Rustのコードをテストする方法について話しましょう。 +ここではRustのコードをテストする正しい方法について議論するつもりはありません。 +テストを書くための正しい方法、誤った方法に関する流派はたくさんあります。 +それらの方法は全て、同じ基本的なツールを使うので、それらのツールを使うための文法をお見せしましょう。 + + +# `test` アトリビュート + + + +Rustでの一番簡単なテストは、 `test` アトリビュートの付いた関数です。 +`adder` という名前の新しいプロジェクトをCargoで作りましょう。 ```bash $ cargo new adder $ cd adder ``` -Cargo will automatically generate a simple test when you make a new project. -Here's the contents of `src/lib.rs`: + + +新しいプロジェクトを作ると、Cargoは自動的に簡単なテストを生成します。 +これが `src/lib.rs` の内容です。 ```rust #[test] @@ -29,9 +41,14 @@ fn it_works() { } ``` -Note the `#[test]`. This attribute indicates that this is a test function. It -currently has no body. That's good enough to pass! We can run the tests with -`cargo test`: + + + +`#[test]` に注意しましょう。 +このアトリビュートは、この関数がテスト関数であるということを示します。 +今のところ、その関数には本文がありません。 +成功させるためにはそれで十分なのです! +テストは `cargo test` で実行することができます。 ```bash $ cargo test @@ -50,29 +67,39 @@ running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured ``` -Cargo compiled and ran our tests. There are two sets of output here: one -for the test we wrote, and another for documentation tests. We'll talk about -those later. For now, see this line: + + + +Cargoはテストをコンパイルし、実行しました。 +ここでは2種類の結果が出力されています。1つは書かれたテストについてのもの、もう1つはドキュメンテーションテストについてのものです。 +それらについては後で話しましょう。 +とりあえず、この行を見ましょう。 ```text test it_works ... ok ``` -Note the `it_works`. This comes from the name of our function: + +`it_works` に注意しましょう。 +これは関数の名前に由来しています。 ```rust fn it_works() { # } ``` -We also get a summary line: + +次のようなサマリも出力されています。 ```text test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured ``` -So why does our do-nothing test pass? Any test which doesn't `panic!` passes, -and any test that does `panic!` fails. Let's make our test fail: + + +なぜ何も書いていないテストがこのように成功するのでしょうか。 +`panic!` しないテストは全て成功で、 `panic!` するテストは全て失敗なのです。 +テストを失敗させましょう。 ```rust #[test] @@ -81,9 +108,12 @@ fn it_works() { } ``` -`assert!` is a macro provided by Rust which takes one argument: if the argument -is `true`, nothing happens. If the argument is `false`, it `panic!`s. Let's run -our tests again: + + + +`assert!` はRustが提供するマクロで、1つの引数を取ります。引数が `true` であれば何も起きません。 +引数が `false` であれば `panic!` します。 +テストをもう一度実行しましょう。 ```bash $ cargo test @@ -108,41 +138,49 @@ test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured thread '
' panicked at 'Some tests failed', /home/steve/src/rust/src/libtest/lib.rs:247 ``` -Rust indicates that our test failed: + +Rustは次のとおりテストが失敗したことを示しています。 ```text test it_works ... FAILED ``` -And that's reflected in the summary line: + +そして、それはサマリにも反映されます。 ```text test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured ``` -We also get a non-zero status code. We can use `$?` on OS X and Linux: + +ステータスコードも非0になっています。 +OS XやLinuxでは `$?` を使うことができます。 ```bash $ echo $? 101 ``` -On Windows, if you’re using `cmd`: + +Windowsでは、 `cmd` を使っていればこうです。 ```bash > echo %ERRORLEVEL% ``` -And if you’re using PowerShell: + +そして、PowerShellを使っていればこうです。 ```bash > echo $LASTEXITCODE # the code itself > echo $? # a boolean, fail or succeed ``` -This is useful if you want to integrate `cargo test` into other tooling. + +これは `cargo test` を他のツールと統合したいときに便利です。 -We can invert our test's failure with another attribute: `should_panic`: + +もう1つのアトリビュート、 `should_panic` を使ってテストの失敗を反転させることができます。 ```rust #[test] @@ -152,7 +190,9 @@ fn it_works() { } ``` -This test will now succeed if we `panic!` and fail if we complete. Let's try it: + +今度は、このテストが `panic!` すれば成功で、完走すれば失敗です。 +試しましょう。 ```bash $ cargo test @@ -171,8 +211,9 @@ running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured ``` -Rust provides another macro, `assert_eq!`, that compares two arguments for -equality: + + +Rustはもう1つのマクロ、 `assert_eq!` を提供しています。これは2つの引数の等価性を調べます。 ```rust #[test] @@ -182,8 +223,10 @@ fn it_works() { } ``` -Does this test pass or fail? Because of the `should_panic` attribute, it -passes: + + +このテストは成功でしょうか、失敗でしょうか。 +`should_panic` アトリビュートがあるので、これは成功です。 ```bash $ cargo test @@ -202,11 +245,15 @@ running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured ``` -`should_panic` tests can be fragile, as it's hard to guarantee that the test -didn't fail for an unexpected reason. To help with this, an optional `expected` -parameter can be added to the `should_panic` attribute. The test harness will -make sure that the failure message contains the provided text. A safer version -of the example above would be: + + + + + +`should_panic` を使ったテストは脆いテストです。なぜなら、テストが予想外の理由で失敗したのではないということを保証することが難しいからです。 +これを何とかするために、 `should_panic` アトリビュートにはオプションで `expected` パラメータを付けることができます。 +テストハーネスが、失敗したときのメッセージに与えられたテキストが含まれていることを確かめてくれます。 +前述の例のもっと安全なバージョンはこうなります。 ```rust #[test] @@ -216,7 +263,9 @@ fn it_works() { } ``` -That's all there is to the basics! Let's write one 'real' test: + +基本はそれだけです! +「リアルな」テストを書いてみましょう。 ```rust,ignore pub fn add_two(a: i32) -> i32 { @@ -229,13 +278,17 @@ fn it_works() { } ``` -This is a very common use of `assert_eq!`: call some function with -some known arguments and compare it to the expected output. + + +これは非常に一般的な `assert_eq!` の使い方です。いくつかの関数に結果の分かっている引数を渡して呼び出し、期待した結果と比較します。 -# The `ignore` attribute + +# `ignore` アトリビュート -Sometimes a few specific tests can be very time-consuming to execute. These -can be disabled by default by using the `ignore` attribute: + + +ときどき、特定のテストの実行に非常に時間が掛かることがあります。 +そのようなテストは、 `ignore` アトリビュートを使ってデフォルトでは無効にすることができます。 ```rust #[test] @@ -246,12 +299,14 @@ fn it_works() { #[test] #[ignore] fn expensive_test() { - // code that takes an hour to run +# // code that takes an hour to run + // 実行に1時間掛かるコード } ``` -Now we run our tests and see that `it_works` is run, but `expensive_test` is -not: + + +テストを実行すると、 `it_works` が実行されることを確認できますが、今度は `expensive_test` は実行されません。 ```bash $ cargo test @@ -271,7 +326,8 @@ running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured ``` -The expensive tests can be run explicitly using `cargo test -- --ignored`: + +無効にされた高コストなテストは `cargo test -- --ignored` を使って明示的に実行することができます。 ```bash $ cargo test -- --ignored @@ -289,14 +345,19 @@ running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured ``` -The `--ignored` argument is an argument to the test binary, and not to Cargo, -which is why the command is `cargo test -- --ignored`. + + +`--ignored` アトリビュートはテストバイナリの引数であって、Cargoのものではありません。 +コマンドが `cargo test -- --ignored` となっているのはそういうことです。 -# The `tests` module + +# `tests` モジュール -There is one way in which our existing example is not idiomatic: it's -missing the `tests` module. The idiomatic way of writing our example -looks like this: + + + +今までの例における手法は、慣用的ではありません。 `tests` モジュールがないからです。 +今までの例の慣用的な書き方はこのようになります。 ```rust,ignore pub fn add_two(a: i32) -> i32 { @@ -314,17 +375,26 @@ mod tests { } ``` -There's a few changes here. The first is the introduction of a `mod tests` with -a `cfg` attribute. The module allows us to group all of our tests together, and -to also define helper functions if needed, that don't become a part of the rest -of our crate. The `cfg` attribute only compiles our test code if we're -currently trying to run the tests. This can save compile time, and also ensures -that our tests are entirely left out of a normal build. - -The second change is the `use` declaration. Because we're in an inner module, -we need to bring our test function into scope. This can be annoying if you have -a large module, and so this is a common use of globs. Let's change our -`src/lib.rs` to make use of it: + + + + + + +ここでは、いくつかの変更点があります。 +まず、 `cfg` アトリビュートの付いた `mod tests` を導入しました。 +このモジュールを使うと、全てのテストをグループ化することができます。また、必要であれば、ヘルパ関数を定義し、それをクレートの一部に含まれないようにすることもできます。 + `cfg` アトリビュートによって、テストを実行しようとしているときにだけテストコードがコンパイルされるようになります。 +これは、コンパイル時間を節約し、テストが通常のビルドに全く影響しないことを保証してくれます。 + + + + + +2つ目の変更点は、 `use` 宣言です。 +ここは内部モジュールの中なので、テスト関数をスコープの中に持ち込む必要があります。 +モジュールが大きい場合、これは面倒かもしれないので、ここがグロブの一般的な使い所です。 +`src/lib.rs` をグロブを使うように変更しましょう。 ```rust,ignore pub fn add_two(a: i32) -> i32 { @@ -342,7 +412,9 @@ mod tests { } ``` -Note the different `use` line. Now we run our tests: + +`use` 行が変わったことに注意しましょう。 +さて、テストを実行します。 ```bash $ cargo test @@ -362,17 +434,24 @@ running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured ``` -It works! + +動きます! -The current convention is to use the `tests` module to hold your "unit-style" -tests. Anything that just tests one small bit of functionality makes sense to -go here. But what about "integration-style" tests instead? For that, we have -the `tests` directory. + + + + +現在の慣習では、 `tests` モジュールは「ユニット」テストを入れるために使うことになっています。 +単一の小さな機能の単位をテストするだけのものは全て、ここに入れる意味があります。 +しかし、「結合」テストはどうでしょうか。 +結合テストのためには、 `tests` ディレクトリがあります。 -# The `tests` directory + +# `tests` ディレクトリ -To write an integration test, let's make a `tests` directory, and -put a `tests/lib.rs` file inside, with this as its contents: + + +結合テストを書くために、 `tests` ディレクトリを作りましょう。そして、その中に次の内容の `tests/lib.rs` ファイルを置きます。 ```rust,ignore extern crate adder; @@ -383,13 +462,18 @@ fn it_works() { } ``` -This looks similar to our previous tests, but slightly different. We now have -an `extern crate adder` at the top. This is because the tests in the `tests` -directory are an entirely separate crate, and so we need to import our library. -This is also why `tests` is a suitable place to write integration-style tests: -they use the library like any other consumer of it would. + + + + + +これは前のテストと似ていますが、少し違います。 +今回は、 `extern crate adder` を先頭に書いています。 +これは、 `tests` ディレクトリの中のテストが全く別のクレートであるため、ライブラリをインポートしなければならないからです。 +これは、なぜ `tests` が結合テストを書くのに適切な場所なのかという理由でもあります。そこにあるテストは、そのライブラリを他のプログラムと同じようなやり方で使うからです。 -Let's run them: + +テストを実行しましょう。 ```bash $ cargo test @@ -415,24 +499,34 @@ running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured ``` -Now we have three sections: our previous test is also run, as well as our new -one. + + +今度は3つのセクションが出力されました。新しいテストが実行され、前に書いたテストも同様に実行されます。 -That's all there is to the `tests` directory. The `tests` module isn't needed -here, since the whole thing is focused on tests. + + +`tests` ディレクトリについてはそれだけです。 +`tests` モジュールはここでは必要ありません。全てのものがテストのためのものだからです。 -Let's finally check out that third section: documentation tests. + +最後に、3つ目のセクションを確認しましょう。ドキュメンテーションテストです。 -# Documentation tests + +# ドキュメンテーションテスト -Nothing is better than documentation with examples. Nothing is worse than -examples that don't actually work, because the code has changed since the -documentation has been written. To this end, Rust supports automatically -running examples in your documentation (**note:** this only works in library -crates, not binary crates). Here's a fleshed-out `src/lib.rs` with examples: + + + + + +例の付いたドキュメントほどよいものはありません。 +ドキュメントを書いた後にコードが変更された結果、実際に動かなくなった例ほど悪いものはありません。 +この状況を終わらせるために、Rustはあなたのドキュメント内の例の自動実行をサポートします( **注意:** これはライブラリクレートの中でのみ動作し、バイナリクレートの中では動作しません)。 +これが例を付けた具体的な `src/lib.rs` です。 ```rust,ignore -//! The `adder` crate provides functions that add numbers to other numbers. +# //! The `adder` crate provides functions that add numbers to other numbers. +//! `adder`クレートはある数値を数値に加える関数を提供する //! //! # Examples //! @@ -440,7 +534,8 @@ crates, not binary crates). Here's a fleshed-out `src/lib.rs` with examples: //! assert_eq!(4, adder::add_two(2)); //! ``` -/// This function adds two to its argument. +# /// This function adds two to its argument. +/// この関数は引数に2を加える /// /// # Examples /// @@ -464,12 +559,16 @@ mod tests { } ``` -Note the module-level documentation with `//!` and the function-level -documentation with `///`. Rust's documentation supports Markdown in comments, -and so triple graves mark code blocks. It is conventional to include the -`# Examples` section, exactly like that, with examples following. + + + + +モジュールレベルのドキュメントには `//!` を付け、関数レベルのドキュメントには `///` を付けていることに注意しましょう。 +RustのドキュメントはMarkdown形式のコメントをサポートしていて、3連バッククオートはコードブロックを表します。 +`# Examples` セクションを含めるのが慣習で、そのとおり、例が後に続きます。 -Let's run the tests again: + +テストをもう一度実行しましょう。 ```bash $ cargo test @@ -497,14 +596,21 @@ test _0 ... ok test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured ``` -Now we have all three kinds of tests running! Note the names of the -documentation tests: the `_0` is generated for the module test, and `add_two_0` -for the function test. These will auto increment with names like `add_two_1` as -you add more examples. - -We haven’t covered all of the details with writing documentation tests. For more, -please see the [Documentation chapter](documentation.html) - -One final note: documentation tests *cannot* be run on binary crates. -To see more on file arrangement see the [Crates and -Modules](crates-and-modules.html) section. + + + + +今回は全ての種類のテストを実行しています! +ドキュメンテーションテストの名前に注意しましょう。 `_0` はモジュールテストのために生成された名前で、 `add_two_0` は関数テストのために生成された名前です。 +例を追加するにつれて、それらの名前は `add_two_1` というような形で数値が増えていきます。 + + + +まだドキュメンテーションテストの書き方の詳細について、全てをカバーしてはいません。 +詳しくは [ドキュメントの章](documentation.html) を見てください。 + + + + +最後の注意:バイナリクレート上のテストは実行 *できません* 。 +ファイルの配置についてもっと知りたい場合は [クレートとモジュール](crates-and-modules.html) セクションを見ましょう。 diff --git a/1.6/ja/book/unsafe.md b/1.6/ja/book/unsafe.md index 1b223365..3cc5a640 100644 --- a/1.6/ja/book/unsafe.md +++ b/1.6/ja/book/unsafe.md @@ -1,67 +1,125 @@ % Unsafe + +Rustの主たる魅力は、プログラムの動作についての強力で静的な保証です。 +しかしながら、安全性検査は本来保守的なものです。 +すなわち、実際には安全なのに、そのことがコンパイラには検証できないプログラムがいくらか存在します。 +その類のプログラムを書くためには、制約を少し緩和するようコンパイラに対して伝えることが要ります。 +そのために、Rustには `unsafe` というキーワードがあります。 +`unsafe` を使ったコードは、普通のコードよりも制約が少なくなります。 + + +まずシンタックスをみて、それからセマンティクスについて話しましょう。 +`unsafe` は4つの場面で使われます。 +1つめは、関数がアンセーフであることを印付ける場合です。 ```rust unsafe fn danger_will_robinson() { - // scary stuff +# // scary stuff + // 恐ろしいもの } ``` + +たとえば、[FFI][ffi]から呼び出されるすべての関数は`unsafe`で印付けることが必要です。 +`unsafe`の2つめの用途は、アンセーフブロックです。 [ffi]: ffi.html ```rust unsafe { - // scary stuff +# // scary stuff + // 恐ろしいもの } ``` -The third is for unsafe traits: + +3つめは、アンセーフトレイトです。 ```rust unsafe trait Scary { } ``` -And the fourth is for `impl`ementing one of those traits: + +そして、4つめは、そのアンセーフトレイトを実装する場合です。 ```rust # unsafe trait Scary { } unsafe impl Scary for i32 {} ``` + +大きな問題を引き起こすバグがあるかもしれないコードを明示できるのは重要なことです。 +もしRustのプログラムがセグメンテーション違反を起こしても、バグは `unsafe` で印付けられた区間のどこかにあると確信できます。 -# What does ‘safe’ mean? +# 「安全」とはどういう意味か? + + +Rustの文脈で、安全とは「どのようなアンセーフなこともしない」ことを意味します。 + +> 訳注: +正確には、安全とは「決して未定義動作を起こさない」ということです。 +そして、安全性が保証されていないことを「アンセーフ」と呼びます。 +つまり、未定義動作が起きるおそれがあるなら、それはアンセーフです。 +知っておくべき重要なことに、たいていのコードにおいて望ましくないが、アンセーフ _ではない_ とされている動作がいくらか存在するということがあります。 + + +* デッドロック +* メモリやその他のリソースのリーク +* デストラクタを呼び出さないプログラム終了 +* 整数オーバーフロー + +Rustはソフトウェアが抱えるすべての種類の問題を防げるわけではありません。 +Rustでバグのあるコードを書くことはできますし、実際に書かれるでしょう。 +これらの動作は良いことではありませんが、特にアンセーフだとは見なされません。 + +さらに、Rustにおいては、次のものは未定義動作で、 `unsafe` コード中であっても、避ける必要があります。 + +> 訳注: +関数に付いている`unsafe`は「その関数の処理はアンセーフである」ということを表します。 +その一方で、ブロックに付いている`unsafe`は「ブロック中の個々の操作はアンセーフだが、全体としては安全な処理である」ということを表します。 +避ける必要があるのは、未定義動作が起こりうる処理をアンセーフブロックの中に書くことです。 +それは、アンセーフブロックの処理が安全であるために、その内部で未定義動作が決して起こらないことが必要だからです。 +アンセーフ関数には安全性の保証が要らないので、未定義動作が起こりうるアンセーフ関数を定義することに問題はありません。 + +* データ競合 +* ヌル・ダングリング生ポインタの参照外し +* [undef][undef] (未初期化)メモリの読み出し +* 生ポインタによる [pointer aliasing rules][aliasing] の違反 +* `&mut T` と `&T` は、 `UnsafeCell` を含む `&T` を除き、LLVMのスコープ化された [noalias][noalias] モデルに従っています。アンセーフコードは、それら参照のエイリアシング保証を破ってはいけません。 +* `UnsafeCell` を持たないイミュータブルな値・参照の変更 +* コンパイラIntrinsic経由の未定義挙動の呼び出し + * `std::ptr::offset` (`offset` intrinsic) を使って、オブジェクトの範囲外を指すこと。ただし、オブジェクトの最後より1バイト後を指すことは許されている。 + * 範囲の重なったバッファに対して `std::ptr::copy_nonoverlapping_memory` (`memcpy32`/`memcpy64` + intrinsics) を使う +* プリミティブ型の不正な値(プライベートなフィールドやローカル変数を含む) + * ヌルかダングリングである参照やボックス + * `bool` における、 `false` (0) か `true` (1) でない値 + * `enum` の定義に含まれていない判別子 + * `char` における、サロゲートか `char::MAX` を超えた値 + * `str` における、UTF-8でないバイト列 +* 他言語からRustへの巻き戻しや、Rustから他言語への巻き戻し [noalias]: http://llvm.org/docs/LangRef.html#noalias [undef]: http://llvm.org/docs/LangRef.html#undefined-values [aliasing]: http://llvm.org/docs/LangRef.html#pointer-aliasing-rules -# Unsafe Superpowers +# アンセーフの能力 + + +アンセーフ関数・アンセーフブロックでは、Rustは普段できない3つのことをさせてくれます。たった3つです。それは、 + +1. [静的ミュータブル変数][static]のアクセスとアップデート。 +2. 生ポインタの参照外し。 +3. アンセーフ関数の呼び出し。これが最も強力な能力です。 + +以上です。 +重要なのは、 `unsafe` が、たとえば「借用チェッカをオフにする」といったことを行わないことです。 +Rustのコードの適当な位置に `unsafe` を加えてもセマンティクスは変わらず、何でもただ受理するようになるということにはなりません。 +それでも、`unsafe` はルールのいくつかを破るコードを書けるようにはするのです。 + +また、`unsafe` キーワードは、Rust以外の言語とのインターフェースを書くときに遭遇するでしょう。 +ライブラリの提供するメソッドの周りに、安全な、Rustネイティブのインターフェースを書くことが推奨されています。 + +これから、その基本的な3つの能力を順番に見ていきましょう。 -## Access or update a `static mut` +## `static mut` のアクセスとアップデート。 + + +Rustには「`static mut`」という、ミュータブルでグローバルな状態を実現する機能があります。 +これを使うことはデータレースが起こるおそれがあるので、本質的に安全ではありません。 +詳細は、この本の[static][static]セクションを参照してください。 [static]: const-and-static.html#static -## Dereference a raw pointer +## 生ポインタの参照外し + + +生ポインタによって任意のポインタ演算が可能になりますが、いくつもの異なるメモリ安全とセキュリティの問題が起こるおそれがあります。 +ある意味で、任意のポインタを参照外しする能力は行いうる操作のうち最も危険なもののひとつです。 +詳細は、[この本の生ポインタに関するセクション][rawpointers]を参照してください。 [rawpointers]: raw-pointers.html -## Call unsafe functions +## アンセーフ関数の呼び出し + + +この最後の能力は、`unsafe`の両面とともに働きます。 +すなわち、`unsafe`で印付けられた関数は、アンセーフブロックの内部からのみ呼び出すことができます。 + +この能力は強力で多彩です。 +Rustはいくらかの[compiler intrinsics][intrinsics]をアンセーフ関数として公開しており、また、いくつかのアンセーフ関数は安全性検査を回避することで、安全性とスピードを引き換えています。 + +繰り返しになりますが、アンセーフブロックと関数の内部で任意のことが _できる_ としても、それをすべきだということを意味しません。コンパイラは、あなたが不変量を守っているかのように動作しますから、注意してください! [intrinsics]: intrinsics.html diff --git a/TranslationTable.md b/TranslationTable.md index f636cfed..acb34944 100644 --- a/TranslationTable.md +++ b/TranslationTable.md @@ -10,6 +10,9 @@ | English | 日本語 |:-------------------------------|:------------- +| abort | アボート +| (lockの) acquire | 獲得 +| aggregate type | 合成型 | alignment | アラインメント | allocator | アロケータ | antipattern | アンチパターン @@ -18,45 +21,77 @@ | array | 配列 | assignment | 代入 | associated - | 関連- +| atomic | アトミック | attribute | アトリビュート | binary | バイナリ | binding | 束縛 | block | ブロック | borrowing | 借用 | bounds | 境界 +| bug | バグ | capture | キャプチャ +| case analysis | 場合分け +| channel | チャネル | closure | クロージャ | coercion | 型強制 +| combinator | コンビネータ | comma | カンマ +| compile-time error | コンパイル時エラー | compiler | コンパイラ +| composable | 合成可能 +| computer science | コンピュータサイエンス +| concurrency | 並行性 | constant | 定数 +| constructor | コンストラクタ +| continuous integration | 継続的インテグレーション | crate | クレート | dangling | ダングリング +| data race | データ競合 +| deadlock | デッドロック | declaration statement | 宣言文 | dereferencing | 参照外し +| destructor | デストラクタ | destructuring | 分配 | directive | ディレクティブ +| directory | ディレクトリ +| discriminant | 判別子 | distribution | 配布物 | diverge | ダイバージ | diverging | ダイバージング | documentation comment | ドキュメンテーションコメント | documentation test | ドキュメンテーションテスト | early return | 早期リターン +| empty tuple | 空タプル +| encode | エンコード | enum | 列挙型 +| equality | 等値性 +| ergonomic | エルゴノミック(人間にとって扱いやすいもの) +| error | エラー +| error handling | エラーハンドリング | expression statement | 式文 | feature | フィーチャ +| foreign | 他言語 +| free-standing function | フリースタンディングな関数 | generic parameter | ジェネリックパラメータ | generics | ジェネリクス +| glob | グロブ | growable | 伸張可能 +| handle | ハンドル +| hash | ハッシュ | identifier | 識別子 | immutable | イミュータブル +| implement | 実装する | initialize | 初期化する | input lifetime | 入力ライフタイム +| install | インストール +| installer | インストーラ | interpolate | インターポーレートする | interpolation | インターポーレーション -| keyword | キーワード | Intrinsics | Intrinsic +| key | キー +| keyword | キーワード | Lang Items | Lang Item +| leak | リーク | lending | 貸付け | library | ライブラリ | lifetime | ライフタイム @@ -64,47 +99,89 @@ | lifetime parameter | ライフタイムパラメータ | link | リンク | lint | リント +| mangling | マングリング | match | マッチ | memory | メモリ | method | メソッド | move | ムーブ -| mutable | ミュータブル | mutability | ミュータビリティ +| mutable | ミュータブル | mutable binding | ミュータブルな束縛 +| null | ヌル +| offline | オフライン +| opaque | オペーク +| open source | オープンソース +| option | オプション | output lifetime | 出力ライフタイム +| overflow | オーバーフロー | owner | 所有者 | ownership | 所有権 | panic | パニック +| parameter | パラメータ | parametric polymorphism | パラメトリック多相 +| parse | パース、パースする +| patch | パッチ | pattern | パターン | performance | パフォーマンス +| platform | プラットフォーム | pointer | ポインタ +| process | プロセス +| raw pointer | 生ポインタ | re-assignment | 再代入 | rebind | 再束縛 +| reference count | 参照カウント +| regression | リグレッション +| release | リリース +| (lockの) release | 解放 | return | 返す +| return type | リターン型 +| return value | 戻り値 +| safe | 安全 +| safety check | 安全性検査 | scope | スコープ +| scoped | スコープ化された +| script | スクリプト +| semantics | セマンティクス | shadow | 覆い隠す | shadowing | シャドーイング | signature | シグネチャ | signed | 符号付き | slice | スライス | slicing | スライシング +| standard library | 標準ライブラリ | string | 文字列 | string interpolation | 文字列インターポーレーション | struct | 構造体 | structure | ストラクチャ +| sum type | 直和型 | symbol | シンボル | syntactic sugar | 糖衣構文 | system | システム +| tagged union | タグ付き共用体 +| term | 項 +| thread-locality | スレッドローカル性 +| threadsafe | スレッドセーフ | tick | クオート | trait | トレイト -| type inference | 型推論 +| tuple | タプル +| type alias | 型エイリアス | type family | 型族 +| type inference | 型推論 +| type parameter | 型パラメータ +| uninstall | アンインストール +| unit 注: `()` の読み | ユニット | Universal Function Call Syntax | 共通の関数呼び出し構文 +| unsafe | アンセーフ | unsigned | 符号無し | unsized type | サイズ不定型 +| unwinding | 巻き戻し +| unwrap | アンラップ +| value constructor | 値コンストラクタ | variable | 変数 | variable binding | 変数束縛 +| variant | ヴァリアント | vector | ベクタ +| version | バージョン | warning | ウォーニング | wildcard | ワイルドカード +| wrapper | ラッパ diff --git a/public/1.6/book/README.html b/public/1.6/book/README.html index ee9c46bc..cad9050b 100644 --- a/public/1.6/book/README.html +++ b/public/1.6/book/README.html @@ -95,11 +95,11 @@
  • 4.25. クレートとモジュール
  • -
  • 4.26. `const`と`static` +
  • 4.26. `const` と `static`
  • 4.27. アトリビュート
  • -
  • 4.28. `type`エイリアス +
  • 4.28. `type` エイリアス
  • 4.29. 型間のキャスト
  • @@ -131,7 +131,7 @@
  • 5.5. イテレータ
  • -
  • 5.6. 並行 +
  • 5.6. 並行性
  • 5.7. エラーハンドリング
  • diff --git a/public/1.6/book/advanced-linking.html b/public/1.6/book/advanced-linking.html index 528fbcd7..0473124d 100644 --- a/public/1.6/book/advanced-linking.html +++ b/public/1.6/book/advanced-linking.html @@ -95,11 +95,11 @@
  • 4.25. クレートとモジュール
  • -
  • 4.26. `const`と`static` +
  • 4.26. `const` と `static`
  • 4.27. アトリビュート
  • -
  • 4.28. `type`エイリアス +
  • 4.28. `type` エイリアス
  • 4.29. 型間のキャスト
  • @@ -131,7 +131,7 @@
  • 5.5. イテレータ
  • -
  • 5.6. 並行 +
  • 5.6. 並行性
  • 5.7. エラーハンドリング
  • @@ -209,8 +209,8 @@

    -

    どのようにリンクをカスタマイズするかをrustcに指示するために、1つの方法があります。それは、link_argsアトリビュートを使うことです。 -このアトリビュートはexternブロックに適用され、生成物を作るときにリンカに渡したいフラグをそのまま指定します。 +

    どのようにリンクをカスタマイズするかを rustc に指示するために、1つの方法があります。それは、 link_args アトリビュートを使うことです。 +このアトリビュートは extern ブロックに適用され、生成物を作るときにリンカに渡したいフラグをそのまま指定します。 使い方の例は次のようになります。

    #![feature(link_args)] @@ -239,16 +239,16 @@

    -

    これはリンクを実行するための認められた方法ではないため、この機能は現在feature(link_args)ゲートによって隠されているということに注意しましょう。 -今はrustcがシステムリンカ(多くのシステムではgcc、MSVCではlink.exe)に渡すので、追加のコマンドライン引数を提供することには意味がありますが、それが今後もそうだとは限りません。 -将来、rustcがネイティブライブラリをリンクするためにLLVMを直接使うようになるかもしれませんし、そのような場合にはlink_argsは意味がなくなるでしょう。 -rustc-C link-args引数をつけることで、link_argsアトリビュートと同じような効果を得ることができます。

    +

    これはリンクを実行するための認められた方法ではないため、この機能は現在 feature(link_args) ゲートによって隠されているということに注意しましょう。 +今は rustc がシステムリンカ(多くのシステムでは gcc 、MSVCでは link.exe )に渡すので、追加のコマンドライン引数を提供することには意味がありますが、それが今後もそうだとは限りません。 +将来、 rustc がネイティブライブラリをリンクするためにLLVMを直接使うようになるかもしれませんし、そのような場合には link_args は意味がなくなるでしょう。 +rustc-C link-args 引数をつけることで、 link_args アトリビュートと同じような効果を得ることができます。

    -

    このアトリビュートは使わ ない ことが強く推奨されているので、代わりにもっと正式な#[link(...)]アトリビュートをexternブロックに使いましょう。

    +

    このアトリビュートは使わ ない ことが強く推奨されているので、代わりにもっと正式な #[link(...)] アトリビュートを extern ブロックに使いましょう。

    @@ -269,7 +269,7 @@

    Linux

    -

    デフォルトでは、Linux上の全てのRustのプログラムはシステムのlibcとその他のいくつものライブラリとリンクされます。 -GCCとglibc(Linuxにおける最も一般的なlibc)を使った64ビットLinuxマシンでの例を見てみましょう。

    +

    デフォルトでは、Linux上の全てのRustのプログラムはシステムの libc とその他のいくつものライブラリとリンクされます。 +GCCと glibc (Linuxにおける最も一般的な libc )を使った64ビットLinuxマシンでの例を見てみましょう。

    $ cat example.rs
     fn main() {}
    @@ -320,8 +320,8 @@ 

    Linux

    -

    スタティックリンクは代わりのlibcであるmuslによってサポートされています。 -以下の手順に従い、muslを有効にした独自バージョンのRustをコンパイルして独自のディレクトリにインストールすることができます。

    +

    スタティックリンクは代わりの libc である musl によってサポートされています。 +以下の手順に従い、 musl を有効にした独自バージョンのRustをコンパイルして独自のディレクトリにインストールすることができます。

    $ mkdir musldist
     $ PREFIX=$(pwd)/musldist
    @@ -369,7 +369,7 @@ 

    Linux

    -

    これでmuslが有効になったRustのビルドが手に入りました! +

    これで musl が有効になったRustのビルドが手に入りました! 独自のプレフィックスを付けてインストールしたので、試しに実行するときにはシステムがバイナリと適切なライブラリを見付けられることを確かめなければなりません。

    $ export PATH=$PREFIX/bin:$PATH
    @@ -402,8 +402,8 @@ 

    Linux

    -

    cargo build--targetオプションを受け付けるので、あなたのクレートも普通にビルドできるはずです。 -ただし、リンクする前にネイティブライブラリをmusl向けにリコンパイルする必要はあるかもしれません。

    +

    cargo build--target オプションを受け付けるので、あなたのクレートも普通にビルドできるはずです。 +ただし、リンクする前にネイティブライブラリを musl 向けにリコンパイルする必要はあるかもしれません。