以下は、MichaelSnoimanによるRustCrash Courseシリーズの一部の翻訳です。これは、所有権の転送方法に関するパラメーター受け渡しメカニズム、反復子、およびクロージャーに焦点を当て、可変性と存続期間に関連しています。
また、著者のスタイルにできるだけ近い形で翻訳しようとしましたが、意味にとってあまり重要ではないいくつかのインタードームと感嘆符を減らしました。
パラメータタイプ
まず、誤解の可能性に対処したいと思います。これは、必須の人々が直面しない「私の脳はハスケルによって損傷を受けた」という妄想の1つである可能性があるため、自分自身や他のハスケリストに対する冗談を前もってお詫びします。
2つの関数の型署名は一致していますか?
fn foo(mut person: Person) { unimplemented!() }
fn bar(person: Person ) { unimplemented!() }
: " !". , (exactly the same). (inner mutability) person
, . person
, . : , foo
:
fn main() {
let alice = Person { name: String::from("Alice"), age: 30 };
foo(alice); // !
}
:
fn baz(person: &Person) { unimplemented!() }
fn bin(person: &mut Person) { unimplemented!() }
-, , baz
, bin
foo
. Person
, Person
. baz
bin
? ? , foo
bar
, , mut
— . !
:
fn main() {
let mut alice = Person { name: String::from("Alice"), age: 30 };
baz(&alice); //
bin(&alice); // !
bin(&mut alice); //
}
bin
, bin
, . . , : , , ( 2).
, :
- ( )
foo
- ,
baz
- ,
bin
, , , , , . (. , , ; foo
, baz
bin
person
).
vs.
. , ? ! birthday
, - 1.
#[derive(Debug)]
struct Person {
name: String,
age: u32,
}
fn birthday_immutable(person: Person) -> Person {
Person {
name: person.name,
age: person.age + 1,
}
}
fn birthday_mutable(mut person: Person) -> Person {
person.age += 1;
person
}
fn main() {
let alice1 = Person { name: String::from("Alice"), age: 30 };
println!("Alice 1: {:?}", alice1);
let alice2 = birthday_immutable(alice1);
println!("Alice 2: {:?}", alice2);
let alice3 = birthday_mutable(alice2);
println!("Alice 3: {:?}", alice3);
}
:
-
_immutable
,Person
,Person
. Rust, , . - , , .
-
alice1
alice2
main
, (move) . alice2
— , , .
vs.
, Rust: — (it's unusual). , . , mut
.
, : , ('
) (lifetime parameters), , . , " ". . , Rust Book.
, , , , .
#[derive(Debug)]
struct Person {
name: String,
age: u32,
}
fn birthday_immutable(person: &mut Person) {
person.age += 1;
}
fn birthday_mutable<'a>(mut person: &'a mut Person, replacement: &'a mut Person) {
person = replacement;
person.age += 1;
}
fn main() {
let mut alice = Person { name: String::from("Alice"), age: 30 };
let mut bob = Person { name: String::from("Bob"), age: 20 };
println!("Alice 1: {:?}, Bob 1: {:?}", alice, bob);
birthday_immutable(&mut alice);
println!("Alice 2: {:?}, Bob 2: {:?}", alice, bob);
birthday_mutable(&mut alice, &mut bob);
println!("Alice 3: {:?}, Bob 3: {:?}", alice, bob);
}
// does not compile
fn birthday_immutable_broken<'a>(person: &'a mut Person, replacement: &'a mut Person) {
person = replacement;
person.age += 1;
}
birtday_immutable
. , . , . : , , (: person
. , , ).
birthday_mutable
— , . : person
replacement
. , person
. , — (person = replacement
). , person
, , . , , , , person
:
warning: value passed to `person` is never read
, main
bob
alice
. ? , . , main
, .
, birthday_immutable_broken
. , . , person
, .
: , , , .
vs.
, , . , , . , , .
:
fn needs_mutable(x: &mut u32) {
*x *= 2;
}
fn needs_immutable(x: &u32) {
println!("{}", x);
}
fn main() {
let mut x: u32 = 5;
let y: &mut u32 = &mut x;
needs_immutable(y);
needs_mutable(y);
needs_immutable(y);
}
, , , . y
&mut u32
, needs_immutable
, &u32
. , .
: , , , , ( , ).
:
, . , , . , . , , , . , , .
1
, 10. .
fn double(mut x: u32) {
x *= 2;
}
fn main() {
let x = 5;
double(x);
println!("{}", x);
}
: , (asterisk, *
) , (dereference) (. — — , , ).
//
fn double(x: &mut u32) {
//
// ,
*x *= 2;
}
fn main() {
//
let mut x = 5;
//
double(&mut x);
println!("{}", x);
}
?
fn main() {
let nums = vec![1, 2, 3, 4, 5];
for i in nums {
println!("{}", i);
}
}
, 1 5. ?
fn main() {
for i in 1..3 {
let nums = vec![1, 2, 3, 4, 5];
for j in nums {
println!("{},{}", i, j);
}
}
}
1,1
, 1,2
, ..., 2,1
, ..., 2,5
. - . nums
. ?
fn main() {
let nums = vec![1, 2, 3, 4, 5];
for i in 1..3 {
for j in nums {
println!("{},{}", i, j);
}
}
}
. .
error[E0382]: use of moved value: `nums` --> main.rs:4:18 | 4 | for j in nums { | ^^^^ value moved here in previous iteration of loop | = note: move occurs because `nums` has type `std::vec::Vec<i32>`, which does not implement the `Copy` trait error: aborting due to previous error
. , , (move) nums
. , , nums
. .
, nums
for
. , . . , nums
. ()!
nums
, (borrowing)? , !
fn main() {
let nums = vec![1, 2, 3, 4, 5];
for i in 1..3 {
for j in &nums {
println!("{},{}", i, j);
}
}
}
, : j
? . println!
, :
let _: u32 = j;
error[E0308]: mismatched types --> src/main.rs:5:26 | 5 | let _: u32 = j; | --- ^ | | | | | expected `u32`, found `&{integer}` | | help: consider dereferencing the borrow: `*j` | expected due to this
, :
let _: &u32 = j;
nums
, , . " " ? !
fn main() {
let nums = vec![1, 2, 3, 4, 5];
for i in 1..3 {
for j in &mut nums {
let _: &mut u32 = j;
println!("{},{}", i, j);
*j *= 2;
}
}
}
. . . , , .
fn main() {
// nums
let mut nums = vec![1, 2, 3, 4, 5];
for i in 1..3 {
for j in &mut nums {
let _: &mut u32 = j;
println!("{},{}", i, j);
*j *= 2;
}
}
}
, . , , .
vec
, . ,
for j in &mut nums {
```Rust
```Rust
for j in nums.iter_mut() {
:
pub fn iter_mut(&mut self) -> IterMut<T>
iter()
, :
fn main() {
let nums = vec![1, 2, 3, 4, 5];
for i in 1..3 {
for j in nums.iter() {
let _: &u32 = j;
println!("{}, {}", i, j);
}
}
}
? into_iter()
. , (into) , ( , nums
Vec
). . , let nums
:
fn main() {
let nums = vec![1, 2, 3, 4, 5];
for i in 1..3 {
for j in nums.into_iter() {
println!("{}, {}", i, j);
}
}
}
fn main() {
for i in 1..3 {
// nums into_iter()
//
let nums = vec![1, 2, 3, 4, 5];
for j in nums.into_iter() {
println!("{}, {}", i, j);
}
}
}
for
, . for
, . into_iter()
, IntoIterator
. for x in y
, into_iter()
y
. , Iterator
.
2
, IntoIterator
InfiniteUnit
. Iterator
! , . ( : , ).
struct InfiniteUnit;
fn main() {
let mut count = 0;
for _ in InfiniteUnit {
count += 1;
println!("count == {}", count);
if count >= 5 {
break;
}
}
}
struct InfiniteUnit;
impl IntoIterator for InfiniteUnit {
type Item = ();
type IntoIter = InfiniteUnitIter;
fn into_iter(self) -> Self::IntoIter {
InfiniteUnitIter
}
}
struct InfiniteUnitIter;
impl Iterator for InfiniteUnitIter {
type Item = ();
fn next(&mut self) -> Option<()> {
Some(())
}
}
fn main() {
let mut count = 0;
for _ in InfiniteUnit {
count += 1;
println!("count == {}", count);
if count >= 5 {
break;
}
}
}
, .. repeat
, . .
struct InfiniteUnit;
impl IntoIterator for InfiniteUnit {
type Item = ();
type IntoIter = std::iter::Repeat<()>;
fn into_iter(self) -> Self::IntoIter {
std::iter::repeat(())
}
}
fn main() {
let mut count = 0;
for _ in InfiniteUnit {
count += 1;
println!("count == {}", count);
if count >= 5 {
break;
}
}
}
, (flavors), :
into_iter
— ,iter
—iter_mut()
—
iter_mut()
, .
, . , (local scope). .
: , , , . , , , . , . , , , JS.
. , ?
fn main() {
fn say_hi() {
let msg: &str = "Hi!";
println!("{}", msg);
};
say_hi();
say_hi();
}
. :
fn main() {
let msg: &str = "Hi!";
fn say_hi() {
println!("{}", msg);
};
say_hi();
say_hi();
}
, :
error[E0434]: can't capture dynamic environment in a fn item --> main.rs:4:24 | 4 | println!("{}", msg); | ^^^ | = help: use the `|| { ... }` closure form instead error: aborting due to previous error
, : . :
fn main() {
let msg: &str = "Hi!";
let say_hi = || {
println!("{}", msg);
};
say_hi();
say_hi();
}
( ||
), . .
: let say_hi = || println!("{}", msg);
, .
3
, say_hi
: msg
. fn
.
:
fn main() {
let msg: &str = "Hi!";
let say_hi = |msg| println!("{}", msg);
say_hi(msg);
say_hi(msg);
}
:
fn main() {
let msg: &str = "Hi!";
fn say_hi(msg: &str) {
println!("{}", msg);
}
say_hi(msg);
say_hi(msg);
}
, say_hi
.
say_hi
? , : , . , , u32
, :
fn main() {
let msg: &str = "Hi!";
let say_hi: u32 = |msg| println!("{}", msg);
}
:
error[E0308]: mismatched types --> src/main.rs:3:23 | 3 | let say_hi: u32 = |msg| println!("{}", msg); | --- ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `u32`, found closure | | | expected due to this | = note: expected type `u32` found closure `[closure@src/main.rs:3:23: 3:48]`
[closure@main.rs:3:23: 3:48]
… , :
fn main() {
let msg: &str = "Hi!";
let say_hi: [closure@main.rs:3:23: 3:48] = |msg| println!("{}", msg);
}
:
error: expected one of `!`, `(`, `+`, `::`, `;`, `<`, or `]`, found `@` --> src/main.rs:3:25 | 3 | let say_hi: [closure@main.rs:3:23: 3:48] = |msg| println!("{}", msg); | ------ ^ expected one of 7 possible tokens | | | while parsing the type for `say_hi`
. ?
. . . , ? , :
fn main() {
let say_message = |msg: &str| println!("{}", msg);
call_with_hi(say_message);
call_with_hi(say_message);
}
fn call_with_hi<F>(f: F) {
f("Hi!");
}
msg
. , -, , . . , .
F
, . F
, . , :
error[E0618]: expected function, found `F` --> src/main.rs:8:5 | 7 | fn call_with_hi<F>(f: F) { | - `F` defined here 8 | f("Hi!"); | ^------- | | | call expression requires function
: , F
. - , : Fn
!
fn call_with_hi<F>(f: F)
where F: Fn(&str) -> ()
{
f("Hi!");
}
F
, , &str
, . , -, .
fn call_with_hi<F>(f: F)
where F: Fn(&str)
{
f("Hi!");
}
, Fn
, .
4
say_message
main
, .
fn main() {
call_with_hi(say_message);
call_with_hi(say_message);
}
fn say_message(msg: &str) {
println!("{}", msg);
}
fn call_with_hi<F>(f: F)
where F: Fn(&str)
{
f("Hi!");
}
say_message
, . .
fn main() {
let name = String::from("Alice");
let say_something = |msg: &str| println!("{}, {}", msg, name);
call_with_hi(say_something);
call_with_hi(say_something);
call_with_bye(say_something);
call_with_bye(say_something);
}
fn call_with_hi<F>(f: F)
where F: Fn(&str)
{
f("Hi");
}
fn call_with_bye<F>(f: F)
where F: Fn(&str)
{
f("Bye");
}
-? !
fn main() {
let mut count = 0;
for _ in 1..6 {
count += 1;
println!("You are visitor #{}", count);
}
}
, ! .
fn main() {
let mut count = 0;
let visit = || {
count += 1;
println!("You are visitor #{}", count);
};
for _ in 1..6 {
visit();
}
}
:
error[E0596]: cannot borrow `visit` as mutable, as it is not declared as mutable --> src/main.rs:9:9 | 3 | let visit = || { | ----- help: consider changing this to be mutable: `mut visit` ... 9 | visit(); | ^^^^^ cannot borrow as mutable
… ? , . , . - . ?
: visit
(captured) count
. , visit
count
. . ? ? , , :
fn main() {
let mut count = 0;
let visit = || {
count += 1;
println!("You are visitor #{}", count);
};
call_five_times(visit);
}
fn call_five_times<F>(f: F)
where F: Fn()
{
for _ in 1..6 {
f();
}
}
:
error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnMut`
! : , (Fn
), , (FnMut
). Fn
FnMut
where
. :
error[E0596]: cannot borrow immutable argument `f` as mutable --> main.rs:16:9 | 11 | fn call_five_times<F>(f: F) | - help: make this binding mutable: `mut f` ... 16 | f(); | ^ cannot borrow mutably
, . mut
f: F
.
?
Fn
FnMut
?
|| println!("Hello World!");
- , , Fn
. , call_five_times
, FnMut
, ? — ! , :
call_five_times(|| println!("Hello World!"));
, Fn
FnMut
. , : , , , . , (FnMut
) , (Fn
) .
(subtyping)? , .
?
, " ", . , , . , , . — (value/move semantics).
, (moves) . String
(Copy
able) u32
. , . , .
fn main() {
let name = String::from("Alice");
let welcome = || {
let name = name; //
println!("Welcome, {}", name);
};
welcome();
}
name
welcome
. let name = name;
. , name
? :
fn main() {
let name1 = String::from("Alice");
let welcom = || {
let mut name2 = name1;
name2 += " and Bob";
println!("Welcome, {}", name2);
};
welcome();
}
name1
. name2
, , . — , . ? name1
, welcome()
.
. call_five_times
? welcome
:
fn main() {
let name = String::from("Alice");
let welcome = || {
let mut name = name;
name += " and Bob";
println!("Welcome, {}", name);
};
call_five_times(welcome);
}
fn call_five_times<F>(f: F)
where
F: Fn(),
{
for _ in 1..6 {
f();
}
}
, FnOnce
:
error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnOnce` --> main.rs:4:19 | 4 | let welcome = || { | ^^ this closure implements `FnOnce`, not `Fn` 5 | let mut name = name; | ---- closure is `FnOnce` because it moves the variable `name` out of its environment ... 10 | call_five_times(welcome); | --------------- the requirement to implement `Fn` derives from here
Fn()
FnOnce()
, ? !
error[E0382]: use of moved value: `f` --> main.rs:18:9 | 18 | f(); | ^ value moved here in previous iteration of loop | = note: move occurs because `f` has type `F`, which does not implement the `Copy` trait
f
. , f
, . , . FnOnce
.
, :
fn main() {
let name = String::from("Alice");
let welcome = || {
let mut name = name;
name += " and Bob";
println!("Welcome, {}", name);
};
call_once(welcome);
}
fn call_once<F>(f: F)
where
F: FnOnce()
{
f();
}
.
, Fn
FnMut
, , , . , Fn
FnOnce
FnOnce
, , , , .
move
, , , ( ). "Rust by Example" . , .
, . , , . , . , , . , :
fn pass_by_value(_x: String) {}
fn pass_by_ref(_x: &String) {}
fn pass_by_mut_ref(x: &mut String) {
pass_by_ref(x); //
pass_by_value(*x); //
}
fn main() {}
, . , (implicit). , . . , - , , (captured), , , .
, , , , :
- ,
- , . , (is dropped), .
- , - ( , ).
, :
, — .
, , . : , . :
fn main() {
// owned by main
let name_outer = String::from("Alice");
let say_hi || {
// force a move, again, we'll get smarter in a second
let name_inner = name_outer;
println!("Hello, {}", name_inner);
};
// main no longer owns name_outer, try this:
println!("Using name from main: {}", name_outer); // error!
// but name_inner lives on, in say_hi!
say_hi(); // success
}
, () — name_outer
, .
, . let name_inner = name_outer;
. name_outer
. , , name_outer
. ( say_hi()
). , . . , , name_outer
:
fn main() {
// owned by main
let name_outer = String::from("Alice");
let say_hi || {
// use by ref
let name_inner = &name_outer;
println!("Hello, {}", name_inner);
};
// main still owns name_outer, this is fine
println!("Using name from main: {}", name_outer); // success
// but name_inner lives on, in say_hi!
say_hi(); // success
say_hi(); // success
}
, , name_outer
say_hi
, !
fn main() {
let say_hi = { //
//
let name_outer = String::from("Alice");
// ,
|| {
// use by ref
let name_inner = &name_outer;
println!("Hello, {}", name_inner);
}
};
// , name_outer
// println!("Using name from main: {}", name_outer); // error!
say_hi();
say_hi();
}
, - : " , , , ( — .)". , . , move
:
fn main() {
let say_hi = {
let name_outer = String::from("Alice");
move || {
let name_inner = &name_outer;
println!("Hello, {}", name_inner);
}
}
say_hi();
say_hi();
}
name_outer
. - , , .
. move
, , . , :
fn main() {
let name = String::from("Alice");
let _ = move || { println!("Hello, {}", name) };
println!("Using name from main: {}", name); // error!
}
Rust
, . . , , , ? , : . Rust by Example:
, , .
let name_inner = name_outer;
. , , ( ), . .
- , .
- , , .
- , , .
, . , . , , , , .
, , move
, .
, , , move
. , , : " , " .
: ,
:
- , .
- , , , , .
- , , . , , .
- ,
move
. - :
- - ,
FnOnce
. - , - ,
FnMut
,FnOnce
. -
Fn
,FnMut
FnOnce
.
- - ,
, , , , , . Rust by example.
, :
fn call_fn<F>(f: F) where F: Fn() {
f()
}
fn call_fn_mut<F>(mut f: F) where F: FnMut() {
f()
}
fn call_fn_once<F>(f: F) where F: FnOnce() {
f()
}
main
:
fn main() {
let name = String::from("Alice");
let say_hi = || println!("Hello, {}", name);
call_fn(say_hi);
call_fn_mut(say_hi);
call_fn_once(say_hi);
}
name
, say_hi
, , , , name
. , say_hi
Fn
, FnMut
FnOnce
, .
// bad!
fn main() {
let say_hi = {
let name = String::from("Alice");
|| println!("Hello, {}", name)
};
}
, . name
. , , , . , , :
fn main() {
let say_hi = {
let name = String::from("Alice");
|| {
let name = name;
println!("Hello, {}", name)
}
};
// call_fn(say_hi);
// call_fn_mut(say_hi);
call_fn_once(say_hi);
}
FnOnce
, , . ! name
, ( - — ):
fn main() {
let say_hi = {
let name = String::from("Alice");
move || println!("Hello, {}", name)
};
call_fn(&say_hi);
call_fn_mut(&say_hi);
call_fn_once(&say_hi);
}
, Fn
, FnMut
FnOnce
. , say_hi
, call_fn
. ( ), , , . ( — .) , .
fn main() {
let say_hi = {
let name = String::from("Alice");
|| std::mem::drop(name)
};
//call_fn(say_hi);
//call_fn_mut(say_hi);
call_fn_once(say_hi);
}
drop
name
. , , , . , move
, .
fn main() {
let mut say_hi = {
let mut name = String::from("Alice");
move || {
name += " and Bob";
println!("Hello, {}", name);
}
};
//call_fn(say_hi);
call_fn_mut(&mut say_hi);
call_fn_once(&mut say_hi);
}
+=
String
, . . , name
. name
, (move
) . say_hi
, mut
.
say_hi
, &mut
, (1) , , (2) . call_fn
, FnMut
FnOnce
, Fn
.
? " and Bob"
name
?
fn main() {
let mut name = String::from("Alice");
let mut say_hi = || {
name += " and Bob";
println!("Hello, {}", name);
};
//call_fn(say_hi);
call_fn_mut(&mut say_hi);
call_fn_once(&mut say_hi);
}
name
, .
// bad!
fn main() {
let mut name = String::from("Alice");
let mut say_hi = || {
name += " and Bob";
println!("Hello, {}", name);
};
//call_fn(say_hi);
call_fn_mut(&mut say_hi);
call_fn_once(&mut say_hi);
println!("And now name is: {}", name);
}
say_hi
, println!
, name
, . - (lexical lifetimes). ( ) " " (non-lexical lifetimes), #![feature(nll)]
. , :
fn main() {
let mut name = String::from("Alice");
{
let mut say_hi = || {
name += " and Bob";
println!("Hello, {}", name);
};
//call_fn(say_hi);
call_fn_mut(&mut say_hi);
call_fn_once(&mut say_hi);
}
println!("And now name is: {}", name);
}
( , ) ( — .):
fn main() {
let mut name = String::from("Alice");
let mut say_hi = || {
println!("Hello, {}", name); // use by ref
name += " and Bob"; // use by mut ref
std::mem::drop(name); // use by value
};
//call_fn(say_hi);
//call_fn_mut(say_hi);
call_fn_oce(say_hi);
}
, , . , , , .
?
, . - . Rust Book:
,Fn
-,Fn
, , , , ,FnMut
FnOnce
.
, " , ". , — FnOnce
. , .
, Fn
. , Fn
FnMut
, FnMut
FnOnce
.
FnOnce
FnMut
Fn
, , , . , Fn
.
5
イテレーターとクロージャーについて学んだことをすべて追加したfor i in
ので、プログラムが数値を2,4,6,...,20
2回出力するように、5行目(で始まる)を変更します。
fn main() {
let nums: Vec<u32> = (1..11).collect();
for _ in 1..3 {
for i in nums.map(todo!()) {
println!("{}", i);
}
}
}
:
error[E0599]: no method named `map` found for type `std::vec::Vec<u32>` in the current scope --> main.rs:5:23 | 5 | for i in nums.map(todo!()) { | ^^^ | = note: the method `map` exists but the following trait bounds were not satisfied: `&mut std::vec::Vec<u32> : std::iter::Iterator` `&mut [u32] : std::iter::Iterator`
, nums
. : into_iter()
, iter()
iter_mut()
. , , iter()
. nums.map
nums.iter().map
, todo!()
.
, . : |x| x * 2
. : FnOnce
, FnMut
Fn
?