From 388afb314a81d5bb419e3dd907f1884cafe98151 Mon Sep 17 00:00:00 2001 From: Pocket7878 Date: Mon, 22 Feb 2016 00:10:22 +0900 Subject: [PATCH 1/7] Start translation. --- 1.6/ja/book/closures.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/1.6/ja/book/closures.md b/1.6/ja/book/closures.md index 7d4452a4..c8b6e0c6 100644 --- a/1.6/ja/book/closures.md +++ b/1.6/ja/book/closures.md @@ -1,4 +1,5 @@ -% Closures + +% クロージャ Sometimes it is useful to wrap up a function and _free variables_ for better clarity and reuse. The free variables that can be used come from the From 70b09bf651b7f6fa5540cf2a156db39580c55714 Mon Sep 17 00:00:00 2001 From: Pocket7878 Date: Mon, 22 Feb 2016 10:52:46 +0900 Subject: [PATCH 2/7] Inprogress --- 1.6/ja/book/closures.md | 75 ++++++++++++++++++++++++++--------------- 1 file changed, 48 insertions(+), 27 deletions(-) diff --git a/1.6/ja/book/closures.md b/1.6/ja/book/closures.md index c8b6e0c6..925ecd1c 100644 --- a/1.6/ja/book/closures.md +++ b/1.6/ja/book/closures.md @@ -1,15 +1,20 @@ - % クロージャ + -Sometimes it is useful to wrap up a function and _free variables_ for better -clarity and reuse. The free variables that can be used come from the -enclosing scope and are ‘closed over’ when used in the function. From this, we -get the name ‘closures’ and Rust provides a really great implementation of -them, as we’ll see. + + + + + +しばしば、関数と _自由変数_ と一つにまとめておくことがコードの明確さや再利用の役に立つことが有ります。 +自由変数は外部のスコープから来て、関数中で使われるときに「閉じ込め」られます。 +このことから、これを「クロージャ」と呼びRustはこれから見ていくようにクロージャの非常に良い実装を提供しています。 -# Syntax + +# 構文 -Closures look like this: + +クロージャは以下のような見た目です: ```rust let plus_one = |x: i32| x + 1; @@ -17,10 +22,14 @@ let plus_one = |x: i32| x + 1; assert_eq!(2, plus_one(1)); ``` -We create a binding, `plus_one`, and assign it to a closure. The closure’s -arguments go between the pipes (`|`), and the body is an expression, in this -case, `x + 1`. Remember that `{ }` is an expression, so we can have multi-line -closures too: + + + + +束縛 `plus_one` を作成し、クロージャをアサインしています。 +クロージャの引数はパイプ( `|` )の間に書きます、そしてクロージャの本体は式です、 +この場合は `x + 1` がそれに当たります。 +`{ }` が式であることを思い出して下さい、 `{ }` が式であるため、複数行のクロージャを作成することも可能です: ```rust let plus_two = |x| { @@ -35,10 +44,13 @@ let plus_two = |x| { assert_eq!(4, plus_two(2)); ``` -You’ll notice a few things about closures that are a bit different from regular -named functions defined with `fn`. The first is that we did not need to -annotate the types of arguments the closure takes or the values it returns. We -can: + + + + +いくつかクロージャと通常の `fn` で定義される関数との違いに気がつくでしょう。 +一つ目はクロージャの引数や返り値の型を示す必要が無い事です。 +型を以下のように示すこともできます: ```rust let plus_one = |x: i32| -> i32 { x + 1 }; @@ -46,15 +58,22 @@ let plus_one = |x: i32| -> i32 { x + 1 }; assert_eq!(2, plus_one(1)); ``` -But we don’t have to. Why is this? Basically, it was chosen for ergonomic -reasons. While specifying the full type for named functions is helpful with -things like documentation and type inference, the full type signatures of -closures are rarely documented since they’re anonymous, and they don’t cause -the kinds of error-at-a-distance problems that inferring named function types -can. - -The second is that the syntax is similar, but a bit different. I’ve added -spaces here for easier comparison: + + + + + + +しかし、このように型を示す必要はありません。 +なぜでしょう?一言で言えば、これは使いやすさのためです。 +名前の有る関数の型を全て指定するのはドキュメンテーションや型推論の役に立つとしても、 +クロージャの型は示されません、これはクロージャたちが匿名であり、 +さらに名前付きの関数が引き起こすと思われるような遠くで発生するエラーの要因ともならないためです。 + + + +通常の関数との違いの二つ目は、構文は似ていますが、ほんの少し違うという点です。 +比較がしやすいようにスペースを適宜つけて以下に示しています: ```rust fn plus_one_v1 (x: i32) -> i32 { x + 1 } @@ -62,9 +81,11 @@ let plus_one_v2 = |x: i32| -> i32 { x + 1 }; let plus_one_v3 = |x: i32| x + 1 ; ``` -Small differences, but they’re similar. + +小さな違いは有りますが似ています。 -# Closures and their environment + +# クロージャとクロージャの環境 The environment for a closure can include bindings from its enclosing scope in addition to parameters and local bindings. It looks like this: From ce65a735542daf03465da4d82fc4d66924b70cc6 Mon Sep 17 00:00:00 2001 From: Pocket7878 Date: Wed, 24 Feb 2016 15:22:46 +0900 Subject: [PATCH 3/7] Inprogress --- 1.6/ja/book/closures.md | 265 ++++++++++++++++++++++++++-------------- 1 file changed, 170 insertions(+), 95 deletions(-) diff --git a/1.6/ja/book/closures.md b/1.6/ja/book/closures.md index 925ecd1c..503ce971 100644 --- a/1.6/ja/book/closures.md +++ b/1.6/ja/book/closures.md @@ -87,8 +87,10 @@ let plus_one_v3 = |x: i32| x + 1 ; # クロージャとクロージャの環境 -The environment for a closure can include bindings from its enclosing scope in -addition to parameters and local bindings. It looks like this: + + +クロージャの環境はクロージャを囲んでいるスコープ中の束縛を引数やローカルな束縛に追加で含むことが可能です。 +例えば以下のようになります: ```rust let num = 5; @@ -97,9 +99,13 @@ let plus_num = |x: i32| x + num; assert_eq!(10, plus_num(5)); ``` -This closure, `plus_num`, refers to a `let` binding in its scope: `num`. More -specifically, it borrows the binding. If we do something that would conflict -with that binding, we get an error. Like this one: + + + +クロージャ `plus_num` はスコープ内の `let` 束縛 `num` を参照しています。 +より厳密に言うと、クロージャ `plus_num` は束縛 `num` を借用しています。 +もし、この束縛と衝突する処理を行うとエラーが発生します。 +例えば、以下のようなコードは: ```rust,ignore let mut num = 5; @@ -108,7 +114,8 @@ let plus_num = |x: i32| x + num; let y = &mut num; ``` -Which errors with: + +以下のエラーを発生させます: ```text error: cannot borrow `num` as mutable because it is also borrowed as immutable @@ -129,22 +136,28 @@ fn main() { ^ ``` -A verbose yet helpful error message! As it says, we can’t take a mutable borrow -on `num` because the closure is already borrowing it. If we let the closure go -out of scope, we can: + + + +冗長ですが役に立つエラーメッセージです! +エラーが示しているように、クロージャが既に `num` を借用しているために、 `num` の変更可能な借用を取得することはできません。 +もしクロージャがスコープ外になるようにした場合以下のようにできます: ```rust let mut num = 5; { let plus_num = |x: i32| x + num; -} // plus_num goes out of scope, borrow of num ends +# // } // plus_num goes out of scope, borrow of num ends +} // plus_numがスコープ外に出て、numの借用が終わります let y = &mut num; ``` -If your closure requires it, however, Rust will take ownership and move -the environment instead. This doesn’t work: + + +もしクロージャが必要としたならば、Rustは所有権を取り、かわりに環境をムーブします。 +以下のコードは動作しません: ```rust,ignore let nums = vec![1, 2, 3]; @@ -154,7 +167,8 @@ let takes_nums = || nums; println!("{:?}", nums); ``` -We get this error: + +このコードは以下の様なエラーを発生させます: ```text note: `nums` moved into closure environment here because it has type @@ -163,14 +177,19 @@ let takes_nums = || nums; ^~~~~~~ ``` -`Vec` has ownership over its contents, and therefore, when we refer to it -in our closure, we have to take ownership of `nums`. It’s the same as if we’d -passed `nums` to a function that took ownership of it. + + + +`Vec` は `Vec` の要素に対する所有権を持っています、 +それゆえそれらの要素をクロージャ内で参照した場合、 `num` の所有権を取ることになります。 +これは `num` の所有権を取るを関数に渡した場合と同じです。 -## `move` closures + +## `move` クロージャ -We can force our closure to take ownership of its environment with the `move` -keyword: + + +`move` キーワードを用いることで、クロージャに環境の所有権を取得することを強制することができます。 ```rust let num = 5; @@ -178,9 +197,13 @@ let num = 5; let owns_num = move |x: i32| x + num; ``` -Now, even though the keyword is `move`, the variables follow normal move semantics. -In this case, `5` implements `Copy`, and so `owns_num` takes ownership of a copy -of `num`. So what’s the difference? + + + +今や、 `move` というキーワードにもかかわらず、変数は通常のmoveのセマンティクスに従います。 +この場合、 `5` は `Copy` を実装しています、 +そのため `owns_num` は `num` のコピーの所有権を取得します。 +では、なにが異なるのでしょうか? ```rust let mut num = 5; @@ -194,12 +217,15 @@ let mut num = 5; assert_eq!(10, num); ``` -So in this case, our closure took a mutable reference to `num`, and then when -we called `add_num`, it mutated the underlying value, as we’d expect. We also -needed to declare `add_num` as `mut` too, because we’re mutating its -environment. + + + + +このケースでは、クロージャは `num` の変更可能な参照を取得し、 `add_num` を呼び出した時予想したように `num` の値を変更します。 +`add_num` を同様に `mut` として宣言する必要があります、なぜならクロージャ `add_num` はその環境を変更するためです。 -If we change to a `move` closure, it’s different: + +もしクロージャを `move` に変更した場合、結果は変化します: ```rust let mut num = 5; @@ -213,36 +239,53 @@ let mut num = 5; assert_eq!(5, num); ``` -We only get `5`. Rather than taking a mutable borrow out on our `num`, we took -ownership of a copy. - -Another way to think about `move` closures: they give a closure its own stack -frame. Without `move`, a closure may be tied to the stack frame that created -it, while a `move` closure is self-contained. This means that you cannot -generally return a non-`move` closure from a function, for example. - -But before we talk about taking and returning closures, we should talk some -more about the way that closures are implemented. As a systems language, Rust -gives you tons of control over what your code does, and closures are no -different. - -# Closure implementation - -Rust’s implementation of closures is a bit different than other languages. They -are effectively syntax sugar for traits. You’ll want to make sure to have read -the [traits chapter][traits] before this one, as well as the chapter on [trait -objects][trait-objects]. + + +結果は `5` になります。`num` の変更可能な借用を取得するよりもむしろ、コピーの所有権を取得します。 + + + + + +`move` クロージャについて考えるその他の方法は: スタックフレームをクロージャに与えるます。 +`move` がなかった場合、クロージャはクロージャを作成したスタックフレームと結合されます、 +`move` クロージャは自己従属しているとしても。 +これは一般的に、`move` でないクロージャを関数から返すことはできないという事を意味しています。 + + + + + +クロージャを引数に取ったり、帰り値として返したりということについて説明する間に、 +クロージャの実装についてもう少し説明する必要があります。 +システム言語としてRustはコードの動作についてコントロールする方法を大量に提供しています、 +そしてそれはクロージャも例外ではありません。 + + +# クロージャの実装 + + + + + +Rustにおけるクロージャの実装は他の言事は少し異なります。 +クロージャは効率的なトレイトへの糖衣構文となっています。 +[トレイト][traits] や [トレイトオブジェクト][trait-objects] についてのチャプターを学ぶ前に読みたくなるでしょう。 [traits]: traits.html [trait-objects]: trait-objects.html -Got all that? Good. + +よろしいですか? では、続きを説明いたします。 -The key to understanding how closures work under the hood is something a bit -strange: Using `()` to call a function, like `foo()`, is an overloadable -operator. From this, everything else clicks into place. In Rust, we use the -trait system to overload operators. Calling functions is no different. We have -three separate traits to overload with: + + + + + +クロージャの内部的な動作を理解するための鍵は少し奇妙です: 関数を呼び出すのに `()` を 例えば `foo()` の様に使いますが、これはオーバーロード可能な演算子です。 +これから、残りの全てを正しく理解することができます。Rustでは、トレイトを演算子のオーバーロードに利用します。 +関数の予備だしも例外ではありません。3つのオーバーロードするトレイトが存在します: ```rust # mod foo { @@ -262,24 +305,37 @@ pub trait FnOnce { # } ``` -You’ll notice a few differences between these traits, but a big one is `self`: -`Fn` takes `&self`, `FnMut` takes `&mut self`, and `FnOnce` takes `self`. This -covers all three kinds of `self` via the usual method call syntax. But we’ve -split them up into three traits, rather than having a single one. This gives us -a large amount of control over what kind of closures we can take. - -The `|| {}` syntax for closures is sugar for these three traits. Rust will -generate a struct for the environment, `impl` the appropriate trait, and then -use it. - -# Taking closures as arguments - -Now that we know that closures are traits, we already know how to accept and -return closures: just like any other trait! - -This also means that we can choose static vs dynamic dispatch as well. First, -let’s write a function which takes something callable, calls it, and returns -the result: + + + + + +これらのトレイトの間の僅かな違いに気がつくことでしょう、しかし大きな違いは `self` についてです: +`Fn` は `&self` を引数に取ります、 `FnMut` は `&mut self` を引数に取ります、そして `FnOnce` は `self` を引数に取ります。 +これは通常のメソッド呼び出しにおける `self` のすべての種類をカバーしています。 +しかし、これら `self` の各種類を一つの大きなトレイトにまとめるのではなく異なるトレイトに分けています。 +このようにすることで、どのような種類のクロージャを取るのかについて多くをコントロールすることができます。 + + + + +クロージャに対する構文 `|| {}` は上述の3つのトレイトへの糖衣構文です。 +Rustは環境の構造体を作成し、 適切なトレイトを `impl` し、それを利用します。 + + + +# クロージャを引数に取る + + + +クロージャが実際にはトレイトであることを知ったので、 +クロージャをどのように引数として取ったり返り値として返せばいいかわかりました: 通常のトレイトと同様に行うのです! + + + + +これは、静的なディスパッチと動的なディスパッチを洗濯することができるという事も意味しています。 +手始めに呼び出し可能な何かを引数にとりそれを呼び出し、その結果を返す関数を書いてみましょう: ```rust fn call_with_one(some_closure: F) -> i32 @@ -293,10 +349,13 @@ let answer = call_with_one(|x| x + 2); assert_eq!(3, answer); ``` -We pass our closure, `|x| x + 2`, to `call_with_one`. It just does what it -suggests: it calls the closure, giving it `1` as an argument. + + +クロージャ `|x| x + 2` を `call_with_one` に渡しました。 +これは `call_with_one` という関数名から推測される処理を行います: クロージャに `1` を与えて呼び出します。 -Let’s examine the signature of `call_with_one` in more depth: + +`call_with_one` のシグネチャを詳細に見ていきましょう: ```rust fn call_with_one(some_closure: F) -> i32 @@ -304,8 +363,10 @@ fn call_with_one(some_closure: F) -> i32 # some_closure(1) } ``` -We take one parameter, and it has the type `F`. We also return a `i32`. This part -isn’t interesting. The next part is: + + +型 `F` を持つ引数を1つ取り、返り値として `i32` を返します。 +この部分は特に注目には値しません。次の部分は: ```rust # fn call_with_one(some_closure: F) -> i32 @@ -313,20 +374,30 @@ isn’t interesting. The next part is: # some_closure(1) } ``` -Because `Fn` is a trait, we can bound our generic with it. In this case, our -closure takes a `i32` as an argument and returns an `i32`, and so the generic -bound we use is `Fn(i32) -> i32`. - -There’s one other key point here: because we’re bounding a generic with a -trait, this will get monomorphized, and therefore, we’ll be doing static -dispatch into the closure. That’s pretty neat. In many languages, closures are -inherently heap allocated, and will always involve dynamic dispatch. In Rust, -we can stack allocate our closure environment, and statically dispatch the -call. This happens quite often with iterators and their adapters, which often -take closures as arguments. - -Of course, if we want dynamic dispatch, we can get that too. A trait object -handles this case, as usual: + + + +`Fn` がトレイトであるために、ジェネリックの境界として `Fn` を指定する事ができます。 +この場合はクロージャは `i32` を引数として取り、 `i32` を返します、そのため +ジェネリックの境界として `Fn(i32) -> i32` を指定子ます。 + + + + + + + + +キーポイントがここにもあります: ジェネリックをトレイトで境界を指定したために、この関数は単相化されます、 +それゆえ、静的なディスパッチをクロージャに対して行います。これはとても素敵です。 +多くの言語では、クロージャは常にヒープにアロケートされ、常に動的ディスパッチが行われます。 +Rustではスタックにクロージャの環境をアロケーションし、呼び出しを静的にディスパッチすることができます。 +これは比較的頻繁にクロージャを引数として取るイテレータやそれらのアダプタにおいて発生します。 + + + +もちろん、動的ディスパッチ行いたいときは、そのようにすることもできます。 +そのような場合もトレイトオブジェクトが通常どうりに対応します: ```rust fn call_with_one(some_closure: &Fn(i32) -> i32) -> i32 { @@ -338,14 +409,18 @@ let answer = call_with_one(&|x| x + 2); assert_eq!(3, answer); ``` -Now we take a trait object, a `&Fn`. And we have to make a reference -to our closure when we pass it to `call_with_one`, so we use `&||`. + + +トレイトオブジェクトを引数に取るようになり、 +また `call_with_one` にクロージャを渡すときに参照を利用するようにしました、 +そのため `&||` を利用しています。 -# Function pointers and closures + +# 関数ポインタとクロージャ -A function pointer is kind of like a closure that has no environment. As such, -you can pass a function pointer to any function expecting a closure argument, -and it will work: + + + ```rust fn call_with_one(some_closure: &Fn(i32) -> i32) -> i32 { From 59f12c5db19c75c373d1487169da73940577a6f4 Mon Sep 17 00:00:00 2001 From: Pocket7878 Date: Wed, 24 Feb 2016 19:29:54 +0900 Subject: [PATCH 4/7] More translation --- 1.6/ja/book/closures.md | 51 ++++++++++++++++++++++++++--------------- 1 file changed, 33 insertions(+), 18 deletions(-) diff --git a/1.6/ja/book/closures.md b/1.6/ja/book/closures.md index 503ce971..e804cc31 100644 --- a/1.6/ja/book/closures.md +++ b/1.6/ja/book/closures.md @@ -421,6 +421,8 @@ assert_eq!(3, answer); +関数ポインタは環境を持たないクロージャのようなものです。 +そのため、クロージャを引数として期待している関数に関数ポインタを渡すことができます。 ```rust fn call_with_one(some_closure: &Fn(i32) -> i32) -> i32 { @@ -438,19 +440,24 @@ let answer = call_with_one(&f); assert_eq!(2, answer); ``` -In this example, we don’t strictly need the intermediate variable `f`, -the name of the function works just fine too: + + +この例では、中間の変数 `f` が必ず必要なわけではありません、関数名を指定することでもきちんと動作します: ```ignore let answer = call_with_one(&add_one); ``` -# Returning closures + +# クロージャを返す -It’s very common for functional-style code to return closures in various -situations. If you try to return a closure, you may run into an error. At -first, it may seem strange, but we’ll figure it out. Here’s how you’d probably -try to return a closure from a function: + + + + +関数を用いたスタイルのコードでは、クロージャを返す事は非常によく見られます。 +もし、クロージャを返す事を試みた場合、エラーが発生します。これは一見奇妙に思われますが、理解することができます。 +以下は、関数からクロージャを返すことを試みた場合のコードです: ```rust,ignore fn factory() -> (Fn(i32) -> i32) { @@ -465,7 +472,8 @@ let answer = f(1); assert_eq!(6, answer); ``` -This gives us these long, related errors: + +このコードは以下の長いエラーを発生させます: ```text error: the trait `core::marker::Sized` is not implemented for the type @@ -483,11 +491,15 @@ let f = factory(); ^ ``` -In order to return something from a function, Rust needs to know what -size the return type is. But since `Fn` is a trait, it could be various -things of various sizes: many different types can implement `Fn`. An easy -way to give something a size is to take a reference to it, as references -have a known size. So we’d write this: + + + + + +関数から何かを返すにあたって、Rustは返り値の型のサイズを知る必要があります。 +しかし、 `Fn` はトレイトであるため、そのサイズや種類は多岐にわたることになります: 多くの異なる型が `Fn` を実装できます。 +何かにサイズを与える簡単な方法は、それに対する参照を取得する方法です、参照は既知のサイズを持っています。 +そのため、以下のように書くことができます: ```rust,ignore fn factory() -> &(Fn(i32) -> i32) { @@ -502,7 +514,8 @@ let answer = f(1); assert_eq!(6, answer); ``` -But we get another error: + +しかし、他のエラーが発生してしまいます: ```text error: missing lifetime specifier [E0106] @@ -510,10 +523,12 @@ fn factory() -> &(Fn(i32) -> i32) { ^~~~~~~~~~~~~~~~~ ``` -Right. Because we have a reference, we need to give it a lifetime. But -our `factory()` function takes no arguments, so -[elision](lifetimes.html#lifetime-elision) doesn’t kick in here. Then what -choices do we have? Try `'static`: + + + + +ふむ。これはリファレンスを利用したため、ライフタイムを指定する必要が有ることによります。 +しかし、 `factory()` 関数は引数を何も取りません、そのため [] ```rust,ignore fn factory() -> &'static (Fn(i32) -> i32) { From 8cc1621435a89b38d10ce26dcc1df1a456e90c50 Mon Sep 17 00:00:00 2001 From: Pocket7878 Date: Fri, 26 Feb 2016 10:39:21 +0900 Subject: [PATCH 5/7] Roughly Translated. --- 1.6/ja/book/closures.md | 70 ++++++++++++++++++++++++++++------------- 1 file changed, 48 insertions(+), 22 deletions(-) diff --git a/1.6/ja/book/closures.md b/1.6/ja/book/closures.md index e804cc31..70b2445b 100644 --- a/1.6/ja/book/closures.md +++ b/1.6/ja/book/closures.md @@ -528,7 +528,9 @@ fn factory() -> &(Fn(i32) -> i32) { ふむ。これはリファレンスを利用したため、ライフタイムを指定する必要が有ることによります。 -しかし、 `factory()` 関数は引数を何も取りません、そのため [] +しかし、 `factory()` 関数は引数を何も取りません、 +そのため [elision](lifetimes.html#lifetime-elision) は実施されません。 +では、どのような選択肢が有るのでしょうか? `'static` を試してみましょう: ```rust,ignore fn factory() -> &'static (Fn(i32) -> i32) { @@ -543,7 +545,8 @@ let answer = f(1); assert_eq!(6, answer); ``` -But we get another error: + +しかし、以下の別のエラーが発生します: ```text error: mismatched types: @@ -556,18 +559,31 @@ error: mismatched types: ``` -This error is letting us know that we don’t have a `&'static Fn(i32) -> i32`, -we have a `[closure@:7:9: 7:20]`. Wait, what? + + +このエラーは `&'static Fn(i32) -> i32` ではなく、 + `[closure@:7:9: 7:20]` を使っているという事を伝えています。 +しかし、これは一体何でしょう? + -Because each closure generates its own environment `struct` and implementation -of `Fn` and friends, these types are anonymous. They exist just solely for -this closure. So Rust shows them as `closure@`, rather than some -autogenerated name. + + + + +それぞれのクロージャはそれぞれの環境の `struct` を生成し、 `Fn` やその仲間を実装するため、 +それぞれの型は匿名となります。それぞれの型はそのクロージャのためだけに存在します。 +そのためRustはそれらの型を自動生成された名前の代わりに `closure@` と示します。 + + + + + +このエラーはその他にも返り値の型が参照であることを期待しているが、 +上のコードではそうではないという事についても指摘しています。 +そのうえ、直接的に `'static` ライフタイムをオブジェクトに割り当てることはできません。 +そのため、`Fn` をボックス化することで「トレイトオブジェクト」を返すという方法を取ります。 +そうすると、動作するように成るまであと一歩のところまで来ます: -The error also points out that the return type is expected to be a reference, -but what we are trying to return is not. Further, we cannot directly assign a -`'static` lifetime to an object. So we'll take a different approach and return -a ‘trait object’ by `Box`ing up the `Fn`. This _almost_ works: ```rust,ignore fn factory() -> Box i32> { @@ -583,7 +599,8 @@ assert_eq!(6, answer); # } ``` -There’s just one last problem: + +最後に残されたエラーは以下のとおりです: ```text error: closure may outlive the current function, but it borrows `num`, @@ -592,12 +609,19 @@ Box::new(|x| x + num) ^~~~~~~~~~~ ``` -Well, as we discussed before, closures borrow their environment. And in this -case, our environment is based on a stack-allocated `5`, the `num` variable -binding. So the borrow has a lifetime of the stack frame. So if we returned -this closure, the function call would be over, the stack frame would go away, -and our closure is capturing an environment of garbage memory! With one last -fix, we can make this work: + + + + + + +以前説明したように、クロージャはその環境を借用します。 +今回の場合は、環境はスタックにアロケートされた `5` に束縛された `num` からできていることから、 +借用はスタックフレームと同じライフタイムを持っています。 +そのため、もしこのクロージャを返り値とした場合、 + `factory()` 関数の処理が完了し、スタックフレームは取り除かれクロージャはゴミとなったメモリを参照することになります! +上のコードに最後の修正を施すことによって動作させることができるようになります: + ```rust fn factory() -> Box i32> { @@ -613,6 +637,8 @@ assert_eq!(6, answer); # } ``` -By making the inner closure a `move Fn`, we create a new stack frame for our -closure. By `Box`ing it up, we’ve given it a known size, and allowing it to -escape our stack frame. + + + +内部のクロージャを `move Fn` にすることで、新しいスタックフレームをクロージャのために生成します。 +そしてボックス化することによって、既知のサイズとなり、現在のスタックフレームから抜けることが可能になります。 From 0be181032e0cf1dc591b3485cbe3b18a4a6ed8c5 Mon Sep 17 00:00:00 2001 From: Pocket7878 Date: Mon, 29 Feb 2016 21:48:19 +0900 Subject: [PATCH 6/7] Little fix translation. --- 1.6/ja/book/closures.md | 148 +++++++++++++++++++++------------------- 1 file changed, 76 insertions(+), 72 deletions(-) diff --git a/1.6/ja/book/closures.md b/1.6/ja/book/closures.md index 70b2445b..4be9f9e1 100644 --- a/1.6/ja/book/closures.md +++ b/1.6/ja/book/closures.md @@ -6,9 +6,10 @@ -しばしば、関数と _自由変数_ と一つにまとめておくことがコードの明確さや再利用の役に立つことが有ります。 +しばしば、関数と _自由変数_ と一つにまとめておくことがコードの明確さや再利用に役立つ場合が有ります。 自由変数は外部のスコープから来て、関数中で使われるときに「閉じ込め」られます。 -このことから、これを「クロージャ」と呼びRustはこれから見ていくようにクロージャの非常に良い実装を提供しています。 +そのためそのようなまとまりを「クロージャ」と呼び、 +Rustはこれから見ていくようにクロージャの非常に良い実装を提供しています。 # 構文 @@ -26,10 +27,10 @@ assert_eq!(2, plus_one(1)); -束縛 `plus_one` を作成し、クロージャをアサインしています。 +束縛 `plus_one` を作成し、クロージャを代入しています。 クロージャの引数はパイプ( `|` )の間に書きます、そしてクロージャの本体は式です、 この場合は `x + 1` がそれに当たります。 -`{ }` が式であることを思い出して下さい、 `{ }` が式であるため、複数行のクロージャを作成することも可能です: +`{ }` が式であることを思い出して下さい、 そのため複数行のクロージャを作成することも可能です: ```rust let plus_two = |x| { @@ -48,9 +49,9 @@ assert_eq!(4, plus_two(2)); -いくつかクロージャと通常の `fn` で定義される関数との違いに気がつくでしょう。 -一つ目はクロージャの引数や返り値の型を示す必要が無い事です。 -型を以下のように示すこともできます: +いくつかクロージャと通常の `fn` で定義される関数との間の違いに気がつくことでしょう。 +一つ目はクロージャの引数や返り値の型を示す必要が無いことです。 +型を以下のように示すことも可能です: ```rust let plus_one = |x: i32| -> i32 { x + 1 }; @@ -66,14 +67,14 @@ assert_eq!(2, plus_one(1)); しかし、このように型を示す必要はありません。 なぜでしょう?一言で言えば、これは使いやすさのためです。 -名前の有る関数の型を全て指定するのはドキュメンテーションや型推論の役に立つとしても、 -クロージャの型は示されません、これはクロージャたちが匿名であり、 -さらに名前付きの関数が引き起こすと思われるような遠くで発生するエラーの要因ともならないためです。 +名前の有る関数の型を全て指定するのはドキュメンテーションや型推論の役に立ちますが、 +クロージャの型は殆ど示されません、これはクロージャたちが匿名であり、 +さらに名前付きの関数が引き起こすと思われるような定義から離れた箇所で発生するエラーの要因ともならないためです。 -通常の関数との違いの二つ目は、構文は似ていますが、ほんの少し違うという点です。 -比較がしやすいようにスペースを適宜つけて以下に示しています: +通常の関数との違いの二つ目は、構文が大部分は似ていますがほんの少しだけ違うという点です。 +比較がしやすいようにスペースを適宜補って以下に示します: ```rust fn plus_one_v1 (x: i32) -> i32 { x + 1 } @@ -82,14 +83,14 @@ let plus_one_v3 = |x: i32| x + 1 ; ``` -小さな違いは有りますが似ています。 +小さな違いは有りますが殆どの部分は同じです。 # クロージャとクロージャの環境 -クロージャの環境はクロージャを囲んでいるスコープ中の束縛を引数やローカルな束縛に追加で含むことが可能です。 +クロージャの環境は引数やローカルな束縛に加えてクロージャを囲んでいるスコープ中の束縛を含むことができます。 例えば以下のようになります: ```rust @@ -103,9 +104,9 @@ assert_eq!(10, plus_num(5)); クロージャ `plus_num` はスコープ内の `let` 束縛 `num` を参照しています。 -より厳密に言うと、クロージャ `plus_num` は束縛 `num` を借用しています。 +より厳密に言うと、クロージャ `plus_num` は束縛を借用しています。 もし、この束縛と衝突する処理を行うとエラーが発生します。 -例えば、以下のようなコードは: +例えば、以下のようなコードでは: ```rust,ignore let mut num = 5; @@ -140,7 +141,8 @@ fn main() { 冗長ですが役に立つエラーメッセージです! -エラーが示しているように、クロージャが既に `num` を借用しているために、 `num` の変更可能な借用を取得することはできません。 +エラーが示しているように、クロージャが既に `num` を借用しているために、 +`num` の変更可能な借用を取得することはできません。 もしクロージャがスコープ外になるようにした場合以下のようにできます: ```rust @@ -156,8 +158,8 @@ let y = &mut num; -もしクロージャが必要としたならば、Rustは所有権を取り、かわりに環境をムーブします。 -以下のコードは動作しません: +もしクロージャが `num` の変更可能な借用を要求した場合、Rustは借用する代わりに環境の所有権を取りムーブします。 +そのため、以下のコードは動作しません: ```rust,ignore let nums = vec![1, 2, 3]; @@ -180,9 +182,9 @@ let takes_nums = || nums; -`Vec` は `Vec` の要素に対する所有権を持っています、 +`Vec` はその要素に対する所有権を持っています、 それゆえそれらの要素をクロージャ内で参照した場合、 `num` の所有権を取ることになります。 -これは `num` の所有権を取るを関数に渡した場合と同じです。 +これは `num`を `num` の所有権を取る関数に渡した場合と同じです。 ## `move` クロージャ @@ -200,7 +202,7 @@ let owns_num = move |x: i32| x + num; -今や、 `move` というキーワードにもかかわらず、変数は通常のmoveのセマンティクスに従います。 +このようにすると `move` というキーワードにもかかわらず、変数は通常のmoveのセマンティクスに従います。 この場合、 `5` は `Copy` を実装しています、 そのため `owns_num` は `num` のコピーの所有権を取得します。 では、なにが異なるのでしょうか? @@ -221,11 +223,11 @@ assert_eq!(10, num); -このケースでは、クロージャは `num` の変更可能な参照を取得し、 `add_num` を呼び出した時予想したように `num` の値を変更します。 -`add_num` を同様に `mut` として宣言する必要があります、なぜならクロージャ `add_num` はその環境を変更するためです。 +このケースでは、クロージャは `num` の変更可能な参照を取得し、 `add_num` を呼び出した時、期待通りに `num` の値を変更します。 +またクロージャ `add_num` はその環境を変更するため `mut` として宣言する必要があります。 -もしクロージャを `move` に変更した場合、結果は変化します: +もしクロージャを `move` に変更した場合、結果が異なります: ```rust let mut num = 5; @@ -241,23 +243,22 @@ assert_eq!(5, num); -結果は `5` になります。`num` の変更可能な借用を取得するよりもむしろ、コピーの所有権を取得します。 +結果は `5` になります。 +`num` の変更可能な借用を取得するのではなく、 `num` のコピーの所有権を取得します。 -`move` クロージャについて考えるその他の方法は: スタックフレームをクロージャに与えるます。 -`move` がなかった場合、クロージャはクロージャを作成したスタックフレームと結合されます、 -`move` クロージャは自己従属しているとしても。 -これは一般的に、`move` でないクロージャを関数から返すことはできないという事を意味しています。 +`move` クロージャを捉えるもう一つの観点は: `move` クロージャは独自のスタックフレームを持っているという点です。 +`move` クロージャは自己従属していますが、 `move` でないクロージャはクロージャを作成したスタックフレームと紐付いています。 +これは一般的に、`move` でないクロージャを関数から返すことはできないということを意味しています。 -クロージャを引数に取ったり、帰り値として返したりということについて説明する間に、 -クロージャの実装についてもう少し説明する必要があります。 +クロージャを引数や返り値にすることについて説明する間に、クロージャの実装についてもう少し説明する必要があります。 システム言語としてRustはコードの動作についてコントロールする方法を大量に提供しています、 そしてそれはクロージャも例外ではありません。 @@ -268,9 +269,9 @@ assert_eq!(5, num); -Rustにおけるクロージャの実装は他の言事は少し異なります。 -クロージャは効率的なトレイトへの糖衣構文となっています。 -[トレイト][traits] や [トレイトオブジェクト][trait-objects] についてのチャプターを学ぶ前に読みたくなるでしょう。 +Rustにおけるクロージャの実装は他の言語とは少し異なります。 +Rustにおけるクロージャは効率的なトレイトへの糖衣構文です。 +続きの説明を読む前に [トレイト][traits] や [トレイトオブジェクト][trait-objects] についてのチャプターを学ぶ前に読みたくなるでしょう。 [traits]: traits.html [trait-objects]: trait-objects.html @@ -283,9 +284,11 @@ Rustにおけるクロージャの実装は他の言事は少し異なります -クロージャの内部的な動作を理解するための鍵は少し奇妙です: 関数を呼び出すのに `()` を 例えば `foo()` の様に使いますが、これはオーバーロード可能な演算子です。 -これから、残りの全てを正しく理解することができます。Rustでは、トレイトを演算子のオーバーロードに利用します。 -関数の予備だしも例外ではありません。3つのオーバーロードするトレイトが存在します: +クロージャの内部的な動作を理解するための鍵は少し変わっています: 関数を呼び出すのに `()` を 例えば `foo()` の様に使いますが、この `()` はオーバーロード可能な演算子です。 +この事実から残りの全てを正しく理解することができます。 +Rustでは、トレイトを演算子のオーバーロードに利用します。 +それは関数の呼び出しも例外ではありません。 +`()` をオーバーロードするのに利用可能な、3つの異なるトレイトが存在します: ```rust # mod foo { @@ -319,8 +322,8 @@ pub trait FnOnce { -クロージャに対する構文 `|| {}` は上述の3つのトレイトへの糖衣構文です。 -Rustは環境の構造体を作成し、 適切なトレイトを `impl` し、それを利用します。 +クロージャの構文 `|| {}` は上述の3つのトレイトへの糖衣構文です。 +Rustは環境用の構造体を作成し、 適切なトレイトを `impl` し、それを利用します。 @@ -328,14 +331,14 @@ Rustは環境の構造体を作成し、 適切なトレイトを `impl` し、 -クロージャが実際にはトレイトであることを知ったので、 -クロージャをどのように引数として取ったり返り値として返せばいいかわかりました: 通常のトレイトと同様に行うのです! +クロージャが実際にはトレイトであることを学んだので、 +クロージャを引数としたり返り値としたりする方法を既に知っていることになります: 通常のトレイトと同様に行うのです! -これは、静的なディスパッチと動的なディスパッチを洗濯することができるという事も意味しています。 -手始めに呼び出し可能な何かを引数にとりそれを呼び出し、その結果を返す関数を書いてみましょう: +これは、静的ディスパッチと動的ディスパッチを選択することができるということも意味しています。 +手始めに呼び出し可能な何かを引数にとり、それを呼び出し、結果を返す関数を書いてみましょう: ```rust fn call_with_one(some_closure: F) -> i32 @@ -352,7 +355,7 @@ assert_eq!(3, answer); クロージャ `|x| x + 2` を `call_with_one` に渡しました。 -これは `call_with_one` という関数名から推測される処理を行います: クロージャに `1` を与えて呼び出します。 +`call_with_one` はその関数名から推測される処理を行います: クロージャに `1` を与えて呼び出します。 `call_with_one` のシグネチャを詳細に見ていきましょう: @@ -365,7 +368,7 @@ fn call_with_one(some_closure: F) -> i32 -型 `F` を持つ引数を1つ取り、返り値として `i32` を返します。 +型 `F` の引数を1つ取り、返り値として `i32` を返します。 この部分は特に注目には値しません。次の部分は: ```rust @@ -377,9 +380,9 @@ fn call_with_one(some_closure: F) -> i32 -`Fn` がトレイトであるために、ジェネリックの境界として `Fn` を指定する事ができます。 +`Fn` がトレイトであるために、ジェネリックの境界として `Fn` を指定することができます。 この場合はクロージャは `i32` を引数として取り、 `i32` を返します、そのため -ジェネリックの境界として `Fn(i32) -> i32` を指定子ます。 +ジェネリックの境界として `Fn(i32) -> i32` を指定します。 @@ -388,15 +391,15 @@ fn call_with_one(some_closure: F) -> i32 -キーポイントがここにもあります: ジェネリックをトレイトで境界を指定したために、この関数は単相化されます、 -それゆえ、静的なディスパッチをクロージャに対して行います。これはとても素敵です。 +キーポイントがほかにもあります: ジェネリックをトレイトで境界を指定したために、 +この関数は単相化され、静的ディスパッチをクロージャに対して行います。これはとても素敵です。 多くの言語では、クロージャは常にヒープにアロケートされ、常に動的ディスパッチが行われます。 -Rustではスタックにクロージャの環境をアロケーションし、呼び出しを静的にディスパッチすることができます。 -これは比較的頻繁にクロージャを引数として取るイテレータやそれらのアダプタにおいて発生します。 +Rustではスタックにクロージャの環境をアロケートし、呼び出しを静的ディスパッチすることができます。 +これは、しばしばクロージャを引数として取る、イテレータやそれらのアダプタにおいて頻繁に行われます。 -もちろん、動的ディスパッチ行いたいときは、そのようにすることもできます。 +もちろん、動的ディスパッチ行いたいときは、そうすることもできます。 そのような場合もトレイトオブジェクトが通常どうりに対応します: ```rust @@ -411,7 +414,7 @@ assert_eq!(3, answer); -トレイトオブジェクトを引数に取るようになり、 +トレイトオブジェクト `&Fn` を引数にとります。 また `call_with_one` にクロージャを渡すときに参照を利用するようにしました、 そのため `&||` を利用しています。 @@ -442,7 +445,7 @@ assert_eq!(2, answer); -この例では、中間の変数 `f` が必ず必要なわけではありません、関数名を指定することでもきちんと動作します: +この例では、中間の変数 `f` が必ずしも必要なわけではありません、関数名を指定することでもきちんと動作します: ```ignore let answer = call_with_one(&add_one); @@ -455,8 +458,8 @@ let answer = call_with_one(&add_one); -関数を用いたスタイルのコードでは、クロージャを返す事は非常によく見られます。 -もし、クロージャを返す事を試みた場合、エラーが発生します。これは一見奇妙に思われますが、理解することができます。 +関数を用いたスタイルのコードでは、クロージャを返すことは非常によく見られます。 +もし、クロージャを返すことを試みた場合、エラーが発生します。これは一見奇妙に思われますが、理解することができます。 以下は、関数からクロージャを返すことを試みた場合のコードです: ```rust,ignore @@ -527,9 +530,9 @@ fn factory() -> &(Fn(i32) -> i32) { -ふむ。これはリファレンスを利用したため、ライフタイムを指定する必要が有ることによります。 +ふむ。これはリファレンスを利用したので、ライフタイムを指定する必要が有るためです。 しかし、 `factory()` 関数は引数を何も取りません、 -そのため [elision](lifetimes.html#lifetime-elision) は実施されません。 +そのため [ライフタイムの省略](lifetimes.html#lifetime-elision) は実施されません。 では、どのような選択肢が有るのでしょうか? `'static` を試してみましょう: ```rust,ignore @@ -562,27 +565,28 @@ error: mismatched types: このエラーは `&'static Fn(i32) -> i32` ではなく、 - `[closure@:7:9: 7:20]` を使っているという事を伝えています。 -しかし、これは一体何でしょう? + `[closure@:7:9: 7:20]` を使ってしまっているということを伝えています。 +ちょっと待ってください、一体これはどういう意味でしょう? -それぞれのクロージャはそれぞれの環境の `struct` を生成し、 `Fn` やその仲間を実装するため、 -それぞれの型は匿名となります。それぞれの型はそのクロージャのためだけに存在します。 -そのためRustはそれらの型を自動生成された名前の代わりに `closure@` と示します。 +それぞれのクロージャはそれぞれの環境用の `struct` を生成し、 +`Fn` やそれに準ずるものを実装するため、それぞれの型は匿名となります。 +それらの型はそれらのクロージャのためだけに存在します。 +そのためRustはそれらの型を自動生成された名前の代わりに `closure@` と表示します。 -このエラーはその他にも返り値の型が参照であることを期待しているが、 -上のコードではそうではないという事についても指摘しています。 -そのうえ、直接的に `'static` ライフタイムをオブジェクトに割り当てることはできません。 -そのため、`Fn` をボックス化することで「トレイトオブジェクト」を返すという方法を取ります。 -そうすると、動作するように成るまであと一歩のところまで来ます: +また、このエラーは返り値の型が参照であることを期待しているが、 +上のコードではそうなっていないということについても指摘しています。 +しかし、直接的に `'static` ライフタイムをオブジェクトに割り当てることはできません。 +そこで、`Fn` をボックス化することで「トレイトオブジェクト」を返すという方法を取ります。 +そうすると、動作するまであと一歩のところまで来ます: ```rust,ignore @@ -617,9 +621,9 @@ Box::new(|x| x + num) 以前説明したように、クロージャはその環境を借用します。 今回の場合は、環境はスタックにアロケートされた `5` に束縛された `num` からできていることから、 -借用はスタックフレームと同じライフタイムを持っています。 +環境の借用はスタックフレームと同じライフタイムを持っています。 そのため、もしこのクロージャを返り値とした場合、 - `factory()` 関数の処理が完了し、スタックフレームは取り除かれクロージャはゴミとなったメモリを参照することになります! +そのあと `factory()` 関数の処理は終了し、スタックフレームが取り除かれクロージャはゴミとなったメモリを参照することになります! 上のコードに最後の修正を施すことによって動作させることができるようになります: @@ -640,5 +644,5 @@ assert_eq!(6, answer); -内部のクロージャを `move Fn` にすることで、新しいスタックフレームをクロージャのために生成します。 +`factory()` 内のクロージャを `move Fn` にすることで、新しいスタックフレームをクロージャのために生成します。 そしてボックス化することによって、既知のサイズとなり、現在のスタックフレームから抜けることが可能になります。 From 634c74c6a01c0c25fd49aa5f1dea4a7a583f2102 Mon Sep 17 00:00:00 2001 From: Pocket7878 Date: Wed, 2 Mar 2016 00:12:08 +0900 Subject: [PATCH 7/7] Fix translation --- 1.6/ja/book/closures.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/1.6/ja/book/closures.md b/1.6/ja/book/closures.md index 4be9f9e1..e7c4fbb5 100644 --- a/1.6/ja/book/closures.md +++ b/1.6/ja/book/closures.md @@ -158,7 +158,7 @@ let y = &mut num; -もしクロージャが `num` の変更可能な借用を要求した場合、Rustは借用する代わりに環境の所有権を取りムーブします。 +もしクロージャが `num` を要求した場合、Rustは借用する代わりに環境の所有権を取りムーブします。 そのため、以下のコードは動作しません: ```rust,ignore @@ -270,7 +270,7 @@ assert_eq!(5, num); Rustにおけるクロージャの実装は他の言語とは少し異なります。 -Rustにおけるクロージャは効率的なトレイトへの糖衣構文です。 +Rustにおけるクロージャは実質的にトレイトへの糖衣構文です。 続きの説明を読む前に [トレイト][traits] や [トレイトオブジェクト][trait-objects] についてのチャプターを学ぶ前に読みたくなるでしょう。 [traits]: traits.html @@ -313,7 +313,7 @@ pub trait FnOnce { -これらのトレイトの間の僅かな違いに気がつくことでしょう、しかし大きな違いは `self` についてです: +これらのトレイトの間のいくつかの違いに気がつくことでしょう、しかし大きな違いは `self` についてです: `Fn` は `&self` を引数に取ります、 `FnMut` は `&mut self` を引数に取ります、そして `FnOnce` は `self` を引数に取ります。 これは通常のメソッド呼び出しにおける `self` のすべての種類をカバーしています。 しかし、これら `self` の各種類を一つの大きなトレイトにまとめるのではなく異なるトレイトに分けています。 @@ -399,8 +399,8 @@ Rustではスタックにクロージャの環境をアロケートし、呼び -もちろん、動的ディスパッチ行いたいときは、そうすることもできます。 -そのような場合もトレイトオブジェクトが通常どうりに対応します: +もちろん、動的ディスパッチを行いたいときは、そうすることもできます。 +そのような場合もトレイトオブジェクトが通常どおりに対応します: ```rust fn call_with_one(some_closure: &Fn(i32) -> i32) -> i32 { @@ -584,7 +584,7 @@ error: mismatched types: また、このエラーは返り値の型が参照であることを期待しているが、 上のコードではそうなっていないということについても指摘しています。 -しかし、直接的に `'static` ライフタイムをオブジェクトに割り当てることはできません。 +もうちょっというと、直接的に `'static` ライフタイムをオブジェクトに割り当てることはできません。 そこで、`Fn` をボックス化することで「トレイトオブジェクト」を返すという方法を取ります。 そうすると、動作するまであと一歩のところまで来ます: