rust 代码确实简介,但是各种操作做层出不穷,这里记录一下一些难以理解的晦涩语法。
fn main() {
let numbers = (2, 4, 8, 16, 32);
match numbers {
(first, .., last) => {
println!("Some numbers: {}, {}", first, last);
},
}
}
…可以省略元组或者接头体的一些无关参数,子啊这个元组中,4.8.16 是我们不关注的,所以可以省略匹配,只匹配第一个和最后一个,所以就拿到了2和16.
?其实更像是一个宏,可以替换成
let f = funx()?
//等价于
let f = match funx() {
Ok(data)=> data,
Err(e) => return Err(e),
但是嵌套到循环中就比较让人疑惑的
fn divide(a: i32, b: i32) -> Result<Option<i32>, String> {
if b == 0 {
return Err("Division by zero".to_string());
}
Ok(Some(2))
}
fn calculate(a: i32, b: i32) -> Result<i32, String> {
let mut tmp = 2;
while let Some(i) = divide(a, tmp)?{
println!("=====: {:?}", i);
tmp = tmp -1
}
Ok(3)
其实这里类似于一个loop循环,只是加入了err强制返回操作
//frame_data 类型是BTreeMap
let frame_data = BTreeMap::new()
frame_data.iter()
.skip_while(|(&output_frameno, _)| {
output_frameno < self.output_frameno
})
.find(|(_, data)| data.is_some())
.map(|(&output_frameno, _)| output_frameno)
.ok_or(EncoderStatus::NeedMoreData)?; // TODO: doesn't play well with the below check?
因为BTreeMap类型是k-v数据map。所以iter后,会变成一种rust的元组类型,无论在后面的各种操作,都可以通过闭包来处理,map是把k-v元组转换成k。
rust 是类型推断的,并且类的函数可以在各种地方添加,甚至可以让一个类无缘无故的拥有一些特性,而into则是鲜明的例子。into代码如下:
// From implies Into
#[stable(feature = "rust1", since = "1.0.0")]
impl<T, U> Into<U> for T
where
U: From<T>,
{
/// Calls `U::from(self)`.
///
/// That is, this conversion is whatever the implementation of
/// <code>[From]<T> for U</code> chooses to do.
#[inline]
fn into(self) -> U {
U::from(self)
}
}
// From (and thus Into) is reflexive
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> From<T> for T {
/// Returns the argument unchanged.
#[inline(always)]
fn from(t: T) -> T {
t
}
}
这段代码是任何的T(任何一个struct,都可以调用)都拥有了Into这个trait(内部有Into方法)。只是这个方法的返回值必须实现From这个trait。通俗的说,我想让结构体A。变成B,我只用把B实现From这个trait。就可以直接调用A的into函数。
这种思考方式非常符合人类的思维模式,但是却很不面向对象。