Skip to content

Latest commit

 

History

History
275 lines (201 loc) · 12.3 KB

1.1-slides.md

File metadata and controls

275 lines (201 loc) · 12.3 KB
title description duration
Module 1.1 - Common programming concepts
Rust Basic Concepts
30 minutes

Data Types

  • Memory only stores binary data
    • Anything can be represented in binary
  • Program determines what the binary represents
  • Basic types that are universally useful are provided by the language

Notes: các loại dữ liệu trong lập trình, đặc biệt là cách chúng được lưu trữ và sử dụng trong bộ nhớ Bộ nhớ chỉ lưu trữ dữ liệu nhị phân:

Tất cả dữ liệu trong bộ nhớ máy tính đều được lưu trữ dưới dạng nhị phân (binary data), tức là các dãy số 0 và 1. Bất cứ thứ gì cũng có thể được biểu diễn dưới dạng nhị phân:

Bất kỳ loại thông tin nào, từ văn bản, hình ảnh, âm thanh đến các cấu trúc dữ liệu phức tạp, đều có thể được mã hóa thành các dãy nhị phân. Chương trình xác định nhị phân đó biểu diễn cái gì:

Các chương trình máy tính quyết định ý nghĩa của các dãy số nhị phân này. Ví dụ, một dãy số nhị phân có thể được diễn giải là một số nguyên, một ký tự, hoặc một phần tử của một cấu trúc dữ liệu phức tạp. Các loại dữ liệu cơ bản mà hữu ích trên toàn cầu được cung cấp bởi ngôn ngữ:

Các ngôn ngữ lập trình cung cấp các loại dữ liệu cơ bản như số nguyên, số thực, ký tự, chuỗi, và các cấu trúc dữ liệu khác. Những loại dữ liệu này rất hữu ích và được sử dụng rộng rãi trong lập trình.


Basic Data Types

  • Boolean
    • true, false
  • Integer
    • 1, 2, 50, 99, -2
  • Double / Float
    • 1.1, 5.5, 200.0001, 2.0
  • Character
    • ‘A’, ‘B’, ‘c’, ‘6’, ‘$’
  • String
    • “Hello”, “string”, “this is a string”, “it’s 42”

What is a variable?

  • Assign data to a temporary memory location
    • Allows programmer to easily work with memory
  • Can be set to any value & type
  • Immutable by default, but can be mutable
    • Immutable: cannot be changed
    • Mutable: can be changed

Notes: Gán dữ liệu vào một vị trí bộ nhớ tạm thời:

Biến là một cách để gán dữ liệu vào một vị trí trong bộ nhớ tạm thời, giúp lập trình viên dễ dàng làm việc với bộ nhớ. Cho phép lập trình viên dễ dàng làm việc với bộ nhớ:

Bằng cách sử dụng biến, lập trình viên có thể dễ dàng truy cập và thao tác dữ liệu mà không cần phải lo lắng về các chi tiết cụ thể của quản lý bộ nhớ. Có thể được gán bất kỳ giá trị và kiểu nào:

Biến có thể được gán cho bất kỳ giá trị nào và có thể có bất kỳ kiểu dữ liệu nào tùy thuộc vào ngôn ngữ lập trình. Mặc định là bất biến, nhưng có thể biến đổi:

Trong nhiều ngôn ngữ lập trình, biến mặc định là bất biến (immutable), nghĩa là giá trị của nó không thể thay đổi sau khi đã được gán. Bất biến (Immutable): Không thể thay đổi. Có thể biến đổi (Mutable): Có thể thay đổi. Việc sử dụng biến một cách hợp lý và hiểu rõ tính chất của chúng giúp lập trình viên viết mã hiệu quả, dễ bảo trì và ít lỗi hơn.


Examples

let two = 2;
let hello = "hello";
let j = 'j';
let my_half = 0.5;
let mut my_name = "Bill";
let quit_program = false;
let your_half = my_half;

What are functions?

  • A way to encapsulate program functionality
  • Optionally accept data
  • Optionally return data
  • Utilized for code organization
    • Also makes code easier to read

Notes:

Một cách để đóng gói các chức năng của chương trình:

Hàm là một đơn vị mã nguồn có thể được tái sử dụng và được sử dụng để thực hiện một tác vụ cụ thể hoặc một tập hợp các tác vụ liên quan. Nó giúp đóng gói chức năng của chương trình. Có thể nhận dữ liệu (tùy chọn):

