Browse Source

+

pull/1397/merge^2
AveN RU 9 months ago
parent
commit
718024f419
  1. 4
      rustbook-ru/listings/ch13-functional-features/listing-13-01/output.txt
  2. 4
      rustbook-ru/listings/ch13-functional-features/listing-13-01/src/main.rs
  3. 8
      rustbook-ru/listings/ch13-functional-features/listing-13-04/output.txt
  4. 8
      rustbook-ru/listings/ch13-functional-features/listing-13-04/src/main.rs
  5. 4
      rustbook-ru/listings/ch13-functional-features/listing-13-05/output.txt
  6. 4
      rustbook-ru/listings/ch13-functional-features/listing-13-05/src/main.rs
  7. 7
      rustbook-ru/listings/ch13-functional-features/listing-13-06/Cargo.lock
  8. 4
      rustbook-ru/listings/ch13-functional-features/listing-13-06/src/main.rs
  9. 1
      rustbook-ru/listings/ch13-functional-features/listing-13-06/target/.rustc_info.json
  10. 3
      rustbook-ru/listings/ch13-functional-features/listing-13-06/target/CACHEDIR.TAG
  11. 0
      rustbook-ru/listings/ch13-functional-features/listing-13-06/target/debug/.cargo-lock
  12. BIN
      rustbook-ru/listings/ch13-functional-features/listing-13-06/target/debug/.fingerprint/closure-example-2a9f545398d311c3/dep-test-bin-closure-example
  13. 1
      rustbook-ru/listings/ch13-functional-features/listing-13-06/target/debug/.fingerprint/closure-example-2a9f545398d311c3/invoked.timestamp
  14. 1
      rustbook-ru/listings/ch13-functional-features/listing-13-06/target/debug/.fingerprint/closure-example-2a9f545398d311c3/test-bin-closure-example
  15. 1
      rustbook-ru/listings/ch13-functional-features/listing-13-06/target/debug/.fingerprint/closure-example-2a9f545398d311c3/test-bin-closure-example.json
  16. 1
      rustbook-ru/listings/ch13-functional-features/listing-13-06/target/debug/.fingerprint/closure-example-afd086ecee8edfec/bin-closure-example
  17. 1
      rustbook-ru/listings/ch13-functional-features/listing-13-06/target/debug/.fingerprint/closure-example-afd086ecee8edfec/bin-closure-example.json
  18. BIN
      rustbook-ru/listings/ch13-functional-features/listing-13-06/target/debug/.fingerprint/closure-example-afd086ecee8edfec/dep-bin-closure-example
  19. 1
      rustbook-ru/listings/ch13-functional-features/listing-13-06/target/debug/.fingerprint/closure-example-afd086ecee8edfec/invoked.timestamp
  20. 5
      rustbook-ru/listings/ch13-functional-features/listing-13-06/target/debug/deps/closure_example-2a9f545398d311c3.d
  21. 5
      rustbook-ru/listings/ch13-functional-features/listing-13-06/target/debug/deps/closure_example-afd086ecee8edfec.d
  22. 0
      rustbook-ru/listings/ch13-functional-features/listing-13-06/target/debug/deps/libclosure_example-2a9f545398d311c3.rmeta
  23. 0
      rustbook-ru/listings/ch13-functional-features/listing-13-06/target/debug/deps/libclosure_example-afd086ecee8edfec.rmeta
  24. BIN
      rustbook-ru/listings/ch13-functional-features/listing-13-06/target/debug/incremental/closure_example-0fjdr4kj3vycs/s-h5np4xfhis-18d734a-c0phqqya5cyyqbg7eq85u0d7c/dep-graph.bin
  25. BIN
      rustbook-ru/listings/ch13-functional-features/listing-13-06/target/debug/incremental/closure_example-0fjdr4kj3vycs/s-h5np4xfhis-18d734a-c0phqqya5cyyqbg7eq85u0d7c/query-cache.bin
  26. BIN
      rustbook-ru/listings/ch13-functional-features/listing-13-06/target/debug/incremental/closure_example-0fjdr4kj3vycs/s-h5np4xfhis-18d734a-c0phqqya5cyyqbg7eq85u0d7c/work-products.bin
  27. 0
      rustbook-ru/listings/ch13-functional-features/listing-13-06/target/debug/incremental/closure_example-0fjdr4kj3vycs/s-h5np4xfhis-18d734a.lock
  28. BIN
      rustbook-ru/listings/ch13-functional-features/listing-13-06/target/debug/incremental/closure_example-18mvx16ei8wrq/s-h5np4xfhi3-0ckmkia-0nt6m12kworcidq21xuznbryy/dep-graph.bin
  29. BIN
      rustbook-ru/listings/ch13-functional-features/listing-13-06/target/debug/incremental/closure_example-18mvx16ei8wrq/s-h5np4xfhi3-0ckmkia-0nt6m12kworcidq21xuznbryy/query-cache.bin
  30. BIN
      rustbook-ru/listings/ch13-functional-features/listing-13-06/target/debug/incremental/closure_example-18mvx16ei8wrq/s-h5np4xfhi3-0ckmkia-0nt6m12kworcidq21xuznbryy/work-products.bin
  31. 0
      rustbook-ru/listings/ch13-functional-features/listing-13-06/target/debug/incremental/closure_example-18mvx16ei8wrq/s-h5np4xfhi3-0ckmkia.lock
  32. 36
      rustbook-ru/nostarch/chapter13.md
  33. 2
      rustbook-ru/nostarch/chapter21.md
  34. 2
      rustbook-ru/src/SUMMARY.md
  35. 2
      rustbook-ru/src/appendix-01-keywords.md
  36. 2
      rustbook-ru/src/appendix-02-operators.md
  37. 2
      rustbook-ru/src/ch02-00-guessing-game-tutorial.md
  38. 2
      rustbook-ru/src/ch03-05-control-flow.md
  39. 2
      rustbook-ru/src/ch09-02-recoverable-errors-with-result.md
  40. 70
      rustbook-ru/src/ch13-01-closures.md
  41. 8
      rustbook-ru/src/ch13-02-iterators.md
  42. 2
      rustbook-ru/src/ch15-05-interior-mutability.md
  43. 12
      rustbook-ru/src/ch16-01-threads.md
  44. 2
      rustbook-ru/src/ch17-02-concurrency-with-async.md
  45. 2
      rustbook-ru/src/ch19-03-pattern-syntax.md
  46. 2
      rustbook-ru/src/ch20-02-advanced-traits.md
  47. 4
      rustbook-ru/src/ch21-02-multithreaded.md
  48. BIN
      заимствованные слова1.xlsx

4
rustbook-ru/listings/ch13-functional-features/listing-13-01/output.txt

