Option
https://doc.rust-lang.org/std/option/enum.Option.html の補足追記です。
この記事は MIT ライセンスです。
is_some
Someならtrue
let x: Option<u32> = Some(2);
assert_eq!(x.is_some(), true);
let x: Option<u32> = None;
assert_eq!(x.is_some(), false);
is_none
Noneならtrue
let x: Option<u32> = Some(2);
assert_eq!(x.is_none(), false);
let x: Option<u32> = None;
assert_eq!(x.is_none(), true);
as_ref
Option を Option<&T> に変換する。この手法によって、元の値には触れず、参照のみを受け取ります。
borrow は発生しません。
let num_as_str: Option<String> = Some("10".to_string());
// First, cast `Option<String>` to `Option<&String>` with `as_ref`,
// then consume *that* with `map`, leaving `num_as_str` on the stack.
let num_as_int: Option<usize> = num_as_str.as_ref().map(|n| n.len());
println!("still can print num_as_str: {:?}", num_as_str);
as_mut
Option を Option<&mut T> に変換
let mut x = Some(2);
match x.as_mut() { Some(v) => *v = 42, None => {},
}
assert_eq!(x, Some(42));
expect
オプションをアンラップし、Someの中身を返す。
unwrapと異なる点は、panicが発生した場合に、msgが流れる
let x = Some("value");
assert_eq!(x.expect("the world is ending"), "value");
unwrap
Some(v) から vを取り出す。
もとの変数からは移動されてしまうので注意。
Noneだった場合はpanicが発生する
let x: Option<&str> = None;
x.expect("the world is ending"); // panics with `the world is ending`
unwrap_or
アンラップ時に、Noneだった場合は、orで指定したものを返す。制約として同じ型のものでなければいけない。
assert_eq!(Some("car").unwrap_or("bike"), "car");
assert_eq!(None.unwrap_or("bike"), "bike");
unwrap_or_else
アンラップ時にNoneだった場合は、or_elseで指定したクロージャの結果を返す。
let k = 10;
assert_eq!(Some(4).unwrap_or_else(|| 2 * k), 4);
assert_eq!(None.unwrap_or_else(|| 2 * k), 20);
map
アンラップ時にSomeだった場合は、Some(v)のvをクロージャに渡し、結果をSome(s)として受け取る。Noneだった場合はそのままNoneになる。
map_or
アンラップ時にSomeだった場合は、Some(v)のvをクロージャに渡し、結果をsとして受け取る。Noneだった場合はデフォルト値が渡される。結果sとデフォルト値は同じ型。
let x = Some("foo");
assert_eq!(x.map_or(42, |v| v.len()), 3);
let x: Option<&str> = None;
assert_eq!(x.map_or(42, |v| v.len()), 42);
map_or_else
Someだった場合もNoneだった場合もクロージャに渡す。結果の型はそれぞれのクロージャで同じでなければいけない。
let k = 21;
let x = Some("foo");
assert_eq!(x.map_or_else(|| 2 * k, |v| v.len()), 3);
let x: Option<&str> = None;
assert_eq!(x.map_or_else(|| 2 * k, |v| v.len()), 42);
ok_or
Option型をResult型に変換する。失敗だった場合の処理は新たに追加する。
let x = Some("foo");
assert_eq!(x.ok_or(0), Ok("foo"));
let x: Option<&str> = None;
assert_eq!(x.ok_or(0), Err(0));
or_or_else
Option型をResult型に変換する。失敗だった場合の処理は、クロージャで計算する。
let x = Some("foo");
assert_eq!(x.ok_or_else(|| 0), Ok("foo"));
let x: Option<&str> = None;
assert_eq!(x.ok_or_else(|| 0), Err(0));
iter
イテレータに変換する。next()すると結果が変える。
二回next()するとNoneになる。
let x = Some(4);
assert_eq!(x.iter().next(), Some(&4));
let x: Option<u32> = None;
assert_eq!(x.iter().next(), None);
iter_mut
iterと一緒だが、ミュータブル
let mut x = Some(4);
match x.iter_mut().next() { Some(v) => *v = 42, None => {},
}
assert_eq!(x, Some(42));
let mut x: Option<u32> = None;
assert_eq!(x.iter_mut().next(), None);
and
引数の条件もSomeでなければ、全体的にNoneになる。
let x = Some(2);
let y: Option<&str> = None;
assert_eq!(x.and(y), None);
let x: Option<u32> = None;
let y = Some("foo");
assert_eq!(x.and(y), None);
let x = Some(2);
let y = Some("foo");
assert_eq!(x.and(y), Some("foo"));
let x: Option<u32> = None;
let y: Option<&str> = None;
assert_eq!(x.and(y), None);
and_then
NoneのときはNoneを返すが、Someだった場合は、クロージャの計算結果を Some<U>
として返す。
fn sq(x: u32) -> Option<u32> { Some(x * x) }
fn nope(_: u32) -> Option<u32> { None }
assert_eq!(Some(2).and_then(sq).and_then(sq), Some(16));
assert_eq!(Some(2).and_then(sq).and_then(nope), None);
assert_eq!(Some(2).and_then(nope).and_then(sq), None);
assert_eq!(None.and_then(sq).and_then(sq), None);
or
どちらかに値が入っていれば、最初にHITした値が帰る
let x = Some(2);
let y = None;
assert_eq!(x.or(y), Some(2));
let x = None;
let y = Some(100);
assert_eq!(x.or(y), Some(100));
let x = Some(2);
let y = Some(100);
assert_eq!(x.or(y), Some(2));
let x: Option<u32> = None;
let y = None;
assert_eq!(x.or(y), None);
or_else
値が含まれていればSomeを返すが、含まれていない場合は、クロージャが呼ばれその結果を返す。クロージャの結果はSomeかNoneである。
fn nobody() -> Option<&'static str> { None }
fn vikings() -> Option<&'static str> { Some("vikings") }
assert_eq!(Some("barbarians").or_else(vikings), Some("barbarians"));
assert_eq!(None.or_else(vikings), Some("vikings"));
assert_eq!(None.or_else(nobody), None);
get_or_insert
Nonen場合は、vをオプションに挿入し、含まれている値への変更可能な参照を返す。
let mut x = None;
{ let y: &mut u32 = x.get_or_insert(5); assert_eq!(y, &5); *y = 7;
}
assert_eq!(x, Some(7));
get_or_insert_with
Noneの場合、クロージャによって計算された値をオプションに挿入し、含まれている値への変更可能な参照を返す。
let mut x = None;
{ let y: &mut u32 = x.get_or_insert_with(|| 5); assert_eq!(y, &5); *y = 7;
}
assert_eq!(x, Some(7));
take
オプションから値を取り除き、Noneをその場所に残す。
let mut x = Some(2);
x.take();
assert_eq!(x, None);
let mut x: Option<u32> = None;
x.take();
assert_eq!(x, None);