Tìm hiểu về ngôn ngữ Rust

Biến và Tính không đổi (Variables and Mutability)

- Có ba kiểu khai báo biến: hằng số thời gian chạy (immutable variable), biến, và hằng số thời gian biên dịch (constant). - Biến có thể được liên kết lại, biến được khai báo sau sẽ thay thế biến cùng tên trước đó và cho phép thay đổi kiểu dữ liệu.

// Hằng số thời gian chạy (immutable variable)
let a = 5;
a = 6; // lỗi lúc biên dịch
// Biến (mutable variable)
let mut a = 5;
a = 6;
// Hằng số thời gian biên dịch (constant)
// Cần sử dụng biểu thức hằng số và khai báo kiểu dữ liệu
const MAX_VALUES: u32 = 100_000;
// Liên kết lại (không thay đổi kiểu)
let a = 5;
let a = a + 1;
let a = a * 2;
// Liên kết lại (thay đổi kiểu)
let spaces = "   ";
let spaces = spaces.len();

Kiểu Dữ Liệu (Data Types)

- Kiểu đơn lẻ (Scalar Types) - Kiểu số nguyên (Integer Types) - i8, u8, i16, u16, i32, u32, i64, u64 - Thập phân, Thập lục phân, Bát phân, Nhị phân, Byte - Kiểu số thực (Floating-Point Types) - f32, f64 - Kiểu boolean (Boolean Type) - Kiểu ký tự (Character Type) - Kiểu hợp thành (Compound Types) - Bộ (Tuples) - Mảng (Arrays)

// Bộ (với khai báo kiểu dữ liệu)
let data: (i32, f64, u8) = (500, 6.4, 1);
// Bộ (khai báo tự động, giải cấu trúc)
let data = (500, 6.4, 1);
let (x, y, z) = data;
println!("Giá trị của y là: {}", y);
// Bộ (sử dụng chỉ mục)
let x: (i32, f64, u8) = (500, 6.4, 1);
let five_hundred = x.0;
let six_point_four = x.1;
let one = x.2;


// Mảng, kích thước cố định, được cấp phát trên stack
let months = ["Tháng Một", "Tháng Hai", "Tháng Ba", "Tháng Tư", "Tháng Năm", "Tháng Sáu", "Tháng Bảy",
              "Tháng Tám", "Tháng Chín", "Tháng Mười", "Tháng Mười Một", "Tháng Mười Hai"];
let a: [i32; 5] = [1, 2, 3, 4, 5];
let a = [3; 5];  // let a = [3, 3, 3, 3, 3];
let a = [1, 2, 3, 4, 5];
let first = a[0];
let second = a[1];

Cách Hoạt Động của Hàm (How Functions Work)


// Câu lệnh gán không trả về giá trị.
let y = {
    let x = 3;
    // Câu cuối cùng trong khối mã có thể là một biểu thức.
    // Không dùng dấu chấm phẩy ở cuối biểu thức. Nếu thêm dấu chấm phẩy, biểu thức trở thành câu lệnh.
    x + 1
};


// Câu cuối cùng trong hàm có thể là một biểu thức, biểu thị giá trị trả về.
fn five() -> i32 {
    5
}
fn plus_one(x: i32) -> i32 {
    x + 1
}

Dòng Điều Khiển (Control Flow)

- if ... else if ... else biểu thức (có thể trả về giá trị) - loop câu lệnh - while câu lệnh - for ... in câu lệnh (tương đương với foreach)

Sở Hữu (Ownership)


let mut s = String::from("chào");
s.push_str(", thế giới!"); // push_str() nối chuỗi văn bản vào String
println!("{}", s); // In ra `chào, thế giới!`


let x = 5;
// Sao chép
let y = x;
let s1 = String::from("chào");
// Di chuyển
let s2 = s1;
// Sao chép sâu
let s2 = s1.clone();

- Các kiểu có đặc điểm Copy sẽ thực hiện Copy khi gán giá trị. Đặc điểm Copy bao gồm các kiểu cơ bản như số nguyên, số thực, boolean và bộ gồm chúng. - Các kiểu không có đặc điểm Copy sẽ thực hiện Move khi gán giá trị. (sao chép nông + biến bị gán mất hiệu lực) - Các kiểu không có đặc điểm Copy cần sao chép sâu thì phải gọi phương thức clone rõ ràng. - Truyền tham số cho hàm tương đương với việc gán giá trị.

// Di chuyển
let s1 = String::from("chào");
let (s2, len) = calculate_length(s1);
fn calculate_length(s: String) -> (String, usize) {
    let length = s.len(); // len() trả về độ dài của một String
    (s, length)
}
// Tham chiếu không đổi
let s1 = String::from("chào");
let len = calculate_length(&s1);
fn calculate_length(s: &String) -> usize {
    s.len()
}
// Tham chiếu có thể thay đổi
let mut s = String::from("chào");
change(&mut s);
fn change(some_string: &mut String) {
    some_string.push_str(", thế giới");
}

Trong cùng một phạm vi đối với cùng một dữ liệu: - Có thể có nhiều tham chiếu không đổi - Chỉ có thể có một tham chiếu có thể thay đổi - Tham chiếu không đổi và có thể thay đổi không thể tồn tại đồng thời

Phần Tử (Slices)

Có phần tử chuỗi và mảng, phần tử là tham chiếu chỉ đọc. Hằng số chuỗi là kiểu phần tử.

// Tìm từ đầu tiên trong chuỗi, trả về kiểu phần tử chuỗi &str
fn first_word(s: &String) -> &str {
    let bytes = s.as_bytes();
    for (i, &item) in bytes.iter().enumerate() {
        if item == b' ' {
            return &s[0..i];
        }
    }
    &s[..]
}
// Rút gọn chỉ mục
let s = String::from("chào");
let slice = &s[0..2];
let slice = &s[..2];
// Rút gọn chỉ mục
let len = s.len();
let slice = &s[3..len];
let slice = &s[3..];
// Rút gọn chỉ mục
let slice = &s[0..len];
let slice = &s[..];
// a có kiểu &[i32] 
let a = [1, 2, 3, 4, 5];
let slice = &a[1..3];

Thẻ: Rust Ownership Data Types

Đăng vào ngày 19 tháng 6 lúc 04:30