Hàm có thể chấp nhận các tham số hoặc dữ liệu đầu vào khi được gọi. Điều này cho phép hàm hoạt động trên các dữ liệu khác nhau mỗi khi được sử dụng. Có thể trả về dữ liệu (tùy chọn):

Hàm có thể trả về một giá trị sau khi thực hiện xong công việc của nó. Giá trị trả về này có thể được sử dụng ở nơi khác trong chương trình. Được sử dụng để tổ chức mã nguồn:

Hàm giúp tổ chức mã nguồn một cách hợp lý và có cấu trúc, giúp mã dễ đọc, dễ hiểu và dễ bảo trì hơn. Cũng làm cho mã dễ đọc hơn: Việc sử dụng hàm giúp mã nguồn trở nên dễ đọc hơn vì nó tách biệt các phần khác nhau của chương trình dựa trên chức năng của chúng. Điều này giúp lập trình viên dễ dàng theo dõi và hiểu rõ các phần của mã nguồn. Sử dụng hàm một cách hợp lý và hiệu quả giúp cải thiện cấu trúc chương trình, tái sử dụng mã, và làm cho quá trình phát triển phần mềm trở nên dễ dàng hơn.

Anatomy of a function

fn add(a: i32, b: i32) -> i32 {
    a + b
}

Using a function

fn add(a: i32, b: i32) -> i32 {
    a + b
}

let x = add(1, 1);
let y = add(3, 0);
let z = add(x, 1);

The println macro

  • Macros expand into additional code
  • println “Prints” (displays) information to the terminal
  • Useful for debugging
let life = 42;

println!("hello");
println!("{:?}", life);
println!("{:?}{:?}", life, life);
println!("the meaning is {:?}", life);

println!("{life:?}");
println!("{life}");

  • Macros use an exclamation point to call/invoke
  • Generate additional Rust code
  • Data can be printed using println!:
    • {:?}
    • {varname:?}

Notes: Macro sử dụng dấu chấm than để gọi/thực thi:

Trong Rust, các macro được gọi bằng cách sử dụng dấu chấm than (!) sau tên của macro. Ví dụ, để gọi macro println, bạn sẽ viết println!. Tạo ra mã Rust bổ sung:

Macro trong Rust có thể tạo ra mã bổ sung trong quá trình biên dịch. Điều này giúp tối ưu hóa và giảm thiểu việc viết mã lặp lại bằng cách tạo ra các đoạn mã tự động dựa trên định nghĩa của macro. Dữ liệu có thể được in ra bằng cách sử dụng println!:

Macro println! được sử dụng để in dữ liệu ra màn hình. Bạn có thể sử dụng nó để in các giá trị của biến hoặc các thông điệp. In dữ liệu với {:?} và {varname:?}:

{:?}: Sử dụng cú pháp này trong println! để in ra dữ liệu dưới dạng gỡ lỗi (debug format), tức là in ra thông tin chi tiết của dữ liệu. {varname:?}: Bạn có thể in ra giá trị của một biến cụ thể bằng cách sử dụng tên biến kết hợp với :? trong println!. Việc sử dụng macro giúp mã nguồn Rust trở nên ngắn gọn, dễ đọc và dễ bảo trì hơn bằng cách tự động hóa các tác vụ lặp đi lặp lại và tạo ra mã bổ sung khi cần thiết.


Type Annotations

  • Required for function signatures
  • Types are usually inferred
  • Can also be specified in code
    • Explicit type annotations

Notes: chú thích kiểu Cần thiết cho chữ ký hàm (function signatures):

Trong Rust, các chữ ký của hàm (tên hàm và các tham số của nó) yêu cầu phải có chú thích kiểu. Điều này giúp trình biên dịch hiểu được kiểu dữ liệu của các tham số và giá trị trả về của hàm. Kiểu thường được suy luận:

Rust có khả năng suy luận kiểu, nghĩa là trình biên dịch có thể tự động xác định kiểu dữ liệu của biến dựa trên ngữ cảnh, do đó không phải lúc nào cũng cần chỉ rõ kiểu dữ liệu một cách tường minh. Cũng có thể được chỉ định trong mã:

