Control Flow
Control flow ใน TypeScript เทียบกับ Rust
หัวข้อที่มีชื่อว่า “Control flow ใน TypeScript เทียบกับ Rust”Rust มีโครงสร้าง control-flow ที่คุณรู้จักดีอยู่แล้ว — if, while, for — แต่มีความแตกต่างสำคัญสองข้อ: if และ match เป็น expression ที่ให้ค่ากลับมา และ match เป็นแบบ exhaustive (compiler จะ error ถ้าคุณตกหล่นเคสใดเคสหนึ่ง)
if ในฐานะ expression
หัวข้อที่มีชื่อว่า “if ในฐานะ expression”ใน TypeScript คุณจะหันไปใช้ ternary ? : เมื่อต้องการค่าตามเงื่อนไข ส่วนใน Rust ตัว if เองเป็น expression — ทุก branch ต้องให้ค่า type เดียวกัน
// TypeScriptconst label = score >= 60 ? "pass" : "fail";
// Rustlet label = if score >= 60 { "pass" } else { "fail" };match — switch แบบ exhaustive
หัวข้อที่มีชื่อว่า “match — switch แบบ exhaustive”match ใน Rust เหมือน switch ของ TypeScript แต่เป็นแบบ exhaustive และ expression-oriented compiler รับประกันว่าทุกค่าที่เป็นไปได้ถูกจัดการ pattern สามารถเป็น range, literal, enum และอื่น ๆ ได้
loop, while, for
หัวข้อที่มีชื่อว่า “loop, while, for”loopรันไปเรื่อย ๆ จนกว่าจะเจอbreakต่างจากwhile trueตรงที่loopสามารถ return ค่ากลับมาได้ผ่านbreak valuewhileทำงานตามที่คาดหวังfor item in collectionวนซ้ำบนสิ่งที่ iterate ได้ใด ๆ — ไม่ต้องคำนวณ index เอง
const score = 85;const grade = score >= 90 ? "A" : score >= 80 ? "B" : "C";console.log(grade); // "B"
// switch (not exhaustive by default)switch (score) { case 100: console.log("perfect"); break; default: console.log("ok");}fn main() { let score = 85; // if is an expression let grade = if score >= 90 { "A" } else if score >= 80 { "B" } else { "C" }; println!("{grade}"); // B
// loop with a break value let mut counter = 0; let result = loop { counter += 1; if counter == 5 { break counter * 2; } }; println!("{result}"); // 10
// for over a range for i in 1..=3 { println!("{i}"); }
// match is exhaustive match score { 90..=100 => println!("A"), 80..=89 => println!("B"), _ => println!("C or below"), }}let chain — เงื่อนไขเดียว ตรวจหลายชั้น
หัวข้อที่มีชื่อว่า “let chain — เงื่อนไขเดียว ตรวจหลายชั้น”ใน TypeScript คุณใช้ optional chaining กับ && เพื่อตรวจและ narrow type ในเงื่อนไขเดียวได้เลย ส่วน Rust เมื่อก่อนบังคับให้ซ้อน: if let วางได้แค่ติดกับ if เท่านั้น การตรวจเพิ่มอีกชั้นจึงหมายถึงการ indent เพิ่มอีกชั้น
ตั้งแต่ edition 2024 คุณต่อ let หลายตัวด้วย && ได้ และผสมกับเงื่อนไข boolean ธรรมดาได้ด้วย ตัวแปรที่ bind ไว้ใช้ได้ทั้งในเงื่อนไขถัดไปและใน body ส่วน let ต้องอยู่ระดับบนสุดของเงื่อนไข — ยังใช้ || คั่นระหว่างกันไม่ได้
const cfg = loadConfig();
// TypeScript narrows through optional chaining and &&if (cfg?.retries != null && cfg.retries > 0) { console.log(`retrying ${cfg.retries} times`);}// Before 2024 — nestedif let Some(c) = &cfg { if let Some(n) = c.retries { if n > 0 { println!("retrying {n} times"); } }}
// 2024 edition — one conditionif let Some(c) = &cfg && let Some(n) = c.retries && n > 0{ println!("retrying {n} times");}let chain ผูกกับ edition 2024 (stabilize ใน Rust 1.88) เพราะต้องพึ่งการเปลี่ยน temporary scope ของ if let ที่มาพร้อม edition นี้ ถ้าใช้ edition เก่ากว่า compiler จะ error ว่า “let chains are only allowed in Rust 2024 or later”
fn sum_first_two(nums: &[u8]) -> Option<u8> { let mut iter = nums.iter(); if let Some(first) = iter.next() && let Some(second) = iter.next() { first.checked_add(*second) } else { None }}
#[derive(Debug)]struct Config { retries: Option<u32> }
fn main() { println!("{:?}", sum_first_two(&[3, 4, 5])); println!("{:?}", sum_first_two(&[9]));
let cfg = Some(Config { retries: Some(3) }); // One condition, three checks — no nesting. if let Some(c) = &cfg && let Some(n) = c.retries && n > 0 { println!("retrying {n} times"); }}Compiling…
ลองเล่นดู
หัวข้อที่มีชื่อว่า “ลองเล่นดู”fn classify(n: i32) -> &'static str { match n { i32::MIN..=-1 => "negative", 0 => "zero", 1..=9 => "small positive", _ => "large positive", }}
fn main() { let score = 85; let grade = if score >= 90 { "A" } else if score >= 80 { "B" } else { "C" }; println!("Grade: {grade}");
for n in [0, -3, 5, 42] { println!("{n} is {}", classify(n)); }}Compiling…