สรุป The Rust Programming Language ฉบับมือเก่า ตอนที่ 3

Kasama Chenkaow
2 min readDec 5, 2024

--

บทความนี้สรุปจากหนังสือ The Rust Programming Language chapter 3 ด้วยความคิดเห็นของผมเอง อาจมีการตีความที่มีโอกาสผิดพลาดได้ ทางที่ดีถ้าอยากได้ reference จริงๆแนะนำต้นทางครับ

(Link บทความที่แล้ว)

บทนี้ (Common Programming Concepts) เป็นการอธิบายพวก concepts ทั่วๆไปของ Rust ซึ่งอาจจะมีบางส่วนที่ overlap กับภาษาอื่นๆด้วย โดยแบ่งเป็น 5 หัวข้อย่อยด้วยกันดังนี้

1. Variables and Mutability — let, const, mut

let จะเป็น immutable by default โดยถ้าพยายาม re-assign value ให้กับมันจะโดน compiler ด่า แต่! สามารถ shadow มันได้โดยการ re-declare ได้ตัวแปรชื่อเดิมด้วย keyword let อีกครั้ง (ตรงนี้ ผมยัง 50/50 อยู่ว่าจะชอบหรือไม่ชอบ คือถ้า shadow ใน inner scope ผมยังมองว่าอาจจะโอเค แต่สามารถ shadow ใน scope เดิมได้ แถมสามารถประกาศด้วย type ใหม่ได้อีกด้วย)

const immutable เหมือนกันแต่ always immutable และไม่สามารถถูก shadow หรือ re-declare ได้ แถม value ที่ assign ให้จะต้องสามารถ evaluate ได้ที่ compile time (เช่น const AA = 10 * 20 แบบนี้ทำได้ ถึงแม้ตัว expressions จะถูก process ที่ runtime แต่สามารถ evaluate ได้ตั้งแต่ที่ compile time แล้ว)

mut อันนี้เป็น keyword ที่ใช้บอกว่าตัวแปร let นี้เป็น immutable ซึ่งก็ถือจะสามารถถูก re-assign value ภายหลังได้นั่นเอง

2. Data Types

ส่วนนี้จะมีความคล้ายกับ data types ทั่วๆไปในภาษาอื่นมากๆ และด้วยความที่เป็น statically typed language ในทุกๆ variable ตัว compiler จะต้องสามารถระบุ type ให้มันได้ บางครั้ง compiler สามารถที่จะ infer type from usage แต่ถ้ามันมีหลาย possibilities เราจะต้อง explicitly define type เสมอ (จริงๆก็ทำนองเดียวกับพวก statically typed language อื่นๆ)

หนังสือแบ่งเป็น 2 หัวข้อใหญ่ๆ

Scala types ซึ่งบอกตรงๆว่าตรงนี้พวกมือเก่าอ่านเร็วๆได้เลย ไม่มีอะไรน่าแปลกใจเท่าไหร่ เป็นพวก Integer, Boolean, Character ปกติทั่วๆไป แต่รายละเอียดลึกๆก็ตามหนังสือเลย

Compound Types เป็น type ที่ประกอบไปด้วย values มากกว่า 1 เช่น Tuple หรือ Array ส่วนนี้ก็คล้ายกับภาษาอื่น มีจุดที่น่าสนใจบางอย่าง

  • Array จะมีความคล้ายๆกับ C ที่ทุก value ต้องเป็น type เดียวกัน และเป็น fixed length เสมอ
  • Array สามารถ initial ได้ด้วย something like let a = [3; 5]และจะได้ค่า [3,3,3,3,3]
  • ยังคงมี out of bound error อยู่ถ้าเราพยายาม access index ที่จะไม่อยู่ใน range ของ Array (ตรงส่วนนี้ผมแอบผิดหวังเล็กๆว่ามันควรที่จะด่าตั้งในที่ compile time ไปเลย)
  • ทั้ง Array และ Tuple สามารถทำ destructuring assigement ได้เช่น
let y = [1, 2, 3, 4, 5];
let [a, b, c, tail @ ..] = y;
println!("a is {a}, b is {b}, c is {c}, tail is {:?}", tail);

หรือสำหรับ Tuple

let x = (500, 6.4, 1);
let (a, b, ..) = x;
println!("a is {a}, b is {b})");

3. Functions

แบ่งเป็น 3 ส่วนคือ

  • `Parameters` — ส่วนนี้เอาตรงๆนะ สามารถ skimming ดู syntax แล้วข้ามๆไปก่อนได้เลย
  • `Statements and Expressions` — อันนี้มีประเด็นนิดหน่อยตรง statement จะไม่ return value เด็ดขาด แปลว่าถ้าเราเขียน let x = (let y = 6) แบบนี้โดน compiler ด่า (เพราะ let y = 6 เป็น statement และไม่ return value) ในขณะที่โค้ดแบบ
let y = {
let x = 3;
x+1
}

แบบนี้ y จะมีค่าเท่ากับ 4 เพราะตัว code block เป็น expression ที่มี return value (น่าสนใจที่ Rust ใช้การที่ถ้า expression มี semicolon จะถือว่าเป็น statement เช่น บรรทัด x+1 ไม่มี semicolon เลยถือว่ายังเป็น expression และ return value)

  • `Return values `— อันนี้ก็สามารถ skimming ข้ามๆได้ (สามารถใช้ last expression เป็น return value ได้เหมือน Ruby เย้)

4. Comments

// ขอข้าม 555

5. Control Flow — If, Loop

  • If — แทบจะข้ามๆได้, supports something like ternary let number = if condition {5} else {6};
  • Loop — ไม่อยากจะพูดเลยว่ามันคือ while (true) นี่เอง 555 แต่ support return value from loop
    let result = loop {
counter += 1;

if counter == 10 {
break counter * 2;
}
};

หรือสามารถ label loop แบบนี้

fn main() {
let mut count = 0;
'counting_up: loop {
println!("count = {count}");
let mut remaining = 10;

loop {
println!("remaining = {remaining}");
if remaining == 9 {
break;
}
if count == 2 {
break 'counting_up;
}
remaining -= 1;
}

count += 1;
}
println!("End count = {count}");
}
  • ที่เหลือ while และ for สามารถ skimming ได้

โอเค จบไปแล้วกับบทที่ 3 (เห้อ บทนี้นานหน่อย)

--

--

No responses yet