读Rust By Example(2)

原生类型

  • 符号整数: i8, i16, i32, i64 and isize (指针大小)
  • 无符号整数: u8, u16, u32, u64 and usize (指针大小)
  • 浮点数: f32, f64
  • Unicode可扩展字符,如 'a', 'α' and '∞' (4位)
  • 布尔值,true or false
  • 单元类型(unit type,空元组): 只有 () 这个唯一值
  • 数组,如 [1, 2, 3]
  • 元组,如 (1, true)

变量都可以被显示定义,默认整形为i32,浮点型为f64

样例:

fn main() {  
    let logical: bool = true;

    let a_float: f64 = 1.0;  // 普通定义
    let an_integer   = 5i32; // 后缀定义

    // Or a default will be used.
    let default_float   = 3.0; // `f64`
    let default_integer = 7;   // `i32`

    let mut mutable = 12; // 可变的 `i32`.

    // 错误,变量类型不可被改变
    //mutable = true;
}

数据和操作符

整数可以用0x, 0o, 0b来表示进制。 下划线可以插入数字中增加可读性:1_0001000是相同的。

样例:

fn main() {  
    // 整数加法
    println!("1 + 2 = {}", 1u32 + 2);

    // 整数减法
    println!("1 - 2 = {}", 1i32 - 2);
    // 将`1i32`改为`1u32`将会运行时恐慌
    // println!("1 - 2 = {}", 1u32 - 2);
    // 布尔短路逻辑
    println!("true AND false is {}", true && false);
    println!("true OR false is {}", true || false);
    println!("NOT true is {}", !true);

    // 位运算 用0填充的4位二进制
    println!("0011 AND 0101 is {:04b}", 0b0011u32 & 0b0101);
    println!("0011 OR 0101 is {:04b}", 0b0011u32 | 0b0101);
    println!("0011 XOR 0101 is {:04b}", 0b0011u32 ^ 0b0101);
    //1左移5位
    println!("1 << 5 is {}", 1u32 << 5);
    //80右移两位
    println!("0x80 >> 2 is 0x{:x}", 0x80u32 >> 2);

    // 用下划线增加可读性
    println!("One million is written as {}", 1_000_000u32);
}

元组

一个元组可以存放不同类型的数据,每个元组本身也是不同类型签名的值(T1, T2, ...),而T1, T2也就是它包含元素的类型。

样例

// 元组可以用于函数参数或者返回值
fn reverse(pair: (i32, bool)) -> (bool, i32) {  
    // `let` can be used to bind the members of a tuple to variables
    let (integer, boolean) = pair;

    (boolean, integer)
}

#[derive(Debug)]
struct Matrix(f32, f32, f32, f32);

fn main() {  
    let long_tuple = (1u8, 2u16, 3u32, 4u64,
                      -1i8, -2i16, -3i32, -4i64,
                      0.1f32, 0.2f64,
                      'a', true);

    // 可以用下表取出元组的而元素
    println!("long tuple first value: {}", long_tuple.0);
    println!("long tuple second value: {}", long_tuple.1);

    // 元组也可以是元组的成员
    let tuple_of_tuples = ((1u8, 2u16, 2u32), (4u64, -1i8), -2i16);

    // 元组是可打印的
    println!("tuple of tuples: {:?}", tuple_of_tuples);

    let pair = (1, true);
    println!("pair is {:?}", pair);

    println!("the reversed pair is {:?}", reverse(pair));

    // 定义单元素的元组必须加上逗号,否则会被认为是其他类型
    println!("one element tuple: {:?}", (5u32,));
    println!("just an integer: {:?}", (5u32));

    //元组可以析构来创建变量绑定
    let tuple = (1, "hello", 4.5, true);

    let (a, b, c, d) = tuple;
    println!("{:?}, {:?}, {:?}, {:?}", a, b, c, d);

    let matrix = Matrix(1.1, 1.2, 2.1, 2.2);
    println!("{:?}", matrix)

}

练习1:对结构Matrix进行fmt::Display的应用,使打印的结果如下

(1.1 1.2)
(2.1 2.2)

解答1:

use std::fmt;

struct Matrix(f32, f32, f32, f32);

impl fmt::Display for Matrix {  
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result{
         write!(f, "({} {})\n({} {})", &self.0, &self.1, &self.2, &self.3)
     }
}

fn main() {  
    for matrix in [
        Matrix(1.1, 1.2, 2.1, 2.2)
    ].iter(){
        println!("{}", matrix);
    }
}

练习2:增加一个transpose转置函数,使得出的结果如下:

Matrix:  
( 1.1 1.2 )
( 2.1 2.2 )
Transpose:  
( 1.1 2.1 )
( 1.2 2.2 )

解答2:

use std::fmt;

struct Matrix(f32, f32, f32, f32);

impl fmt::Display for Matrix {  
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result{
         write!(f, "({} {})\n({} {})", &self.0, &self.1, &self.2, &self.3)
     }
}
//嗨呀, 引用搞了我半天
fn transpose(matrix: &Matrix) -> Matrix {  
    Matrix(matrix.0, matrix.2, matrix.1, matrix.3)
}


fn main() {  
    for matrix in [
        Matrix(1.1, 1.2, 2.1, 2.2)
    ].iter(){
        println!("Matrix:\n{}", matrix);
    }

    for trans in [
        Matrix(1.1, 1.2, 2.1, 2.2)
    ].iter(){
        println!("Transpose:\n{}", transpose(trans));
    }
}

输出如下:

Matrix:  
(1.1 1.2)
(2.1 2.2)
Transpose:  
(1.1 2.1)
(1.2 2.2)

数据和切片类型

数组包含的是相同类型的数据,保存在连续的内存中,大小在编译的时候就已经确定了。用[T;size]来表示一个数组。

切片与数组类似,但在编译的时候不知道大小。切片可以作为一个数组的借用,并且拥有类型标记&[T]

样例:

use std::mem;

// 函数借用一个slice
fn analyze_slice(slice: &[i32]) {  
    println!("first element of the slice: {}", slice[0]);
    println!("the slice has {} elements", slice.len());
}

fn main() {  
    // 定长数组 (type signature is superfluous)
    let xs: [i32; 5] = [1, 2, 3, 4, 5];

    // 元素统一初始化
    let ys: [i32; 500] = [0; 500];

    // 下标索引从0开始
    println!("first element of the array: {}", xs[0]);
    println!("second element of the array: {}", xs[1]);

    // `len` 返回数组大小
    println!("array size: {}", xs.len());

    // 数组分配在栈中, 5*4=20位
    println!("array occupies {} bytes", mem::size_of_val(&xs));

    // 数组可以自动作为切片借用
    println!("borrow the whole array as a slice");
    analyze_slice(&xs);

    // 切片可以定向到数组的一部分
    println!("borrow a section of the array as a slice");
    analyze_slice(&ys[1 .. 4]);

    // 超出范围将会产生 panic
    //println!("{}", xs[5]);
}