===^^===
《榴芒客服系统》是我们工作室开发的在线客服系统,欢迎下载试用:
https://blog.csdn.net/look4liming/article/details/164755808
https://blog.csdn.net/look4liming/article/details/164755808
Rust是表达式语言。
if和switch是语句,他们不生成值,也不能在表达式中间使用,而在Rust中,if和match可以生成值。
所有可以链式书写的运算符都是左结合的。
比较运算符、赋值运算符和范围运算符,则根本无法链式书写。
如果一个块看起来很像C代码,每个地方都有分号,那么它就会像C的块一样运行,并且其值为()。
当块的最后一行不带分号时,就以最后这个表达式的值而不是通常的()作为块的值。
在Rust中,分号是有实际意义的:
let msg = {
// let声明:分号总是必须的
let dandelion_control = puffball.open();
// 带分号的表达式:调用方法,丢弃返回值
dandelion_control.release_all_seeds(launch_codes);
// 无分号的表达式:调用方法,返回值将存入msg
dandelion_control.get_status();
};
变量名必须以字母或下划线开头,并且只能在第一个字母之后包含数字。“字母”是广义的,包括希腊字母、带重音的拉丁字符和更多符号,也包括中文。不允许使用表情符号。
let声明可以在不初始化变量的情况下声明变量,因为有时候确实应该在某些控制流结构的中间初始化变量:
let name;
if user.has_nickname() {
name = user.nickname();
} else {
name = generate_unique_name();
user.register(&name);
}
在初始化之前就使用变量是错误的。
看这段代码:
for line in file.lines() {
let line = line?;
}
for循环里的这个let声明,会创建一个不同类型的、新的变量。第二个定义会在所处代码块的其余部分代替第一个定义,这叫作遮蔽(shadowing)。
块还可以包含语法项声明,比如fn、struct或use。
当在块内声明一个fn时,它的作用域是整个块,也就是说,它可以在这个封闭块内部使用。但是嵌套的fn无法访问恰好在同一作用域内的局部变量或参数。闭包可以看到封闭块作用域内的变量。
if表达式示例:
if condition1 {
block1
} else if condition2 {
block2
} else {
block_n
}
每个condition都必须是bool类型的表达式。condition周围不需要圆括号,但花括号是必须的。
else if块以及最后的else是可选的。
match表达式示例:
match code {
0 => println!("OK"),
1 => println!("Wires Tangled"),
2 => println!("User Asleep"),
_ => println!("Unrecognized Error {}", code)
}
match表达式的一般形式如下:
match value {
pattern => expr,
...
}
如果expr是一个块,可以省略此分支之后的逗号。
Rust禁止执行未覆盖所有可能值的match表达式:
let score = match card.rank {
Jack => 10,
Queen => 10,
Ace => 11
}; // 错误,为穷举所有模式
if表达式的所有块都必须生成相同类型的值。
match表达式的所有分支都必须具有相同的类型。
if let表达式:
if let pattern = expr {
block1
} else {
block2
}
expr要么匹配pattern,运行block1;要么运行block2。
if let是只有一个模式的match的简写形式:
match expr {
pattern => { block1 }
_ => { block2 }
}
4种循环表达式:
while condition {
block
}
while let pattern = expr {
block
}
loop {
block
}
for pattern in iterable {
block
}
各种循环都是Rust中的表达式,但while循环或for循环的值总是()。
可以用loop来编写无限循环。
看下面这个for循环:
for i in 0..20 {
println!("{}", i);
}
..运算符会生成一个范围(range),及具有两个字段(start和end)的简单结构体。0..20与std::ops::Range {start: 0, end: 20}相同。
标准集合都是可迭代的,数组和切片也是如此。
为了与Rust的移动语义保持一致,把值用于for循环会消耗该值:
let strings: Vec<String> = error_messages();
for s in strings { // 在这里,每个String都会转移给s
println!("{}", s);
} // 并在此丢弃
println!("{} error(s)", srings.len()); // 错误,使用了已经转移出去的值
这可能很不方便,补救措施是在循环中访问此集合的引用。循环变量也会变成对集合中每个条目的引用:
for rs in &strings {
println!("String {:?} is at address {:p}.", *rs, rs);
}
这里&string的类型是&Vec<String>,rs的类型是&String。
遍历可变引用会为每个元素提供一个可变引用:
for rs in &mut strings { // rs的类型是&mut String
rs.push('\n'); // 为每个字符串添加一个换行
}
break表达式会推出所在循环。break只能用在循环中,不能用在match表达式中,这与C系语言中的switch语句不同。
在loop循环体中,可以在break后面跟一个表达式,该表达式的值会成为此loop的值:
continue表达式会跳转到循环的下一次迭代。
循环可以带有生命周期标签:
'search: // 生命周期标签
for room in apartment {
for spot in room.hiding_spots() {
if spot.contains(keys) {
break 'search;
}
}
}
break可以同时具有标签和值表达式:
// 找到此系列中的第一个完全平方数的平方根
let spart = 'outer: loop {
let n = next_number();
for i in 1.. {
let square = i * i;
if square == n {
break 'outer i; // 找到了平方根,跳出最外层循环,把i给spart
}
if square > n {
break;
}
}
};
return表达式会退出当前函数,并向调用者返回值。
不带值的return是return ()的简写:
fn f() {
return; // 返回()
}
函数调用与方法调用:
let x = gcd(1302, 462); // 函数调用
let room = player.location(); // 方法调用
在上面的代码中,player可能是Player、&Player类型的引用,也可能是Box<Player>或Rc<Player>类型的智能指针,因为Rust的.运算符会根据需要自动对player解引用或接入对它的引用。
普通方法会在值上调用,如my_vec.len()
类型关联函数会在类型是调用,如Vec::new()
在函数调用或方法调用中,泛型类型的常用语法Vec<T>是不起作用的:
return Vec<i32>::with_capacity(1000); // 错误
let ramp = (0..n).collect<Vec<i32>>(); // 同样错误
在表达式中<是小于运算符,Rust编译期建议用::<T>代替<T>:
return Vec::<i32>::with_capacity(1000);
let ramp = (0..n).collect::<Vec<i32>>();
或者删掉类型参数,让Rust来推断它们:
return Vec::with_capacity(1000);
let ramp: Vec<i32> = (0..n).collect();
字段与元素:
game.black_pawns // 结构体字段
coords.1 // 元组元素
如果.左边的值是引用或智能指针类型,那么它就会像方法调用一样自动解引用。
方括号会访问数组、切片或向量的元素:
pieces[i] // 数组元素
方括号左侧的值也会自动解引用。
..运算符允许省略任何操作数:
.. // RangeFull
a.. // RangeFrom {start: a}
..b // RangeTo {end: b}
a..b // Range {start: a, end: b}
后两种是排除结束值(或半开放)的。例如,范围0..3包括数值0、1和2,但不包括3。
..=运算符会生成包含结束值(或封闭)的范围:
..=b // RangeToInclusive {end: b}
a..=b // RangeInclusive::new(a, b)
例如,范围0..=3包括数值0、1、2和3。
一元*运算符用于访问引用所指向的值。看下面的程序:
let padovan: Vec<u64> = compute_padovan_sequence(n);
for elem in &padovan {
draw_triangle(turtle, *elem);
}
elem的类型是&u64,因此*elem为u64。
一元-运算符会对一个数取负,它支持除无符号整数之外的所有数值类型。
没有一元+运算符!
%取余运算符,既能用于整数,也能用于浮点数。
Rust支持C系语言中的整数位运算符(&、|、^、<<和>>)。但是,Rust会使用!而不是~表示按位非。
移位总是对有符号整数类型进行符号扩展,对无符号数进行零扩展。由于Rust支持无符号数,所以它不需要>>>这样的无符号移位运算符。
Rust不支持链式赋值,不能编写a=b=3来将3同时赋给a和b。
Rust没有自增运算符++和自减运算符--。
将一种类型转换成另一种类型,需要显式转换:
let x = 17; // x是i32的
let index = x as usize; // 通过as关键字,将i32转换成usize
闭包通常由一个参数列表组成,在两条竖线之间列出,后跟一个表达式:
let is_even = |x| x % 2 == 0;
如果确实指定了返回类型,那么为了语法的完整性,闭包的主体必须是一个块:
let is_even = |x: u64| -> bool x % 2 == 0; // 错误
let is_even = |x: u64| -> bool { x % 2 == 0; } // 正确
调用闭包和调用函数的语法是一样的:
is_even(14);
===^^===
《榴芒客服系统》是我们工作室开发的在线客服系统,欢迎下载试用:
https://blog.csdn.net/look4liming/article/details/164755808
https://blog.csdn.net/look4liming/article/details/164755808
转载自 CSDN-专业IT技术社区
原文链接:https://blog.csdn.net/look4liming/article/details/167282638




