2016-03-23 26 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值。

我知道没有类似箭头的运算符用于解引用和调用原始指针的方法,这使得我的一些代码看起来很糟糕,但它有点可以理解为什么它不在语言中。

+2

我们真的很喜欢[MCVE(http://stackoverflow.com/help/mcve),因为它确保了答案适当的,而不是疯狂的猜测。具体来说,我不清楚'util :: request_mem'的签名是什么。从你的评论看来,它似乎会返回某种'Option ',但我不太确定。此外,尽管知道您希望避免“解包”,但您并不指定如果request_mem返回“无”会发生什么情况。 –

+0

另外,如果你用*“双缩进匹配语句”编写代码*,那将是一种展示你想要它做什么的方法。 – Shepmaster

回答

1

一种解决方案是返回Option转换为Result,然后用像Result::or_else方法链的进一步工作和宏像try!返回早期:或者

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!'的确切范围! –

+0

@MatthieuM。是的。我不喜欢这样做,我必须制作一个“假”的错误值“0”,我不喜欢该行太长以至于“try”很难理解。我真的想要一个'Option'的方法,它需要'F:FnOnce() - >结果',但这看起来很特别。我通常可以将'try'分成两行...... – Shepmaster