@ -2,5 +2,5 @@ $ cargo run @@ -2,5 +2,5 @@ $ cargo run
Compiling shirt-company v0.1.0 (file:///projects/shirt-company)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.27s
Running `target/debug/shirt-company`
The user with preference Some(Red) gets Red
The user with preference None gets Blue
Пользователь выбрал Some(Red) получил Красную
Пользователь выбрал None получил Голубую

4
rustbook-ru/listings/ch13-functional-features/listing-13-01/src/main.rs

@ -39,14 +39,14 @@ fn main() { @@ -39,14 +39,14 @@ fn main() {
let user_pref1 = Some(ShirtColor::Red);
let giveaway1 = store.giveaway(user_pref1);
println!(
"The user with preference {:?} gets {:?}",
"Пользователь выбрал {:?} получил {:?}",
user_pref1, giveaway1
);
let user_pref2 = None;
let giveaway2 = store.giveaway(user_pref2);
println!(
"The user with preference {:?} gets {:?}",
"Пользователь выбрал {:?} получил {:?}",
user_pref2, giveaway2
);
}

8
rustbook-ru/listings/ch13-functional-features/listing-13-04/output.txt

@ -4,7 +4,7 @@ $ cargo run @@ -4,7 +4,7 @@ $ cargo run
Compiling closure-example v0.1.0 (file:///projects/closure-example)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.43s
Running `target/debug/closure-example`
Before defining closure: [1, 2, 3]
Before calling closure: [1, 2, 3]
From closure: [1, 2, 3]
After calling closure: [1, 2, 3]
До определения замыкания: [1, 2, 3]
До вызова замыкания: [1, 2, 3]
Вызов замыкания: [1, 2, 3]
После вызова замыкания: [1, 2, 3]

8
rustbook-ru/listings/ch13-functional-features/listing-13-04/src/main.rs

@ -1,10 +1,10 @@ @@ -1,10 +1,10 @@
fn main() {
let list = vec![1, 2, 3];
println!("Before defining closure: {list:?}");
println!("До определения замыкания: {list:?}");
let only_borrows = || println!("From closure: {list:?}");
let only_borrows = || println!("Вызов замыкания: {list:?}");
println!("Before calling closure: {list:?}");
println!("До вызова замыкания: {list:?}");
only_borrows();
println!("After calling closure: {list:?}");
println!("После вызова замыкания: {list:?}");
}

4
rustbook-ru/listings/ch13-functional-features/listing-13-05/output.txt

@ -4,5 +4,5 @@ $ cargo run @@ -4,5 +4,5 @@ $ cargo run
Compiling closure-example v0.1.0 (file:///projects/closure-example)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.43s
Running `target/debug/closure-example`
Before defining closure: [1, 2, 3]
After calling closure: [1, 2, 3, 7]
До определения замыкания: [1, 2, 3]
После вызова замыкания: [1, 2, 3, 7]

4
rustbook-ru/listings/ch13-functional-features/listing-13-05/src/main.rs

@ -1,9 +1,9 @@ @@ -1,9 +1,9 @@
fn main() {
let mut list = vec![1, 2, 3];
println!("Before defining closure: {list:?}");
println!("До определения замыкания: {list:?}");
let mut borrows_mutably = || list.push(7);
borrows_mutably();
println!("After calling closure: {list:?}");
println!("После вызова замыкания: {list:?}");
}

7
rustbook-ru/listings/ch13-functional-features/listing-13-06/Cargo.lock generated

@ -0,0 +1,7 @@ @@ -0,0 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 4
[[package]]
name = "closure-example"
version = "0.1.0"

4
rustbook-ru/listings/ch13-functional-features/listing-13-06/src/main.rs

@ -2,9 +2,9 @@ use std::thread; @@ -2,9 +2,9 @@ use std::thread;
fn main() {
let list = vec![1, 2, 3];
println!("Before defining closure: {list:?}");
println!("До определения замыкания: {list:?}");
thread::spawn(move || println!("From thread: {list:?}"))
thread::spawn(move || println!("Из основного потока: {list:?}"))
.join()
.unwrap();
}

1
rustbook-ru/listings/ch13-functional-features/listing-13-06/target/.rustc_info.json

@ -0,0 +1 @@ @@ -0,0 +1 @@
{"rustc_fingerprint":15658296027255894067,"outputs":{"17747080675513052775":{"success":true,"status":"","code":0,"stdout":"rustc 1.85.1 (4eb161250 2025-03-15)\nbinary: rustc\ncommit-hash: 4eb161250e340c8f48f66e2b929ef4a5bed7c181\ncommit-date: 2025-03-15\nhost: x86_64-pc-windows-msvc\nrelease: 1.85.1\nLLVM version: 19.1.7\n","stderr":""},"13331785392996375709":{"success":true,"status":"","code":0,"stdout":"___.exe\nlib___.rlib\n___.dll\n___.dll\n___.lib\n___.dll\nC:\\Program Files\\Rust stable MSVC 1.85\npacked\n___\ndebug_assertions\npanic=\"unwind\"\nproc_macro\ntarget_abi=\"\"\ntarget_arch=\"x86_64\"\ntarget_endian=\"little\"\ntarget_env=\"msvc\"\ntarget_family=\"windows\"\ntarget_feature=\"cmpxchg16b\"\ntarget_feature=\"fxsr\"\ntarget_feature=\"sse\"\ntarget_feature=\"sse2\"\ntarget_feature=\"sse3\"\ntarget_has_atomic=\"128\"\ntarget_has_atomic=\"16\"\ntarget_has_atomic=\"32\"\ntarget_has_atomic=\"64\"\ntarget_has_atomic=\"8\"\ntarget_has_atomic=\"ptr\"\ntarget_os=\"windows\"\ntarget_pointer_width=\"64\"\ntarget_vendor=\"pc\"\nwindows\n","stderr":""}},"successes":{}}

3
rustbook-ru/listings/ch13-functional-features/listing-13-06/target/CACHEDIR.TAG

@ -0,0 +1,3 @@ @@ -0,0 +1,3 @@
Signature: 8a477f597d28d172789f06886806bc55
# This file is a cache directory tag created by cargo.
# For information about cache directory tags see https://bford.info/cachedir/

0
rustbook-ru/listings/ch13-functional-features/listing-13-06/target/debug/.cargo-lock

BIN
rustbook-ru/listings/ch13-functional-features/listing-13-06/target/debug/.fingerprint/closure-example-2a9f545398d311c3/dep-test-bin-closure-example

Binary file not shown.

1
rustbook-ru/listings/ch13-functional-features/listing-13-06/target/debug/.fingerprint/closure-example-2a9f545398d311c3/invoked.timestamp

@ -0,0 +1 @@ @@ -0,0 +1 @@
This file has an mtime of when this was started.

1
rustbook-ru/listings/ch13-functional-features/listing-13-06/target/debug/.fingerprint/closure-example-2a9f545398d311c3/test-bin-closure-example

@ -0,0 +1 @@ @@ -0,0 +1 @@
8676145ac934361e

1
rustbook-ru/listings/ch13-functional-features/listing-13-06/target/debug/.fingerprint/closure-example-2a9f545398d311c3/test-bin-closure-example.json

@ -0,0 +1 @@ @@ -0,0 +1 @@
{"rustc":12488743700189009532,"features":"[]","declared_features":"[]","target":3385139634213972182,"profile":3316208278650011218,"path":4942398508502643691,"deps":[],"local":[{"CheckDepInfo":{"dep_info":"debug\\.fingerprint\\closure-example-2a9f545398d311c3\\dep-test-bin-closure-example","checksum":false}}],"rustflags":[],"config":2069994364910194474,"compile_kind":0}

1
rustbook-ru/listings/ch13-functional-features/listing-13-06/target/debug/.fingerprint/closure-example-afd086ecee8edfec/bin-closure-example

@ -0,0 +1 @@ @@ -0,0 +1 @@
a1343fd0e7610781

1
rustbook-ru/listings/ch13-functional-features/listing-13-06/target/debug/.fingerprint/closure-example-afd086ecee8edfec/bin-closure-example.json

@ -0,0 +1 @@ @@ -0,0 +1 @@
{"rustc":12488743700189009532,"features":"[]","declared_features":"[]","target":3385139634213972182,"profile":17672942494452627365,"path":4942398508502643691,"deps":[],"local":[{"CheckDepInfo":{"dep_info":"debug\\.fingerprint\\closure-example-afd086ecee8edfec\\dep-bin-closure-example","checksum":false}}],"rustflags":[],"config":2069994364910194474,"compile_kind":0}

BIN
rustbook-ru/listings/ch13-functional-features/listing-13-06/target/debug/.fingerprint/closure-example-afd086ecee8edfec/dep-bin-closure-example

Binary file not shown.

1
rustbook-ru/listings/ch13-functional-features/listing-13-06/target/debug/.fingerprint/closure-example-afd086ecee8edfec/invoked.timestamp

@ -0,0 +1 @@ @@ -0,0 +1 @@
This file has an mtime of when this was started.

5
rustbook-ru/listings/ch13-functional-features/listing-13-06/target/debug/deps/closure_example-2a9f545398d311c3.d vendored

@ -0,0 +1,5 @@ @@ -0,0 +1,5 @@
E:\Rust\книги\book\rustbook-ru\listings\ch13-functional-features\listing-13-06\target\debug\deps\libclosure_example-2a9f545398d311c3.rmeta: src\main.rs
E:\Rust\книги\book\rustbook-ru\listings\ch13-functional-features\listing-13-06\target\debug\deps\closure_example-2a9f545398d311c3.d: src\main.rs
src\main.rs:

5
rustbook-ru/listings/ch13-functional-features/listing-13-06/target/debug/deps/closure_example-afd086ecee8edfec.d vendored

@ -0,0 +1,5 @@ @@ -0,0 +1,5 @@
E:\Rust\книги\book\rustbook-ru\listings\ch13-functional-features\listing-13-06\target\debug\deps\libclosure_example-afd086ecee8edfec.rmeta: src\main.rs
E:\Rust\книги\book\rustbook-ru\listings\ch13-functional-features\listing-13-06\target\debug\deps\closure_example-afd086ecee8edfec.d: src\main.rs
src\main.rs:

0
rustbook-ru/listings/ch13-functional-features/listing-13-06/target/debug/deps/libclosure_example-2a9f545398d311c3.rmeta vendored

0
rustbook-ru/listings/ch13-functional-features/listing-13-06/target/debug/deps/libclosure_example-afd086ecee8edfec.rmeta vendored

BIN
rustbook-ru/listings/ch13-functional-features/listing-13-06/target/debug/incremental/closure_example-0fjdr4kj3vycs/s-h5np4xfhis-18d734a-c0phqqya5cyyqbg7eq85u0d7c/dep-graph.bin

Binary file not shown.

BIN
rustbook-ru/listings/ch13-functional-features/listing-13-06/target/debug/incremental/closure_example-0fjdr4kj3vycs/s-h5np4xfhis-18d734a-c0phqqya5cyyqbg7eq85u0d7c/query-cache.bin

Binary file not shown.

BIN
rustbook-ru/listings/ch13-functional-features/listing-13-06/target/debug/incremental/closure_example-0fjdr4kj3vycs/s-h5np4xfhis-18d734a-c0phqqya5cyyqbg7eq85u0d7c/work-products.bin

Binary file not shown.

0
rustbook-ru/listings/ch13-functional-features/listing-13-06/target/debug/incremental/closure_example-0fjdr4kj3vycs/s-h5np4xfhis-18d734a.lock

BIN
rustbook-ru/listings/ch13-functional-features/listing-13-06/target/debug/incremental/closure_example-18mvx16ei8wrq/s-h5np4xfhi3-0ckmkia-0nt6m12kworcidq21xuznbryy/dep-graph.bin

Binary file not shown.

BIN
rustbook-ru/listings/ch13-functional-features/listing-13-06/target/debug/incremental/closure_example-18mvx16ei8wrq/s-h5np4xfhi3-0ckmkia-0nt6m12kworcidq21xuznbryy/query-cache.bin

Binary file not shown.

BIN
rustbook-ru/listings/ch13-functional-features/listing-13-06/target/debug/incremental/closure_example-18mvx16ei8wrq/s-h5np4xfhi3-0ckmkia-0nt6m12kworcidq21xuznbryy/work-products.bin

Binary file not shown.

0
rustbook-ru/listings/ch13-functional-features/listing-13-06/target/debug/incremental/closure_example-18mvx16ei8wrq/s-h5np4xfhi3-0ckmkia.lock

36
rustbook-ru/nostarch/chapter13.md

@ -114,14 +114,14 @@ fn main() { @@ -114,14 +114,14 @@ fn main() {
let user_pref1 = Some(ShirtColor::Red);
let giveaway1 = store.giveaway(user_pref1);
println!(
"The user with preference {:?} gets {:?}",
"Пользователь выбрал {:?} gets {:?}",
user_pref1, giveaway1
);
let user_pref2 = None;
let giveaway2 = store.giveaway(user_pref2);
println!(
"The user with preference {:?} gets {:?}",
"Пользователь выбрал {:?} gets {:?}",
user_pref2, giveaway2
);
}
@ -160,8 +160,8 @@ $ cargo run @@ -160,8 +160,8 @@ $ cargo run
Compiling shirt-company v0.1.0 (file:///projects/shirt-company)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.27s
Running `target/debug/shirt-company`
The user with preference Some(Red) gets Red
The user with preference None gets Blue
Пользователь выбрал Some(Red) gets Red
Пользователь выбрал None gets Blue
```
One interesting aspect here is that we’ve passed a closure that calls
@ -305,13 +305,13 @@ src/main.rs @@ -305,13 +305,13 @@ src/main.rs
```
fn main() {
let list = vec![1, 2, 3];
println!("Before defining closure: {list:?}");
println!("До определения замыкания: {list:?}");
let only_borrows = || println!("From closure: {list:?}");
let only_borrows = || println!("Вызов замыкания: {list:?}");
println!("Before calling closure: {list:?}");
println!("До вызова замыкания: {list:?}");
only_borrows();
println!("After calling closure: {list:?}");
println!("После вызова замыкания: {list:?}");
}
```
@ -333,10 +333,10 @@ $ cargo run @@ -333,10 +333,10 @@ $ cargo run
Compiling closure-example v0.1.0 (file:///projects/closure-example)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.43s
Running `target/debug/closure-example`
Before defining closure: [1, 2, 3]
Before calling closure: [1, 2, 3]
From closure: [1, 2, 3]
After calling closure: [1, 2, 3]
До определения замыкания: [1, 2, 3]
До вызова замыкания: [1, 2, 3]
Вызов замыкания: [1, 2, 3]
После вызова замыкания: [1, 2, 3]
```
Next, in Listing 13-5, we change the closure body so that it adds an element to
@ -347,12 +347,12 @@ src/main.rs @@ -347,12 +347,12 @@ src/main.rs
```
fn main() {
let mut list = vec![1, 2, 3];
println!("Before defining closure: {list:?}");
println!("До определения замыкания: {list:?}");
let mut borrows_mutably = || list.push(7);
borrows_mutably();
println!("After calling closure: {list:?}");
println!("После вызова замыкания: {list:?}");
}
```
@ -367,8 +367,8 @@ $ cargo run @@ -367,8 +367,8 @@ $ cargo run
Compiling closure-example v0.1.0 (file:///projects/closure-example)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.43s
Running `target/debug/closure-example`
Before defining closure: [1, 2, 3]
After calling closure: [1, 2, 3, 7]
До определения замыкания: [1, 2, 3]
После вызова замыкания: [1, 2, 3, 7]
```
Note that there’s no longer a `println!` between the definition and the call of
@ -397,9 +397,9 @@ use std::thread; @@ -397,9 +397,9 @@ use std::thread;
fn main() {
let list = vec![1, 2, 3];
println!("Before defining closure: {list:?}");
println!("До определения замыкания: {list:?}");
thread::spawn(move || println!("From thread: {list:?}"))
thread::spawn(move || println!("Из основного потока: {list:?}"))
.join()
.unwrap();
}

2
rustbook-ru/nostarch/chapter21.md

@ -802,7 +802,7 @@ pool and think about how things would look different or the same with async. @@ -802,7 +802,7 @@ pool and think about how things would look different or the same with async.
#### Creating a Finite Number of Threads
We want our thread pool to work in a similar, familiar way so that switching
from threads to a thread pool doesn’t require large changes to the code that
из основного потокаs to a thread pool doesn’t require large changes to the code that
uses our API. Listing 21-12 shows the hypothetical interface for a `ThreadPool`
struct we want to use instead of `thread::spawn`.

2
rustbook-ru/src/SUMMARY.md

@ -85,7 +85,7 @@ @@ -85,7 +85,7 @@
- [Полезные возможности языка: повторители и замыкания](ch13-00-functional-features.md)
- [Замыкания: безымянные функции, которые захватывают своё окружение](ch13-01-closures.md)
- [Замыкания: безымянные функции, которые получают своё окружение](ch13-01-closures.md)
- [Обработка последовательности переменных с помощью повторителей](ch13-02-iterators.md)
- [Улучшение нашего дела с вводом/выводом](ch13-03-improving-our-io-project.md)
- [Сравнение производительности: круговороты и повторители](ch13-04-performance.md)

2
rustbook-ru/src/appendix-01-keywords.md

@ -27,7 +27,7 @@ @@ -27,7 +27,7 @@
- `loop` — безусловный круговорот
- `match` — сопоставление значения с образцами данных
- `mod` — определение раздела
- `move` — перекладывание владения на замыкание всеми захваченными переменными
- `move` — перекладывание владения на замыкание всеми полученными переменными
- `mut` — обозначение изменяемости в разных видах данных, в том числе в переменных, ссылках, сырых указателей и привязках к образцу данных
- `pub` — измениие открытого доступа для полей стопок, разделов `impl` и разделов
- `ref` — привязка по ссылке

2
rustbook-ru/src/appendix-02-operators.md

@ -140,7 +140,7 @@ @@ -140,7 +140,7 @@
`#[meta]` | Внешнее свойство
`#![meta]` | Внутреннее свойство
`$ident` | Подстановка в макросе
`$ident:kind` | Захват макроса
`$ident:kind` | Получение макроса
`$(…)…` | Повторение макроса
`ident!(...)`, `ident!{...}`, `ident![...]` | Вызов макроса

2
rustbook-ru/src/ch02-00-guessing-game-tutorial.md

@ -273,7 +273,7 @@ $ cargo build @@ -273,7 +273,7 @@ $ cargo build
Когда мы подключаем внешнее дополнение, Cargo берет последние исполнения всего, что нужно этого дополнения, из *перечня (registry)*, который является повтором данных с [Crates.io]. Crates.io — это место, где участники сообщества Ржавчины размещают свои дела с открытой исходной рукописью для использования другими.
После обновления перечня Cargo проверяет раздел `[dependencies]` и загружает все указанные в списке дополнения, которые ещё не были загружены. В нашем случае, хотя мы указали только `rand` в качестве дополнения, Cargo также захватил другие дополнения, от которых зависит работа `rand`. После загрузки всех дополнений Ржавчины происходит их сборка, а затем собирает дело с имеющимися дополнениями.
После обновления перечня Cargo проверяет раздел `[dependencies]` и загружает все указанные в списке дополнения, которые ещё не были загружены. В нашем случае, хотя мы указали только `rand` в качестве дополнения, Cargo также получил другие дополнения, от которых зависит работа `rand`. После загрузки всех дополнений Ржавчины происходит их сборка, а затем собирает дело с имеющимися дополнениями.
Если сразу же запустить `cargo build` снова, не внося никаких изменений, то кроме строки `Finished` вы не получите никакого вывода. Cargo знает, что он уже загрузил и собрал дополнения, и вы не вносили никаких изменений в файл *Cargo.toml*. Cargo также знает, что вы ничего не изменили в своей рукописи, поэтому он не пересоберет и его. Если делать нечего, он просто завершает работу.

2
rustbook-ru/src/ch03-05-control-flow.md

@ -208,7 +208,7 @@ again! @@ -208,7 +208,7 @@ again!
<span class="caption">Приложение 3-4: Перебор каждой переменной собрания с помощью круговорота <code>while</code></span>
Эта рукопись использует перебор переменных массива. Он начинается с порядкового указателя `0`, а затем замкнуто выполняется, пока не достигнет последнего порядкового указателя в массиве (то есть, когда `index < 5` уже не является истиной). Выполнение этой рукописи выведет каждая переменная массива:
Эта рукопись использует перебор переменных массива. Он начинается с порядкового указателя `0`, а затем замкнуто выполняется, пока не достигнет последнего порядкового указателя в массиве (то есть, когда `index < 5` уже не является истиной). Итог выполнения рукописи выведет каждую переменную массива:
```console
{{#include ../listings/ch03-common-programming-concepts/listing-03-04/output.txt}}

2
rustbook-ru/src/ch09-02-recoverable-errors-with-result.md

@ -171,7 +171,7 @@ don't want to include it for rustdoc testing purposes. --> @@ -171,7 +171,7 @@ don't want to include it for rustdoc testing purposes. -->
Затем рукопись, вызывающая эту, будет обрабатывать полученное значение `Ok`, содержащего имя пользователя, либо значения `Err`, содержащего `io::Error`. Вызывающая рукопись должна решить, что делать с этими значениями. Если вызывающая рукопись получает значение `Err`, она может вызвать `panic!` и завершить работу программы, использовать имя пользователя по умолчанию или найти имя пользователя, например, не в файле. У нас недостаточно сведений о том, что на самом деле пытается сделать вызывающая рукопись, поэтому мы распространяем все сведения об успехах или ошибках вверх, чтобы она могла обрабатываться соответствующим образом.
Эта схема передачи ошибок настолько распространена в языке Ржавчина, что язык предоставляет приказчик вопросительного знака `?`, чтобы облегчить эту задачу.
Этот порядок передачи ошибок настолько распространена в языке Ржавчина, что язык предоставляет приказчик вопросительного знака `?`, чтобы облегчить эту задачу.
#### Сокращение для проброса ошибок: приказчик `?`

70
rustbook-ru/src/ch13-01-closures.md

@ -2,7 +2,7 @@ @@ -2,7 +2,7 @@
<a id="closures-anonymous-functions-that-can-capture-their-environment"></a>
## Замыкания: безымянные функции, которые запечатлевают ("захватывают") своё окружение
## Замыкания: безымянные функции, которые запечатлевают ("получают") своё окружение
Замыкания в Ржавчине - это безымянные функции, которые можно сохранять в переменных или передавать в качестве переменных другим функциям. Вы можете создать замыкание в одном месте, а затем вызвать его в каком-нибудь другом, чтобы выполнить обработку в иной среде. В отличие от функций, замыкания могут использовать значения из области видимости в которой они были определены. Мы выполним, как эти функции замыканий открывают возможности для повторного использования рукописи и изменения её поведения.
@ -12,11 +12,11 @@ @@ -12,11 +12,11 @@
<a id="refactoring-using-functions"></a>
<a id="refactoring-with-closures-to-store-code"></a>
### Захват переменных окружения с помощью замыкания
### Получение переменных окружения с помощью замыкания
Сначала мы рассмотрим, как с помощью замыканий можно использовать предметы из области, в которой они вместе были определены, для их последующего использования. Вот задумка: Время от времени наше предприятие по производству рубашек в качестве акции дарит рубашки ограниченного выпуска, выпущенные ограниченным тиражом, каким-нибудь пользователям из нашего списка рассылки. Люди из списка рассылки при желании могут выбрать любимый цвет в своём личном кабинете. Если человек, выбранный для получения бесплатной рубашки, указал свой любимый цвет, он получает рубашку этого цвета. Если человек не указал свой любимый цвет, он получит рубашку того цвета, которых у предприятия на данное мгновение больше всего.
Существует множество способов выполнить это. В данном примере мы будем использовать перечисление `ShirtColor`, которое может быть двух исходов `Red` и `Blue` (для простоты ограничим количество доступных цветов этими двумя). Запасы предприятия мы представим стопкой `Inventory`, которая состоит из поля `shirts`, содержащего `Vec<ShirtColor>`, в котором перечислены рубашки тех цветов, которые есть в наличии. Способ `giveaway`, определённый в `Inventory`, принимает необязательное свойство - цвет, предпочитаемый пользователем, выбранным для получения бесплатной рубашки, и возвращает тот цвет рубашки, который он получит в действительности. Эта схема показана в приложении 13-1:
Существует множество способов выполнить это. В данном примере мы будем использовать перечисление `ShirtColor`, которое имеет два исхода: `Red` и `Blue` (для простоты ограничим количество доступных цветов этими двумя). Запасы предприятия мы представим стопкой `Inventory`, которая состоит из поля `shirts`, содержащего `Vec<ShirtColor>`, в котором перечислены рубашки тех цветов, которые есть в наличии. Способ `giveaway`, определённый в `Inventory`, принимает необязательное свойство - цвет, предпочитаемый пользователем, выбранным для получения бесплатной рубашки, и возвращает тот цвет рубашки, который он получит в действительности. Этот порядок показана в приложении 13-1:
<span class="filename">Имя файла: src/main.rs</span>
@ -28,25 +28,25 @@ @@ -28,25 +28,25 @@
В магазине `store`, определённом в `main`, осталось две синие и одна красная рубашки для этой ограниченной акции. Мы вызываем способ `giveaway` для пользователя предпочитающего красную рубашку и для пользователя без каких-либо предпочтений.
Опять же, эта рукопись могла быть выполнена множеством способов, но в данном случае, чтобы сосредоточиться на замыканиях, мы придерживались изученных ранее подходов, за исключением тела способа `giveaway`, в котором используется замыкание. В способе `giveaway` мы получаем пользовательское предпочтение цвета как свойство вида данных `Option<ShirtColor>` и вызываем способ `unwrap_or_else` на `user_preference`. Способ <a data-md-type="raw_html" href="../std/option/enum.Option.html#method.unwrap_or_else">`unwrap_or_else` перечисления `Option<T>`</a><!-- ignore --> определён встроенной библиотекой. Он принимает одну переменную: замыкание без переменных, которое возвращает значение `T` (преобразуется в вид значения, которое окажется в исходе `Some` перечисления `Option<T>`, в нашем случае `ShirtColor`). Если `Option<T>` окажется исходом `Some`, `unwrap_or_else` вернёт значение из `Some`. А если `Option<T>` будет является исходом `None`, `unwrap_or_else` вызовет замыкание и вернёт значение, возвращённое замыканием.
Опять же, эта рукопись могла быть выполнена множеством способов, но в данном случае, чтобы сосредоточиться на замыканиях, мы придерживались изученных ранее подходов, за исключением тела способа `giveaway`, в котором используется замыкание. В способе `giveaway` мы получаем пользовательское предпочтение цвета как свойство вида данных `Option<ShirtColor>` и применяем способ `unwrap_or_else` для `user_preference`. Способ <a data-md-type="raw_html" href="../std/option/enum.Option.html#method.unwrap_or_else">`unwrap_or_else` перечисления `Option<T>`</a><!-- ignore --> определён встроенной библиотекой. Он принимает одну переменную: значение `T` (возвращается значение в заранее заданном виде, которое окажется в исходе `Some` перечисления `Option<T>`, в нашем случае `ShirtColor`). Если `Option<T>` окажется исходом `Some`, `unwrap_or_else` вернёт значение из `Some`. А если `Option<T>` будет является исходом `None`, `unwrap_or_else` вызовет замыкание и вернёт значение, полученное из замыкания.
В качестве переменной `unwrap_or_else` мы передаём замыкание `|| self.most_stocked()`. Это замыкание, которое не принимает никаких свойств (если бы у замыкания были свойства, они были бы перечислены между двумя вертикальными полосами). В теле замыкания вызывается `self.most_stocked()`. Здесь мы определили замыкание, а использование `unwrap_or_else` такова, что выполнится оно позднее, когда потребуется получить итог.
В качестве переменной `unwrap_or_else` мы передаём замыкание `|| self.most_stocked()`. Это замыкание, которое не принимает никаких свойств (если бы у замыкания были свойства, они были бы перечислены между двумя вертикальными полосами). В теле замыкания вызывается `self.most_stocked()`. Здесь мы определили замыкание, а использование `unwrap_or_else` таково, что оно выполнится позднее, когда потребуется получить итог.
Выполнение этой рукописи выводит:
Итог выполнения рукописи:
```console
{{#include ../listings/ch13-functional-features/listing-13-01/output.txt}}
```
Важной особенностью здесь является то, что мы передали замыкание, которое вызывает `self.most_stocked()` текущего образца данных `Inventory`. Обычной библиотеке не нужно знать ничего о видах `Inventory` или `ShirtColor`, которые мы определили, или о ходу мыслей, которую мы хотим использовать в этом задумки. Замыкание определяет неизменяемую ссылку на `self` `Inventory` и передаёт её с указанным нами рукописью в способ `unwrap_or_else`. А вот функции не могут определять своё окружение таким образом.
Важной особенностью здесь является то, что мы вызвали замыкание, которое в свою очередь вызывает `self.most_stocked()` - способ для нашего образца данных (стопки) `Inventory`. Обычной библиотеке не нужно знать ничего о видах данных: стопка -> `Inventory` или перечисление -> `ShirtColor`, которые мы определили, или о ходе мыслей, который мы хотим использовать для решения данной задачи. Замыкание определяет неизменяемую ссылку на `self` `Inventory` и передаёт её с указанным нами содержимым в способ `unwrap_or_else`. А вот функции не могут определять своё окружение таким образом.
### Выведение и изложение видов замыкания
Есть и другие различия между функциями и замыканиями. Замыкания обычно не требуют определения видов данных в входных свойств или возвращаемого значения, как это делается в функциях `fn`. Изложения видов данных требуются для функций, потому что виды данных являются частью явного внешней оболочки, предоставляемого пользователям. Жёсткое определение таких внешних оболочек важно для того, чтобы все были согласованы в том, какие виды значений использует и возвращает функция. А вот замыкания, напротив, не употребляются в значении подобных открытых внешних оболочек: они хранятся в переменных, используются не имея имени и незримо для пользователей нашей библиотеки.
Есть и другие различия между функциями и замыканиями. Замыкания обычно не требуют определения видов данных в входных свойств или возвращаемого значения, как это делается в функциях `fn`. Изложения видов данных требуются для функций, потому что виды данных находятся за пределами самой функции, предоставляемого пользователям. Жёсткое определение видов данных необходимо для того, чтобы все вида данных были согласованы в том, какие виды данных использует и возвращает функция. А вот замыкания, напротив, для них не требуется строго указывать виды данных: так как они могут храниться в переменных и использоваться не имея имени, при этом незримо для пользователей нашей библиотеки.
Замыкания, как правило, небольшие и уместны в каком-то узконаправленном среде, а не в произвольных случаях. В этих ограниченных средах сборщик может вывести виды свойств и возвращаемого вида данных, подобно тому, как он может вывести виды данных большинства переменных (есть редкие случаи, когда сборщику также нужны изложении видов замыканий).
Замыкания, как правило, небольшие и уместны в какой-то узконаправленном среде, а не в произвольных случаях. В этих ограниченных средах сборщик может вывести виды свойств и возвращаемого вида данных, подобно тому, как он может вывести виды данных большинства переменных (есть редкие случаи, когда сборщику также нужны изложения видов замыканий).
Как и в случае с переменными, мы можем добавить изложении видов данных, если хотим повысить ясность и чёткость описания ценой увеличения многословности, большей чем это необходимо. Определение видов данных для замыкания будет выглядеть как определение, показанное в приложении 13-2. В этом примере мы определяем замыкание и храним его в переменной, а не определяем замыкание в том месте, куда мы передаём его в качестве переменной, как это было в приложении 13-1.
Как и в случае с переменными, мы можем добавить изложения видов данных, если хотим внести определенность при описании за счёт увеличения рукописи. Определение видов данных для замыкания будет выглядеть как определение в приложении 13-2. В этом примере в переменной определено замыкание, при этом мы не определяем замыкание в том месте, куда мы передаём его в качестве переменной, как это было в приложении 13-1.
<span class="filename">Имя файла: src/main.rs</span>
@ -56,7 +56,7 @@ @@ -56,7 +56,7 @@
<span class="caption">Приложение 13-2: Добавление необязательных наставлений видов свойств и возвращаемых значений в замыкании</span>
С добавлением наставлений видов данных правила написания замыканий выглядит более похожим на правила написания функций. Здесь мы, для сравнения, определяем функцию, которая добавляет 1 к своему свойству, и замыкание, которое имеет такое же поведение. Мы добавили несколько пробелов, чтобы выровнять соответствующие части. Это показывает, что правила написания замыкания похож на правила написания функции, за исключением использования труб (вертикальная черта) и количества необязательного правил написания:
С добавлением описаний видов данных, правила написания замыканий выглядят более похожими на правила написания функций. Здесь мы для сравнения, определяем функцию, которая добавляет 1 к своему значению, и замыкание, которое имеет такое же поведение. Мы добавили несколько пробелов, чтобы выровнять соответствующие части. Это показывает, что правила написания замыкания похожи на правила написания функции, за исключением использования труб (вертикальная черта) и дополнительного количества необязательных пояснений согласно правилам написания:
```rust,ignore
fn add_one_v1 (x: u32) -> u32 { x + 1 }
@ -65,9 +65,9 @@ let add_one_v3 = |x| { x + 1 }; @@ -65,9 +65,9 @@ let add_one_v3 = |x| { x + 1 };
let add_one_v4 = |x| x + 1 ;
```
В первой строке показано определение функции, а во второй - полностью определенное определение замыкания. В третьей строке мы удаляем изложении видов данных из определения замыкания. В четвёртой строке мы убираем скобки, которые являются необязательными, поскольку тело замыкания содержит только одно действие. Это всё правильные определения, которые будут иметь одинаковое поведение при вызове. Строки `add_one_v3` и `add_one_v4` требуют, чтобы замыкания были вычислены до сборки, поскольку виды данных будут выведены из их использования. Это похоже на `let v = Vec::new();`, когда в `Vec` необходимо вставить либо изложении видов данных, либо значения некоторого вида данных, чтобы Ржавчина смогла вывести вид данных.
В первой строке описано определение функции, а во второй - полностью расписано всё замыкание от начала и до конца. В третьей строке мы удаляем из изложения описания видов данных при описании замыкания. В четвёртой строке мы убираем узорчатые скобки, которые являются необязательными, поскольку тело замыкания содержит только одно действие. Все выше указанные изложения являются правильными согласно правил написания и являются равноценными с точки зрения поведения при их вызове. Строки `add_one_v3` и `add_one_v4` требуют, чтобы виды данных, используемых в замыканиях были заранее определены до сборки, поскольку виды данных не определены. Это похоже на `let v = Vec::new();`, когда для `Vec` необходимо указать вид данных, либо значения ранее определенного вида данных, чтобы Ржавчина смогла понять с каким видом данных ей предстоит выполнять действия.
Для определений замыкания сборщик выводит определенные виды данных для каждого из свойств и возвращаемого значения. Например, в приложении 13-3 показано определение короткого замыкания, которое просто возвращает значение, полученное в качестве свойства. Это замыкание не очень полезно, кроме как для целей данного примера. Обратите внимание, что мы не добавили в определение никаких наставлений видо данных. Поскольку наставлений видов данных нет, мы можем вызвать замыкание для любого вида данных, что мы и сделали в первый раз с `String`. Если затем мы попытаемся вызвать `example_closure` для целого числа, мы получим ошибку.
Для определения итога замыкания сборщик определяет виды данных для каждого из входных и возвращаемых значений. Например, в приложении 13-3 показано определение короткого замыкания, которое просто возвращает значение, полученное в качестве входного. Это замыкание бесполезно, показано для примера. Обратите внимание, что мы не указали в описании вид данных. Поскольку виды данных не определены, мы можем вызвать замыкание для любого вида данных, что мы и сделали в первый раз с `String`. Но если мы затем попытаемся вызвать `example_closure` для другого вида данных - например целого числа, мы получим ошибку.
<span class="filename">Имя файла: src/main.rs</span>
@ -75,7 +75,7 @@ let add_one_v4 = |x| x + 1 ; @@ -75,7 +75,7 @@ let add_one_v4 = |x| x + 1 ;
{{#rustdoc_include ../listings/ch13-functional-features/listing-13-03/src/main.rs:here}}
```
<span class="caption">Приложение 13-3: Попытка вызова замыкания, виды которого выводятся из двух разных видов данных</span>
<span class="caption">Приложение 13-3: Попытка вызова замыкания, при обращении к которому вкладываются разные виды данных</span>
Сборщик вернёт нам вот такую ошибку:
@ -83,13 +83,13 @@ let add_one_v4 = |x| x + 1 ; @@ -83,13 +83,13 @@ let add_one_v4 = |x| x + 1 ;
{{#include ../listings/ch13-functional-features/listing-13-03/output.txt}}
```
При первом вызове `example_closure` со значением `String` сборщик определяет вид данных `x` и возвращаемый вид данных замыкания как `String`. Эти виды данных затем определятся в замыкании в `example_closure`, и мы получаем ошибку вида данных при следующей попытке использовать другой вид данных с тем же замыканием.
При первом вызове `example_closure` со значением `String` сборщик определяет входной (`x`) и выходной вид данных для данного замыкания как `String`. Этот вид данных затем привязывается к замыканию в `example_closure`, и мы получаем ошибку из-за недопустимого вида данных при следующей попытке , так как нельзя повторно использовать другой вид данных с тем же замыканием.
### Захват ссылок или передача владения
### Получение ссылок или передача владения
Замыкания могут захватывать значения из своего окружения тремя способами, которые соответствуют тем же трём способам, которыми функция может принимать свойства: заимствование неизменяемых, заимствование изменяемых и получение владения. Замыкание самостоятельно определяет, какой из этих способов использовать, исходя из того, что тело функции делает с полученными значениями.
Замыкания могут получать значения из своего окружения тремя способами, которые соответствуют тем же трём способам, которыми функция может принимать свойства: заимствование неизменяемое, заимствование изменяемое и получение владения. Замыкание самостоятельно определяет, какой из этих способов использовать, исходя из того, что тело замыкания делает с полученными значениями.
В приложении 13-4 мы определяем замыкание, которое захватывает неизменяемую ссылку на вектор с именем `list`, поскольку неизменяемой ссылки достаточно для вывода значения:
В приложении 13-4 мы определяем замыкание, которое получает неизменяемую ссылку на вектор с именем `list`, поскольку неизменяемой ссылки достаточно для вывода значения:
<span class="filename">Имя файла: src/main.rs</span>
@ -97,17 +97,17 @@ let add_one_v4 = |x| x + 1 ; @@ -97,17 +97,17 @@ let add_one_v4 = |x| x + 1 ;
{{#rustdoc_include ../listings/ch13-functional-features/listing-13-04/src/main.rs}}
```
<span class="caption">Приложение 13-4: Определение и вызов замыкания, которое захватывает неизменяемую ссылку</span>
<span class="caption">Приложение 13-4: Определение и вызов замыкания, которое получает неизменяемую ссылку</span>
Этот пример также отображает, то что переменная может быть привязана к определению замыкания, и в дальнейшем мы можем вызвать замыкание, используя имя переменной и круглые скобки, как если бы имя переменной было именем функции.
Этот пример также отображает, то что переменная может быть привязана к вызову самого замыкания, и в дальнейшем мы можем вызвать замыкание, используя имя переменной и круглые скобки, как если бы имя переменной было именем функции.
Поскольку мы можем иметь несколько неизменяемых ссылок на `list` одновременно, `list` остаётся доступным из рукописи до определения замыкания, после определения замыкания, а также до вызова замыкания и после. Эта рукопись собирается, выполняется и выводит:
Поскольку мы можем иметь несколько неизменяемых ссылок на `list` одновременно, `list` остаётся доступным из рукописи до определения замыкания, после определения замыкания, а также до вызова замыкания и после. Итог данной рукописи:
```console
{{#include ../listings/ch13-functional-features/listing-13-04/output.txt}}
```
В следующем приложении 13-5 мы изменили тело замыкания так, чтобы оно добавляло переменную в вектор `list`. Теперь замыкание захватывает изменяемую ссылку:
В следующем приложении 13-5 мы изменили тело замыкания так, чтобы оно добавляло переменную в вектор `list`. Теперь замыкание получает изменяемую ссылку:
<span class="filename">Имя файла: src/main.rs</span>
@ -115,7 +115,7 @@ let add_one_v4 = |x| x + 1 ; @@ -115,7 +115,7 @@ let add_one_v4 = |x| x + 1 ;
{{#rustdoc_include ../listings/ch13-functional-features/listing-13-05/src/main.rs}}
```
<span class="caption">Приложение 13-5. Определение и вызов замыкания, захватывающего изменяемую ссылку</span>
<span class="caption">Приложение 13-5. Определение и вызов замыкания, получающего изменяемую ссылку</span>
Эта рукопись собирается, запускается и выводит:
@ -123,11 +123,11 @@ let add_one_v4 = |x| x + 1 ; @@ -123,11 +123,11 @@ let add_one_v4 = |x| x + 1 ;
{{#include ../listings/ch13-functional-features/listing-13-05/output.txt}}
```
Обратите внимание, что между определением и вызовом замыкания `borrows_mutably` больше нет `println!`: когда определяется `borrows_mutably`, оно захватывает изменяемую ссылку на `list`. После вызова замыкания мы больше не используем его, поэтому изменяемое заимствование заканчивается. Между определением замыкания и вызовом замыкания неизменяемое заимствование для вывода недоступно, потому что при наличии изменяемого заимствования никакие другие заимствования недопустимы. Попробуйте добавить туда `println!` и посмотрите, какое сообщение об ошибке вы получите!
Обратите внимание, что между определением и вызовом замыкания `borrows_mutably` больше нет `println!`: когда определяется `borrows_mutably`, оно получает изменяемую ссылку на `list`. После вызова замыкания мы больше не используем его, поэтому изменяемое заимствование заканчивается. Между определением замыкания и вызовом замыкания неизменяемое заимствование для вывода недоступно, потому что при наличии изменяемого заимствования никакие другие заимствования недопустимы. Попробуйте добавить туда `println!` и посмотрите, какое сообщение об ошибке вы получите!
Если вы хотите заставить замыкание принять владение значениями, которые оно использует в окружении, даже если в теле замыкания нет рукописи, требующего владения, вы можете использовать ключевое слово `move` перед списком свойств.
Если вы хотите заставить замыкание принять владение значениями, которые оно использует в окружении, даже если в теле замыкания нет рукописи, требующей владения, вы можете использовать ключевое слово `move` перед указанием свойств.
Это средства в основном полезно при передаче замыкания новому потоку, чтобы переместить данные так, чтобы они принадлежали новому потоку. Мы подробно обсудим потоки и то, зачем их использовать, в главе 16, когда будем говорить о одновременности, а пока давайте вкратце рассмотрим порождение нового потока с помощью замыкания, в котором используется ключевое слово `move`. В приложении 13-6 показана рукопись из приложения 13-4, измененный для вывода вектора в новом потоке, а не в основном потоке:
Это средство в основном полезно при передаче замыкания владения новому потоку, чтобы переместить владение данными так, чтобы ими владел новый поток. Мы подробно обсудим потоки и то, зачем их использовать, в главе 16, когда будем говорить о одновременности и многопоточности, а пока давайте вкратце рассмотрим порождение порождённого потока с помощью замыкания, в котором используется ключевое слово `move`. В приложении 13-6 показана рукопись из приложения 13-4, измененная для вывода вектора в новом потоке, а не в основном:
<span class="filename">Файл: src/main.rs</span>
@ -137,7 +137,7 @@ let add_one_v4 = |x| x + 1 ; @@ -137,7 +137,7 @@ let add_one_v4 = |x| x + 1 ;
<span class="caption">Приложение 13-6: Использование <code>move</code> для принуждения замыкания потока принять на себя владение <code>list</code></span>
Мы порождаем новый поток, передавая ему в качестве переменной замыкание для выполнения. Тело замыкания выводит список. В приложении 13-4 замыкание захватило `list` только с помощью неизменяемой ссылки, потому что это наименьше необходимый доступ к `list` для его выводе. В этом примере, несмотря на то, что тело замыкания по-прежнему требует только неизменяемой ссылки, нам нужно указать, что `list` должен быть перемещён в замыкание, поместив ключевое слово `move` в начало определения замыкания. Новый поток может завершиться раньше, чем завершится основной поток, или основной поток может завершиться первым. Если основной поток сохранил владение `list`, но завершился раньше нового потока и удалил `list`, то неизменяемая ссылка в потоке будет недействительной. Поэтому сборщик требует, чтобы `list` был перемещён в замыкание, переданное новому потоку, чтобы ссылка была действительной. Попробуйте убрать ключевое слово `move` или использовать `list` в основном потоке после определения замыкания и посмотрите, какие ошибки сборщика вы получите!
Мы порождаем новый поток, передавая ему в качестве переменной замыкание для выполнения. Тело замыкания выводит список. В приложении 13-4 замыкание получило `list` только с помощью неизменяемой ссылки, потому что это наименьший уровень доступа, необходимый для обращения к `list` для вывода. В этом примере, несмотря на то, что тело замыкания по-прежнему требует только неизменяемой ссылки, нам нужно указать, что `list` должен быть передан во владение замыканию, поместив ключевое слово `move` в начало определения замыкания. Порожденный поток может завершиться раньше, чем завершится основной поток, или основной поток может завершиться первым. Если основной поток сохранил владение `list`, но завершился раньше порождённого потока и удалил `list`, то неизменяемая ссылка в потоке будет недействительной. Поэтому сборщик требует, чтобы `list` был передан во владение замыканию, которое передаёт владение порожденному потоку, чтобы ссылка была действительной. Попробуйте убрать ключевое слово `move` или использовать `list` в основном потоке после вызова замыкания и посмотрите, какие ошибки сборщика вы получите!
<!-- Old headings. Do not remove or links may break. -->
@ -145,15 +145,15 @@ let add_one_v4 = |x| x + 1 ; @@ -145,15 +145,15 @@ let add_one_v4 = |x| x + 1 ;
<a id="limitations-of-the-cacher-implementation"></a>
<a id="moving-captured-values-out-of-the-closure-and-the-fn-traits"></a>
### Перемещение захваченных значений из замыканий и сущности `Fn`
### Перемещение полученных значений из замыканий и сущности `Fn`
После того, как замыкание захватило ссылку или владение значением из среды, в которой оно определено (тем самым влияя на то, что перемещается *в* замыкание), рукопись в теле замыкания определяет, что происходит со ссылками или значениями, в мгновение последующего выполнения замыкания (тем самым влияя на то, что перемещается *из* замыкания). Тело замыкания может делать любое из следующих действий: перемещать захваченное значение из замыкания, изменять захваченное значение, не перемещать и не изменять значение или вообще ничего не захватывать из среды.
После того, как замыкание получило ссылку или право владения значением из области видимости, в которой оно определено (тем самым влияя на то, что перемещается *в* замыкание), рукопись в теле замыкания определяет, что происходит со ссылками или значениями, во время последующего выполнения (тем самым влияя на то, что перемещается *из* замыкания). Тело замыкания может делать любое из следующих действий: перемещать полученное значение из замыкания, изменять полученное значение, не перемещать и не изменять значение или вообще ничего не получать из среды.
То, как замыкание получает и обрабатывает значения из своего окружения, указывает на то, какие сущности используют замыкание, а с помощью сущностей функции и стопки могут определять, какие виды замыканий они могут использовать. Замыканиям самостоятельно присваивается выполнение одного, двух или всех трёх из нижеперечисленных сущностей `Fn`, аддитивным образом, в зависимости от того, как тело замыкания обрабатывает значения:
1. `FnOnce` применяется к замыканиям, которые могут быть вызваны один раз. Все замыкания используют по крайней мере эту сущность, потому что все замыкания могут быть вызваны. Замыкание, которое перемещает захваченные значения из своего тела, использует только `FnOnce` и ни один из других признаков `Fn`, потому что оно может быть вызвано только один раз.
2. `FnMut` применяется к замыканиям, которые не перемещают захваченные значения из своего тела, но могут изменять захваченные значения. Такие замыкания могут вызываться более одного раза.
3. `Fn` применяется к замыканиям, которые не перемещают захваченные значения из своего тела и не изменяют захваченные значения, а также к замыканиям, которые ничего не захватывают из своего окружения. Такие замыкания могут выполняться более одного раза и не меняют ничего в своём окружении, что важно в таких случаях, как одновременный вызов замыкания несколько раз.
1. `FnOnce` применяется к замыканиям, которые могут быть вызваны один раз. Все замыкания используют по крайней мере эту сущность, потому что все замыкания могут быть вызваны. Замыкание, которое передаёт право владения на полученные значения из своего тела, использует только `FnOnce` и ни один из других признаков `Fn`, потому что оно может быть вызвано только один раз.
2. `FnMut` применяется к замыканиям, которые не передают полученные значения из своего тела, но могут изменять полученные значения. Такие замыкания могут вызываться более одного раза.
3. `Fn` применяется к замыканиям, которые не передают право владения на полученные значения из своего тела и не изменяют полученные значения, а также к замыканиям, которые ничего не получают из своего окружения. Такие замыкания могут выполняться более одного раза и не меняют ничего в своём окружении, что важно в таких случаях, как одновременный вызов замыкания несколько раз.
Давайте рассмотрим определение способа `unwrap_or_else` у `Option<T>`, который мы использовали в приложении 13-1:
@ -177,7 +177,7 @@ impl<T> Option<T> { @@ -177,7 +177,7 @@ impl<T> Option<T> {
Ограничением сущности, заданным для обобщённого вида данных `F`, является `FnOnce() -> T`, что означает, что `F` должен вызываться один раз, не принимать никаких переменных и возвращать `T`. Использование `FnOnce` в ограничении сущности говорит о том, что `unwrap_or_else` должен вызывать `f` не более одного раза. В теле `unwrap_or_else` мы видим, что если `Option` будет равен `Some`, то `f` не будет вызван. Если же значение `Option` будет равным `None`, то `f` будет вызван один раз. Поскольку все замыкания используют `FnOnce`, `unwrap_or_else` принимает самые разные виды замыканий и является настолько гибким, насколько это возможно.
> Примечание: Функции также могут использовать все три сущности `Fn`. Если то, что мы хотим сделать, не требует захвата значения из среды, мы можем передавать имя какой-либо функции, а не замыкания, когда нам нужно что-то, выполняющее одну из сущностей `Fn`. Например, для значения `Option<Vec<T>>` мы можем вызвать `unwrap_or_else(Vec::new)`, чтобы получить новый пустой вектор, если значение окажется `None`.
> Примечание: Функции также могут использовать все три сущности `Fn`. Если то, что мы хотим сделать, не требует получения значения из среды, мы можем передавать имя какой-либо функции, а не замыкания, когда нам нужно что-то, выполняющее одну из сущностей `Fn`. Например, для значения `Option<Vec<T>>` мы можем вызвать `unwrap_or_else(Vec::new)`, чтобы получить новый пустой вектор, если значение окажется `None`.
Теперь рассмотрим способ встроенной библиотеки `sort_by_key`, определённый у срезов, чтобы увидеть, чем он отличается от `unwrap_or_else` и почему `sort_by_key` использует `FnMut` вместо `FnOnce` для ограничения сущности. Замыкание принимает единственная переменная в виде ссылки на текущую переменную в рассматриваемом срезе и возвращает значение вида данных `K`, к которому применимо упорядочивание. Эта функция полезна, когда вы хотите упорядочить срез по определённому свойству каждой переменной. В приложении 13-7 у нас есть список образцов `Rectangle`, и мы используем `sort_by_key`, чтобы упорядочить их по свойству `width` от меньшего к большему:
@ -195,7 +195,7 @@ impl<T> Option<T> { @@ -195,7 +195,7 @@ impl<T> Option<T> {
{{#include ../listings/ch13-functional-features/listing-13-07/output.txt}}
```
Причина, по которой `sort_by_key` определена как принимающая замыкание `FnMut`, заключается в том, что она вызывает замыкание несколько раз: по одному разу для каждой переменной в срезе. Замыкание `|r| r.width` не захватывает, не изменяет и не перемещает ничего из своего окружения, поэтому оно удовлетворяет требованиям связанности признаков.
Причина, по которой `sort_by_key` определена как принимающая замыкание `FnMut`, заключается в том, что она вызывает замыкание несколько раз: по одному разу для каждой переменной в срезе. Замыкание `|r| r.width` не получает, не изменяет и не перемещает ничего из своего окружения, поэтому оно удовлетворяет требованиям связанности признаков.
И наоборот, в приложении 13-8 показан пример замыкания, которое использует только признак `FnOnce`, потому что оно перемещает значение из среды. Сборщик не позволит нам использовать это замыкание с `sort_by_key`:
@ -207,7 +207,7 @@ impl<T> Option<T> { @@ -207,7 +207,7 @@ impl<T> Option<T> {
<span class="caption">Приложение 13-8: Попытка использовать замыкание <code>FnOnce</code> с <code>sort_by_key</code></span>
Это надуманный, замысловатый способ (который не работает) подсчёта количества вызовов `sort_by_key` при упорядочиванию `list`. Эта рукопись пытается выполнить подсчёт, перемещая `value` - `String` из окружения замыкания - в вектор `sort_operations`. Замыкание захватывает `value`, затем перемещает `value` из замыкания, передавая владение на `value` вектору `sort_operations`. Это замыкание можно вызвать один раз; попытка вызвать его второй раз не сработает, потому что `value` уже не будет находиться в той среде, из которой его можно будет снова поместить в `sort_operations`! Поэтому это замыкание использует только `FnOnce`. Когда мы попытаемся собрать эту рукопись, мы получим ошибку сообщающую о том что `value` не может быть перемещено из замыкания, потому что замыкание должно использовать `FnMut`:
Это надуманный, замысловатый способ (который не работает) подсчёта количества вызовов `sort_by_key` при упорядочиванию `list`. Эта рукопись пытается выполнить подсчёт, перемещая `value` - `String` из окружения замыкания - в вектор `sort_operations`. Замыкание получает `value`, затем перемещает `value` из замыкания, передавая владение на `value` вектору `sort_operations`. Это замыкание можно вызвать один раз; попытка вызвать его второй раз не сработает, потому что `value` уже не будет находиться в той среде, из которой его можно будет снова поместить в `sort_operations`! Поэтому это замыкание использует только `FnOnce`. Когда мы попытаемся собрать эту рукопись, мы получим ошибку сообщающую о том что `value` не может быть перемещено из замыкания, потому что замыкание должно использовать `FnMut`:
```console
{{#include ../listings/ch13-functional-features/listing-13-08/output.txt}}

8
rustbook-ru/src/ch13-02-iterators.md

@ -110,13 +110,13 @@ pub trait Iterator { @@ -110,13 +110,13 @@ pub trait Iterator {
Вы можете выстроить цепочку из нескольких вызовов переходников повторителя для выполнения сложных действий удобном для прочтения виде. Но поскольку все повторители являются "ленивыми", для получения итогов вызовов переходников повторителя необходимо вызвать один из способов потребляющего переходника.
### Использование замыканий, которые захватывают переменные окружения
### Использование замыканий, которые получают переменные окружения
Многие переходники повторителей принимают замыкания в качестве переменных, и обычно замыкания, которые мы будем указывать в качестве переменных переходникам повторителей, это замыкания, которые определяют (захватывают) своё окружение.
Многие переходники повторителей принимают замыкания в качестве переменных, и обычно замыкания, которые мы будем указывать в качестве переменных переходникам повторителей, это замыкания, которые определяют (получают) своё окружение.
В этом примере мы будем использовать способ `filter`, который принимает замыкание. Замыкание получает переменную из повторителя и возвращает `bool`. Если замыкание возвращает `true`, значение будет включено в повторение, создаваемую `filter`. Если замыкание возвращает `false`, значение не будет включено.
В приложении 13-16 мы используем `filter` с замыканием, которое захватывает переменную `shoe_size` из своего окружения для повторения по собрания образцов стопки `Shoe`. Он будет возвращать обувь только указанного размера.
В приложении 13-16 мы используем `filter` с замыканием, которое получает переменную `shoe_size` из своего окружения для повторения по собрания образцов стопки `Shoe`. Он будет возвращать обувь только указанного размера.
<span class="filename">Файл: src/lib.rs</span>
@ -130,6 +130,6 @@ pub trait Iterator { @@ -130,6 +130,6 @@ pub trait Iterator {
В теле `shoes_in_my_size` мы вызываем `into_iter` чтобы создать повторитель , который становится владельцем вектора. Затем мы вызываем `filter`, чтобы превратить этот повторитель в другой, который содержит только переменные, для которых замыкание возвращает `true`.
Замыкание захватывает свойство `shoe_size` из окружения и сравнивает его с размером каждой пары обуви, оставляя только обувь указанного размера. Наконец, вызов `collect` собирает значения, возвращаемые приспособленным повторителем, в вектор, возвращаемый функцией.
Замыкание получает свойство `shoe_size` из окружения и сравнивает его с размером каждой пары обуви, оставляя только обувь указанного размера. Наконец, вызов `collect` собирает значения, возвращаемые приспособленным повторителем, в вектор, возвращаемый функцией.
Проверка показывает, что когда мы вызываем `shoes_in_my_size`, мы возвращаем только туфли, размер которых совпадает с указанным нами значением.

2
rustbook-ru/src/ch15-05-interior-mutability.md

@ -161,7 +161,7 @@ @@ -161,7 +161,7 @@
{{#include ../listings/ch15-smart-pointers/listing-15-24/output.txt}}
```
Это средства довольно изящно! Используя `RefCell<T>`, мы получаем внешне неизменяемое значение `List`. Но мы можем использовать способы `RefCell<T>`, которые предоставляют доступ к его внутренностям, чтобы мы могли изменять наши данные, когда это необходимо. Проверка правил заимствования во время выполнения защищает нас от гонок данных, и иногда стоит немного пожертвовать производительностью ради такой гибкости наших стопок данных. Обратите внимание, что `RefCell<T>` не работает для многопоточного рукописи! `Mutex<T>` - это thread-safe исполнение `RefCell<T>`, а `Mutex<T>` мы обсудим в главе 16.
Это средство довольно изящно! Используя `RefCell<T>`, мы получаем внешне неизменяемое значение `List`. Но мы можем использовать способы `RefCell<T>`, которые предоставляют доступ к его внутренностям, чтобы мы могли изменять наши данные, когда это необходимо. Проверка правил заимствования во время выполнения защищает нас от гонок данных, и иногда стоит немного пожертвовать производительностью ради такой гибкости наших стопок данных. Обратите внимание, что `RefCell<T>` не работает для многопоточного рукописи! `Mutex<T>` - это thread-safe исполнение `RefCell<T>`, а `Mutex<T>` мы обсудим в главе 16.
["Где находится приказчик `->`?"]: ch05-03-method-syntax.html#wheres-the---operator

12
rustbook-ru/src/ch16-01-threads.md

@ -118,9 +118,9 @@ changes in the compiler --> @@ -118,9 +118,9 @@ changes in the compiler -->
### Использование `move`-замыканий в потоках
Мы часто используем ключевое слово `move` с замыканиями, переданными в `thread::spawn`, потому что в этом случае замыкание получает из окружения права владения на используемые им значения, таким образом передавая права владения этими значениями от одного потока к другому. В разделе ["Захват ссылок или перемещение прав владения"] Главы 13 мы обсудили `move` в среде замыканий. Теперь мы сосредоточимся на взаимодействии между `move` и `thread::spawn`.
Мы часто используем ключевое слово `move` с замыканиями, переданными в `thread::spawn`, потому что в этом случае замыкание получает из окружения права владения на используемые им значения, таким образом передавая права владения этими значениями от одного потока к другому. В разделе ["Получение ссылок или перемещение прав владения"] Главы 13 мы обсудили `move` в среде замыканий. Теперь мы сосредоточимся на взаимодействии между `move` и `thread::spawn`.
Обратите внимание, что в приложении 16-1 замыкание, которое мы передаём в `thread::spawn` не принимает переменных: мы не используем никаких данных из основного потока в рукописи порождённого потока. Чтобы использовать данные из основного потока в порождённом потоке, замыкание порождённого потока должно захватывать значения, которые ему необходимы. Приложение 16-3 показывает попытку создать вектор в главном потоке и использовать его в порождённом потоке. Тем не менее, это не будет работать, как вы увидите через мгновение.
Обратите внимание, что в приложении 16-1 замыкание, которое мы передаём в `thread::spawn` не принимает переменных: мы не используем никаких данных из основного потока в рукописи порождённого потока. Чтобы использовать данные из основного потока в порождённом потоке, замыкание порождённого потока должно получать значения, которые ему необходимы. Приложение 16-3 показывает попытку создать вектор в главном потоке и использовать его в порождённом потоке. Тем не менее, это не будет работать, как вы увидите через мгновение.
<span class="filename">Файл: src/main.rs</span>
@ -130,13 +130,13 @@ changes in the compiler --> @@ -130,13 +130,13 @@ changes in the compiler -->
<span class="caption">Приложение 16-3: Попытка использовать вектор, созданный основным потоком, в другом потоке</span>
Замыкание использует переменную `v`, поэтому оно захватит `v` и сделает его частью окружения замыкания. Поскольку `thread::spawn` запускает это замыкание в новом потоке, мы должны иметь доступ к `v` внутри этого нового потока. Но при сборке этого примера, мы получаем следующую ошибку:
Замыкание использует переменную `v`, поэтому оно получит `v` и сделает его частью окружения замыкания. Поскольку `thread::spawn` запускает это замыкание в новом потоке, мы должны иметь доступ к `v` внутри этого нового потока. Но при сборке этого примера, мы получаем следующую ошибку:
```console
{{#include ../listings/ch16-fearless-concurrency/listing-16-03/output.txt}}
```
Ржавчина *выводит* как захватить `v` и так как в `println!` нужна только ссылка на `v`, то замыкание пытается заимствовать `v`. Однако есть неполадка: Ржавчина не может определить, как долго будет работать порождённый поток, поэтому он не знает, будет ли всегда действительной ссылка на `v`.
Ржавчина *выводит* как получить `v` и так как в `println!` нужна только ссылка на `v`, то замыкание пытается заимствовать `v`. Однако есть неполадка: Ржавчина не может определить, как долго будет работать порождённый поток, поэтому он не знает, будет ли всегда действительной ссылка на `v`.
В приложении 16-4 приведён задумка, который с большей вероятностью будет иметь ссылку на `v`, что будет недопустимо:
@ -146,7 +146,7 @@ changes in the compiler --> @@ -146,7 +146,7 @@ changes in the compiler -->
{{#rustdoc_include ../listings/ch16-fearless-concurrency/listing-16-04/src/main.rs}}
```
<span class="caption">Приложение 16-4. Поток с замыканием, который пытается захватить ссылку на <code>v</code> из основного потока, удаляющего <code>v</code></span>
<span class="caption">Приложение 16-4. Поток с замыканием, который пытается получить ссылку на <code>v</code> из основного потока, удаляющего <code>v</code></span>
Если бы Ржавчина позволил нам запустить эту рукопись, есть вероятность, что порождённый поток был бы немедленно переведён в фоновый режим, не выполнив ничего. Порождённый поток имеет ссылку на `v`, но основной поток немедленно удаляет `v` , используя функцию `drop` , которую мы обсуждали в главе 15. Затем, когда порождённый поток начинает выполняться, `v` уже не существует, поэтому ссылка на него также будет недействительной. О, нет!
@ -184,4 +184,4 @@ help: to force the closure to take ownership of `v` (and any other referenced va @@ -184,4 +184,4 @@ help: to force the closure to take ownership of `v` (and any other referenced va
Имея достаточное понимание потоков и API потоков, давайте посмотрим, что мы можем *делать* с помощью потоков.
["Захват ссылок или перемещение прав владения"]: ch13-01-closures.html#capturing-references-or-moving-ownership
["Получение ссылок или перемещение прав владения"]: ch13-01-closures.html#capturing-references-or-moving-ownership

2
rustbook-ru/src/ch17-02-concurrency-with-async.md

@ -296,7 +296,7 @@ future, пока он не будет готов. Как только приде @@ -296,7 +296,7 @@ future, пока он не будет готов. Как только приде
Прямо сейчас несогласованный блок, в который мы отправляем сообщения, заимствует только `tx`,
потому что отправка сообщения не требует владения, но если бы мы могли переместить `tx` в этот
несогласованный блок, он был бы удален, как только этот раздел закончится. В разделе Главы 13
[Захват ссылок или перемещение владения][capture-or-move]<!-- ignore --> вы
[Получение ссылок или перемещение владения][capture-or-move]<!-- ignore --> вы
узнали, как использовать ключевое слово `move` с замыканиями, и, как обсуждалось в разделе
Главы 16 [Использование замыканий `move` с потоками][move-threads]<!-- ignore
-->, нам часто нужно перемещать данные в замыкания при работе с потоками.

2
rustbook-ru/src/ch19-03-pattern-syntax.md

@ -338,7 +338,7 @@ @@ -338,7 +338,7 @@
<span class="caption">Приложение 18-29: Использование <code>@</code> для привязывания значения в образце, с одновременной его проверкой</span>
В этом примере будет выведено `Found an id in range: 5`. Указывая `id_variable @` перед рядом `3..=7`, мы захватываем любое значение, попадающее в ряд, одновременно проверяя, что это значение соответствует ряду в образце.
В этом примере будет выведено `Found an id in range: 5`. Указывая `id_variable @` перед рядом `3..=7`, мы получаем любое значение, попадающее в ряд, одновременно проверяя, что это значение соответствует ряду в образце.
Во второй ветке, где у нас в образце указан только ряд, рукопись этой ветки не имеет переменной, которая содержит действительное значение поля `id`. Значение поля `id` могло бы быть 10, 11 или 12, но рукопись, соответствующую этому образцу данных, не знает, чему оно равно. Рукопись образца не может использовать значение из поля `id`, потому что мы не сохранили значение `id` в переменной.

2
rustbook-ru/src/ch20-02-advanced-traits.md

@ -131,7 +131,7 @@ trait Add<Rhs = Self> { @@ -131,7 +131,7 @@ trait Add<Rhs = Self> {
Указание имени сущности перед именем способа проясняет сборщику Ржавчина, какую именно использование `fly` мы хотим вызвать. Мы могли бы также написать `Human::fly(&person)`, что равнозначно используемому нами `person.fly()` в приложении 19-18, но это писание немного длиннее, когда нужна неоднозначность.
Выполнение этой рукописи выводит следующее:
Итог выполнения рукописи:
```console
{{#include ../listings/ch20-advanced-features/listing-19-18/output.txt}}

4
rustbook-ru/src/ch21-02-multithreaded.md

@ -128,7 +128,7 @@ @@ -128,7 +128,7 @@
Теперь мы ошибка возникает из-за того, что у нас нет способа `execute` в стопке `ThreadPool`. Вспомните раздел ["Создание конечного числа потоков"](#creating-a-finite-number-of-threads)<!-- ignore -->, в котором мы решили, что наш объединение потоков должно иметь внешнюю оболочку, похожий на `thread::spawn`. Кроме того, мы выполняем функцию `execute`, чтобы она принимала замыкание и передавала его свободному потоку из объединения для запуска.
Мы определим способ `execute` у `ThreadPool`, принимающий замыкание в качестве свойства. Вспомните из раздела ["Перемещение захваченных значений из замыканий и сущности `Fn`"](ch13-01-closures.html#moving-captured-values-out-of-the-closure-and-the-fn-traits) <!-- ignore --> Главы 13 сведения о том, что мы можем принимать замыкания в качестве свойств тремя различными сущностями: `Fn` , `FnMut` и `FnOnce`. Нам нужно решить, какой вид данных замыкания использовать здесь. Мы знаем, что в конечном счёте мы сделаем что-то похожее на выполнение встроенной библиотеки `thread::spawn`, поэтому мы можем посмотреть, какие ограничения накладывает на свой свойство ярлык функции `thread::spawn`. Пособие показывает следующее:
Мы определим способ `execute` у `ThreadPool`, принимающий замыкание в качестве свойства. Вспомните из раздела ["Перемещение полученных значений из замыканий и сущности `Fn`"](ch13-01-closures.html#moving-captured-values-out-of-the-closure-and-the-fn-traits) <!-- ignore --> Главы 13 сведения о том, что мы можем принимать замыкания в качестве свойств тремя различными сущностями: `Fn` , `FnMut` и `FnOnce`. Нам нужно решить, какой вид данных замыкания использовать здесь. Мы знаем, что в конечном счёте мы сделаем что-то похожее на выполнение встроенной библиотеки `thread::spawn`, поэтому мы можем посмотреть, какие ограничения накладывает на свой свойство ярлык функции `thread::spawn`. Пособие показывает следующее:
```rust,ignore
pub fn spawn<F, T>(f: F) -> JoinHandle<T>
@ -332,7 +332,7 @@ pub fn spawn<F, T>(f: F) -> JoinHandle<T> @@ -332,7 +332,7 @@ pub fn spawn<F, T>(f: F) -> JoinHandle<T>
<span class="caption">Приложение 20-20: Получение и выполнение заданий в потоке "работника"</span>
Здесь мы сначала вызываем `lock` у `receiver`, чтобы получить взаимное исключение, а затем вызываем `unwrap`, чтобы со сбоем завершить работу при любых ошибках. Захват запрета может завершиться неудачей, если взаимное исключение находится в *отравленном* состоянии (poisoned state), что может произойти, если какой-то другой поток завершился со сбоем, удерживая запрет, вместо снятия запрета. В этой случае вызвать `unwrap` для со сбоем завершения потока вполне оправдано. Не стесняйтесь заменить `unwrap` на `expect` с сообщением об ошибке, которое имеет для вас значение.
Здесь мы сначала вызываем `lock` у `receiver`, чтобы получить взаимное исключение, а затем вызываем `unwrap`, чтобы со сбоем завершить работу при любых ошибках. Получение запрета может завершиться неудачей, если взаимное исключение находится в *отравленном* состоянии (poisoned state), что может произойти, если какой-то другой поток завершился со сбоем, удерживая запрет, вместо снятия запрета. В этой случае вызвать `unwrap` для со сбоем завершения потока вполне оправдано. Не стесняйтесь заменить `unwrap` на `expect` с сообщением об ошибке, которое имеет для вас значение.
Если мы получили запрет взаимного исключения, мы вызываем `recv`, чтобы получить `Job` из потока. Последний вызов `unwrap` позволяет миновать любые ошибки, которые могут возникнуть, если поток, управляющий отправитель, прекратил исполняться, подобно тому, как способ `send` возвращает `Err`, если получатель не принимает сообщение.

BIN
заимствованные слова1.xlsx

Binary file not shown.
Loading…
Cancel
Save