2016-03-23 3 views
0

プロジェクトからいくつかのアンラップ関数を削除しようとしていますが、このブロックの慣用バージョンが何であるかわかりません::オプションと結果からアンラップコールを削除します。

let free_block = match util::find_free_block(size) { 
    Some(block) => unsafe { (*block).split(size) }, 
    None  => unsafe { (*util::request_mem(size).unwrap()).split(size) } 
}; 

Noneの一致の場合、二重にインデントされた一致ステートメントはありません。

util::request_mem(size)Result<*mut T, i32>を返し、失敗した場合はi32の値を返します。

逆参照と生ポインタのメソッドを呼び出すための矢印演算子のCのような同等物がないことを理解していますが、私のコードのいくつかはひどく見えますが、なぜそれが言語に含まれないのか。

+2

我々は本当に(http://stackoverflow.com/help/mcve)[MCVE]のような、それは答えがあることを保証するため、適切な、野生の推測ではなく。特にここでは、 'util :: request_mem'の署名が何であるかは不明です。あなたのコメントから、 'Option 'のようなものが返ってくるようですが、私はあまりよく分かりません。また、 'unwrap'を避けたいということを知ってうれしいのですが、' request_mem'が 'None'を返す場合に何が起こるべきかを指定していません。 –

+0

さらに、コード*を「二重にインデントされたmatch文」で記述した場合、それはあなたがしたいことを示す方法になります。 – Shepmaster

答えて

1

一つの解決策を早期に返すためにtry!のようなチェーン更なる作業やマクロにResult::or_elseのようなメソッドを使用し、その後、Resultに返さOptionを変換することです:代わり

struct Thing; 
impl Thing { 
    fn split(&self, size: u8) -> bool { false } 
} 

fn find_free_block(size: u8) -> Option<*mut Thing> { None } 
fn request_mem(size: u8) -> Result<*mut Thing, i32> { Err(1) } 

fn the_answer(size: u8) -> Result<bool, i32> { 
    let thing_ptr = try!(find_free_block(size).ok_or(0).or_else(|_| request_mem(size))); 
    let thing = unsafe { &*thing_ptr }; 
    Ok(thing.split(size)) 
} 

fn main() {} 

fn the_answer(size: u8) -> Result<bool, i32> { 
    find_free_block(size) 
     .ok_or(0) 
     .or_else(|_| request_mem(size)) 
     .map(|t| unsafe { &*t }) 
     .map(|t| t.split(size)) 
} 

このようなものがうまくいくとすれば、何がすばらしいのですか?

fn the_answer(size: u8) -> Result<bool, i32> { 
    find_free_block(size) 
     .ok_or_maybe(|| request_mem(size)) 
     .map(|t| unsafe { &*t }) 
     .map(|t| t.split(size)) 
} 

あなたはこれはしかし今を実現することができます:

trait Secret<T> { 
    fn ok_or_maybe<E, F>(self, F) -> Result<T, E> 
     where F: FnOnce() -> Result<T, E>; 
} 

impl<T> Secret<T> for Option<T> { 
    fn ok_or_maybe<E, F>(self, f: F) -> Result<T, E> 
     where F: FnOnce() -> Result<T, E> 
    { 
     match self { 
      Some(e) => Ok(e), 
      None => f(), 
     } 
    } 
} 
+1

私は今度の '? 'の可読性について疑問を抱いていましたが、ここで私は認めなければなりません...' try! 'の正確な範囲を理解するために、 @MatthieuM。 –

+0

。ええ。私は「偽」エラー値を「0」にしなければならないことを嫌い、「試行」が理解しにくいほど長い行が好きではない。私は 'F:FnOnce() - > Result 'を取る 'Option'のメソッドを実際に欲しがっていますが、それはかなり特別なケースです。私は通常、 'try'を2行に分けるかもしれません... – Shepmaster

関連する問題