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

Kasama Chenkaow
2 min read5 days ago

--

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

(Link ตอนที่แล้ว)

บทนี้จะเกี่ยวกับการจัดระเบียบ project structure ของ Rust โดยจะเรียกรวมๆว่า module system ประกอบไปด้วย Packages, Crates, Modules และ Paths

Packages and Crates

Crates เป็นหน่วยย่อยที่สุดที่ Rust compiler จะ build ในแต่ละครั้ง แบ่งเป็น 2 แบบคือ

  • Binary crate — มองว่าเป็น executable ที่ต้องมี fn main() เป็น entrypoint
  • Library crate — เอิ่ม… ก็คือ library 😅เอาไว้แชร์ให้ project อื่นๆใช้

Package คือ project เรานี่แหล่ะที่ต้องมีอย่างน้อย 1 crate และจะมีกี่ binary crates ก็ได้แต่จะมีได้อย่างมากสุดคือ 1 library crate

Crate root ของ library by default คือ src/lib.rs ส่วนของ binary คือ src/main.rs

Binary crates อื่นๆที่ไม่ใช่ root จะอยู่ใน src/bin/

Modules and Paths

สำหรับ modules ก็จะเป็นหน่วยย่อยที่อยู่ใน crate อีกที พูดง่ายๆก็คือใน 1 crates เราสามารถ define ได้หลาย modules

ยกตัวอย่างเช่น Restuarant crate อาจจะมี module kitchen, module cashier หรือ module tables อะไรแบบนี้

การสร้าง module ก็จะทำได้โดยการสร้าง mod [module_name]; แบบนี้ เสร็จแล้วตอน compile ตัว compiler ก็จะไปหา code ของ module ตามนี้

  • Inline -> อันนี้คือประกาศตรงที่ประกาศ module เลย
mod Kitchen {
// ...body
}
  • In the file `src/[module_name].rs`
  • In the file `src/[module_name]/mod.rs`

และ module สามารถประกาศ module ซ้อน module ได้และเรียกว่า submodule

โดย folders ของ submodules ก็จะอยู่ภายใน folder ของ parent module ไป (ตรงนี้แนะนำว่าดู original content อาจจะเข้าใจง่ายกว่า)

module เป็น private by default (หมายความว่าเฉพาะสิ่งที่อยู่ภายใน module นั้นเท่านั้นที่จะสามารถ refer ถึงของใน module นั้นได้ รวมถึง submodules)

เราสามารถประกาศ public module ได้แบบนี้ pub mod [module_name] ก็จะทำให้ external code เรียกใช้ของใน module ได้

ต่อมาทางหนังสือก็จะพูดถึงการ refer ไปที่ path ของพวก module แล้วก็ของใน module ซึ่ง… เอาจริงๆก็ไม่ได้มีอะไรเท่าไหร่ คล้ายเวลาเรา refer พวก filesystem path เลย

ด้วยความที่คล้าย filesystem path เลยทำให้ใช้ได้ทั้งแบบ absolute และ relative

เช่น code ด้านล่างนี้เป็นต้น

mod front_of_house {
mod hosting {
fn add_to_waitlist() {}
}
}

pub fn eat_at_restaurant() {
// Absolute path
crate::front_of_house::hosting::add_to_waitlist();

// Relative path
front_of_house::hosting::add_to_waitlist();
}

ที่เหลือก็เป็นเรื่องของ privacy แล้วว่าเข้าถึงได้ไหม และด้วยความที่ผมขี้เกียจ และบทความนี้มีไว้สำหรับมือเก่า ก็ไป skimming เอาละกันเนอะ ตรงนี้ไม่ได้มีอะไรน่าสงสัยเท่าไหร่

มีเรื่องที่เกี่ยวกับ path ก็คือการที่เราสามารถ bringing paths into scope ได้ พูดง่ายๆก็คือเทียบกับภาษาอื่นเป็นการ include, using, require อะไรทำนองนี้นั่นแหล่ะ แต่ Rust จะได้ keyword ว่า use

มีความน่าสนใจเล็กน้อยตรง

  • สามารถ re-export ได้แบบนี้ pub use create::front_of_house::housing;
  • สามารถใช้ nested paths ได้แบบนี้ use std::io::{self, Write};
  • สามารถใช้ glob operator ได้แบบนี้ use std::collections::*;

ต่อมาก็จะเป็นเรื่องของการที่เราสามารถ split module ไปอยู่ใน file ของตัวเองได้ ซึ่งจริงๆก็เหมือนกับที่ mentioned ไว้ด้านบน พูดก็คือสมมติเราประกาศ module แบบนี้ใน crate scope

mod front_of_house;

ทีนี้ตัว implementation ของ module เราก็จะสามารถทำได้ 3 ที่ตามด้านบน (inline, src/[module_name].rs, src/[module_name]/mod.rs ) แต่ตัวสุดท้ายเค้าบอกว่าเป็น old style เพราะงั้นก็น่าจะ prefer แบบที่ 1 กับ 2 มากกว่ามั้ง

จบแล้วครับบทที่ 7

--

--

No responses yet