- เรียนภาษา Rust ผ่านเว็บ Tour of Rust
- Tour of Rust - Ch.1 - The Basics
- Tour of Rust - Ch.2 - Basic Control Flow
- Tour of Rust - Ch.3 - Basic Data Structure Types
- Tour of Rust - Ch.4 - Generic Types
- Tour of Rust - Ch.5 - Ownership & Borrowing Data
Tour of Rust - Ch.3 - Basic Data Structure Types
เขียนวันที่ : Apr 16, 2022
บันทึกการเรียน Tour Of Rust บทเรียนที่ 3 - Tour of Rust - Chapter 3 - Basic Data Structure Types
Chapter 3 - Basic Data Structure Types 🦀
Struct
- struct เป็น Collection หรือกลุ่มของข้อมูล
struct Monster {
name: String,
age: i32,
arms: i32,
legs: i32,
weapon: String
}
Calling Methods
- methods คล้ายๆกับ functions (ที่ใช้
fn
) แต่ต่างกันตรง methods นั้น define ใน context ของ struct - จริงๆแล้ว methods ก็คือ functions ที่ทำใน struct (อาจจะฟังดูสับสน เหมือนหรือไม่เหมือนกันแน่? ดูตัวอย่างครับ)
- static methods - คือเมธอดที่เป็นของชนิดตัวแปร เรียกด้วย
::
เช่นString::from()
- instance methods - คือเมธอดที่เป็นของตัวแปร ใช้
.
เช่นs.len()
เอาจริงๆ ผมก็เพิ่งรู้นะเนี่ย ผมไปเรียกมันเป็น function ตลอด และบางทีก็เรียกสลับกันด้วยทั้ง function/method และเพิ่งเห็นใน doc ก็ใช้ methods
fn main() {
// Using a static method to create an instance of String
let s = String::from("Hello world!");
// Using a method on the instance
println!("{} is {} characters long.", s, s.len());
}
// Declare a struct:
struct Student {
id: i32,
name: String
}
// Declare its method:
impl Student {
fn some_method() {}
}
Memory
- data memory - สำหรับเก็บข้อมูลที่รู้ขนาด (กำหนดขนาดไว้ชัดเจนแล้ว) รวมถึงค่าคงที่ต่างๆ
- stack memory - สำหรับข้อมูลที่ถูก declare ใน function โดยตำแหน่งของข้อมูลจะไม่เปลี่ยนแปลงตลอดการทำงานของ function.
- heap memory - ข้อมูลที่ถูกสร้างขึ้นในขณะ application ทำงาน เช่น เพิ่ม ลบ ปรับขนาด - ส่วนนี้ข้อมูลจะช้าเพราะด้วยความที่มัน dynamic เปลี่ยนแปลงได้ - เมื่อข้อมูลเพิ่มเข้ามาใน heap เราเรียกว่า allocation และข้อมูลถูกลบ เราเรียก deallocation
Create data in memory
- เวลาสร้าง instance ของ Struct ตัวโปรแกรมจะสร้างข้อมูลใน memory
Structname {...}
- การเข้าถึง field ของ Struct ใช้ dot operator (
.
) - พวกข้อมูลที่เป็น read-only จะไปอยู่ใน data memory
struct SeaCreature {
animal_type: String,
name: String,
arms: i32,
legs: i32,
weapon: String,
}
fn main() {
// SeaCreature's data is on stack
let ferris = SeaCreature {
// String struct is also on stack,
// but holds a reference to data on heap
animal_type: String::from("crab"),
name: String::from("Ferris"),
arms: 2,
legs: 4,
weapon: String::from("claw"),
};
let sarah = SeaCreature {
animal_type: String::from("octopus"),
name: String::from("Sarah"),
arms: 8,
legs: 0,
weapon: String::from("none"),
};
println!(
"{} is a {}. They have {} arms, {} legs, and a {} weapon",
ferris.name, ferris.animal_type, ferris.arms, ferris.legs, ferris.weapon
);
println!(
"{} is a {}. They have {} arms, and {} legs. They have no weapon..",
sarah.name, sarah.animal_type, sarah.arms, sarah.legs
);
}
String::from
เพื่อสรา้ง field struct แบบString
ซึ่งค่านี้สามารถเปลี่ยนแปลงได้ โดย:
- ไปสร้างเป็น heap memory สำหรับข้อความที่ต้องการแก้ไข
- จับเก็บเป็น reference ที่อ้างอถึงตำแหน่ง heap memory และเซฟใน
String
struct.
- สุดท้าย ตอน struct ถูกสร้างเสร็จ ทั้ง
ferris
และsarah
จะถูกกำหนด location แน่นอนในโปรแกรม ถูกเก็บไว้ใน stack
Tuple-like Strcuts
- คือ Struct ที่หน้าตาเหมือน tuple
struct Location(i32, i32);
fn main() {
// This is still a struct on a stack
let loc = Location(42, 32);
println!("{}, {}", loc.0, loc.1);
}
Unit-like Structs
- นอกจาก tuple เรายังสามารถสร้าง Struct ได้แบบ Unit (คือ tuple ว่างๆ
()
) - ซึ่ง Struct แบบนี้ถูกใช้น้อยมากๆ
struct Marker;
fn main() {
let _m = Marker;
}
Enumerations
- Enumerations คือให้เราสร้าง type ใหม่ให้มีขุดข้อมูล กลุ่มข้อมูลที่เราต้องการ ใช้ keyword
enum
enum Keyboard {
UP,
DOWN,
LEFT,
RIGHT
}
match
เป็นตัวช่วยจัดการ condition ของenum
เช่น
#![allow(dead_code)] // this line prevents compiler warnings
enum Species {
Crab,
Octopus,
Fish,
Clam
}
struct SeaCreature {
species: Species,
name: String,
arms: i32,
legs: i32,
weapon: String,
}
fn main() {
let ferris = SeaCreature {
species: Species::Crab,
name: String::from("Ferris"),
arms: 2,
legs: 4,
weapon: String::from("claw"),
};
match ferris.species {
Species::Crab => println!("{} is a crab",ferris.name),
Species::Octopus => println!("{} is a octopus",ferris.name),
Species::Fish => println!("{} is a fish",ferris.name),
Species::Clam => println!("{} is a clam",ferris.name),
}
}
Enumerations with Data
- element ของ
enum
สามารถเป็นได้ทั้ง data type เดียว หรือมีหลาย data type ก็ได้ - เมื่อใช้
match
มาจับคู่ของenum
เราสามารถผูกตัวแปรให้ value ได้เลย enum
หลายๆคนรู้จักในชื่อtagged union
- algebraic types หมายถึงการเอา type หลายๆตัวมารวมกันเป็น type ใหม่
enum Species { Crab, Octopus, Fish, Clam }
enum PoisonType { Acidic, Painful, Lethal }
enum Size { Big, Small }
enum Weapon {
Claw(i32, Size),
Poison(PoisonType),
None
}
- ดู enum
Weapon
ข้างในเป็น data type คนละชนิด
สรุปบทที่ 3
บทนี้มีทฤษฎีพวก memory มาเกี่ยวข้อง ซึ่งถ้าอ่านเพิ่มเติม และเข้าในว่า ข้อมูลแต่ละชนิดเก็บลง memory แบบใดบ้าง จะทำให้เราเข้าใจการทำงาน รวมถึงจัดการกับ ตัวแปร, reference ได้ดีขึ้น (ส่วนตัวผมก็ยังมีปัญหาตรงนี้เยอะมากๆ และก็พยายามอ่านพวกนี้เรื่อยๆ)
ส่วนเรื่อง Enum และ Match ใช้บ่อยๆ จนชอบ และก็สนุก และมีประโยชน์มากๆ
อ่านเพิ่มเติม