Ngoài việc suy luận kiểu, lập trình viên cũng có thể chỉ định kiểu dữ liệu một cách rõ ràng trong mã nguồn. Chú thích kiểu tường minh (Explicit type annotations): Lập trình viên có thể thêm các chú thích kiểu rõ ràng để xác định kiểu dữ liệu của biến hoặc tham số, giúp mã nguồn dễ hiểu hơn và tránh nhầm lẫn. Việc sử dụng chú thích kiểu giúp cải thiện tính rõ ràng và an toàn của mã nguồn, đảm bảo rằng các giá trị và biến được sử dụng đúng cách trong toàn bộ chương trình.


Example - Basic

fn print_many(msg: &str, count: i32) {
    // Presumably the body of the function would print the message many times
    // but since it's not shown in the image, it's left empty here.
}

enum Mouse {
    LeftClick,
    RightClick,
    MiddleClick,
}

fn main() {
    let num: i32 = 15;
    let a: char = 'a';
    let left_click: Mouse = Mouse::LeftClick;
}

Notes: Định nghĩa hàm print_many:

Hàm print_many nhận hai tham số: msg là một tham chiếu đến một chuỗi ký tự (&str) và count là một số nguyên 32-bit có dấu (i32). Chú thích kiểu ở đây giúp xác định rõ ràng kiểu dữ liệu của các tham số mà hàm này nhận.

Định nghĩa enum Mouse:

Enum Mouse định nghĩa ba biến thể: LeftClick, RightClick, và MiddleClick. Enum là một kiểu dữ liệu cho phép bạn định nghĩa các biến thể khác nhau dưới cùng một kiểu dữ liệu. Hàm main:

Hàm main là điểm bắt đầu của chương trình. Bên trong hàm này: let num: i32 = 15;: Biến num được khai báo với kiểu dữ liệu là số nguyên 32-bit có dấu (i32) và được gán giá trị 15. let a: char = 'a';: Biến a được khai báo với kiểu dữ liệu ký tự (char) và được gán giá trị 'a'. let left_click: Mouse = Mouse::LeftClick;: Biến left_click được khai báo với kiểu dữ liệu là enum Mouse và được gán giá trị Mouse::LeftClick.

Chú thích kiểu trong đoạn mã này giúp xác định rõ ràng kiểu dữ liệu của các biến và tham số, đảm bảo rằng chúng được sử dụng một cách nhất quán và đúng đắn trong toàn bộ chương trình.


Example - Generics

enum Mouse {
    LeftClick,
    RightClick,
    MiddleClick,
}

let numbers: Vec<i32> = vec![1, 2, 3];
let letters: Vec<char> = vec!['a', 'b'];
let clicks: Vec<Mouse> = vec![
    Mouse::LeftClick,
    Mouse::LeftClick,
    Mouse::RightClick,
];

Notes: cách sử dụng generic với kiểu dữ liệu Vec (vector) Định nghĩa enum Mouse: Enum Mouse định nghĩa ba biến thể: LeftClick, RightClick, và MiddleClick. Enum là một kiểu dữ liệu cho phép bạn định nghĩa các biến thể khác nhau dưới cùng một kiểu dữ liệu. Khai báo biến sử dụng generic Vec: Biến numbers được khai báo với kiểu dữ liệu là Vec, nghĩa là một vector chứa các phần tử kiểu số nguyên 32-bit có dấu (i32). Biến này được gán giá trị là một vector chứa các số [1, 2, 3]. Biến letters được khai báo với kiểu dữ liệu là Vec, nghĩa là một vector chứa các phần tử kiểu ký tự (char). Biến này được gán giá trị là một vector chứa các ký tự ['a', 'b']. Biến clicks được khai báo với kiểu dữ liệu là Vec, nghĩa là một vector chứa các phần tử kiểu Mouse (enum đã định nghĩa ở trên). Biến này được gán giá trị là một vector chứa các giá trị Mouse::LeftClick, Mouse::LeftClick, và Mouse::RightClick. Trong đoạn mã này, việc sử dụng generic cho phép vector chứa các kiểu dữ liệu khác nhau, từ số nguyên, ký tự cho đến enum. Chú thích kiểu giúp xác định rõ ràng kiểu dữ liệu mà mỗi vector chứa, đảm bảo rằng các giá trị được gán vào vector phù hợp với kiểu dữ liệu đã định nghĩa. Điều này giúp mã nguồn rõ ràng hơn và ngăn ngừa lỗi khi thao tác với các phần tử trong vector.