option::swap_unwrap, the ubiquitous 'option dance'.

This commit is contained in:
Ben Blum 2012-08-02 14:40:42 -04:00
parent 7d4742e101
commit 9facb15c49
2 changed files with 29 additions and 2 deletions

View File

@ -23,7 +23,7 @@ pure fn get<T: copy>(opt: option<T>) -> T {
* Fails if the value equals `none`
*/
alt opt { some(x) { return x; } none { fail ~"option none"; } }
alt opt { some(x) { return x; } none { fail ~"option::get none"; } }
}
pure fn expect<T: copy>(opt: option<T>, reason: ~str) -> T {
@ -112,7 +112,7 @@ pure fn unwrap<T>(-opt: option<T>) -> T {
unsafe {
let addr = alt opt {
some(x) { ptr::addr_of(x) }
none { fail ~"option none" }
none { fail ~"option::unwrap none" }
};
let liberated_value = unsafe::reinterpret_cast(*addr);
unsafe::forget(opt);
@ -120,6 +120,13 @@ pure fn unwrap<T>(-opt: option<T>) -> T {
}
}
/// The ubiquitous option dance.
#[inline(always)]
fn swap_unwrap<T>(opt: &mut option<T>) -> T {
if opt.is_none() { fail ~"option::swap_unwrap none" }
unwrap(util::replace(opt, none))
}
pure fn unwrap_expect<T>(-opt: option<T>, reason: ~str) -> T {
//! As unwrap, but with a specified failure message.
if opt.is_none() { fail reason; }
@ -204,6 +211,24 @@ fn test_unwrap_resource() {
assert *i == 1;
}
#[test]
fn test_option_dance() {
let x = some(());
let mut y = some(5);
let mut y2 = 0;
do x.iter |_x| {
y2 = swap_unwrap(&mut y);
}
assert y2 == 5;
assert y.is_none();
}
#[test] #[should_fail] #[ignore(cfg(windows))]
fn test_option_too_much_dance() {
let mut y = some(util::noncopyable());
let _y2 = swap_unwrap(&mut y);
let _y3 = swap_unwrap(&mut y);
}
#[test]
fn test_option_while_some() {
let mut i = 0;

View File

@ -9,6 +9,7 @@ pure fn id<T>(+x: T) -> T { x }
* Swap the values at two mutable locations of the same type, without
* deinitialising or copying either one.
*/
#[inline(always)]
fn swap<T>(x: &mut T, y: &mut T) {
*x <-> *y;
}
@ -17,6 +18,7 @@ fn swap<T>(x: &mut T, y: &mut T) {
* Replace the value at a mutable location with a new one, returning the old
* value, without deinitialising or copying either one.
*/
#[inline(always)]
fn replace<T>(dest: &mut T, +src: T) -> T {
let mut tmp = src;
swap(dest, &mut tmp);