มาโครแบบประกาศ (`macro_rules!`)
เรียนรู้การเขียนมาโครแบบประกาศเพื่อแยกรูปแบบโค้ดที่ซ้ำกันเป็นนามธรรมและสร้างโค้ดขณะคอมไพล์
มาโครแบบประกาศ (`macro_rules!`) เป็นบทเรียน Learn Rust Coding ฟรีบน CoddyKit นี่คือบทเรียนที่ 1 จากทั้งหมด 3 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Learn Rust Coding และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Learn Rust Coding มีบทเรียนทั้งหมด 3 บทเรียน
มาโคร Rust คืออะไร
มาโครเป็นวิธีเขียนโค้ดที่ใช้เขียนโค้ดอีกที! มาโครคล้ายฟังก์ชัน แต่ทำงานกับต้นไม้ไวยากรณ์ (โครงสร้างของโค้ด) แทนค่า
- ช่วยลดความซ้ำซ้อนของโค้ด
- ช่วยให้ใช้ภาษาสำหรับโดเมนเฉพาะ (DSL) ภายใน Rust ได้
- ทำงานขณะคอมไพล์ โดยขยายเป็นโค้ด Rust ปกติก่อนการคอมไพล์
ไวยากรณ์ของมาโครแบบประกาศ
มาโครแบบประกาศของ Rust ใช้คีย์เวิร์ด macro_rules! โดยกำหนดชุดกฎที่จับคู่กับรูปแบบเฉพาะของโค้ด Rust
ลองนึกภาพว่าเป็นการจับคู่รูปแบบสำหรับส่วนย่อยของโค้ด เมื่อคอมไพเลอร์พบการเรียกใช้มาโคร ก็จะพยายามจับคู่อินพุตกับกฎข้อใดข้อหนึ่งที่คุณกำหนดไว้
`macro_rules!` แรกของคุณ
มาสร้างมาโครอย่างง่ายที่พิมพ์คำทักทายกัน สังเกตคีย์เวิร์ด macro_rules! และไวยากรณ์ () => {} ซึ่งกำหนดกฎที่ไม่มีรูปแบบอินพุต
ลองเรียกใช้ตัวอย่างนี้:
macro_rules! greet {
() => {
println!("Hello from a macro!");
};
}
fn main() {
greet!(); // Call our macro!
}รับอินพุตด้วยตัวระบุรูปแบบ
มาโครสามารถรับอินพุตโดยใช้ "ตัวระบุรูปแบบ" ซึ่งจะบอกมาโครว่าควรคาดหวังและจับไวยากรณ์ Rust ประเภทใด
$expr: นิพจน์ (เช่น1 + 2,"hello")$ident: ตัวระบุ (เช่น ชื่อตัวแปร ชื่อฟังก์ชัน)$ty: ชนิดข้อมูล (เช่นi32,String)$block: บล็อกโค้ด (เช่น{ ... })- ...และยังมีอีกมากมาย!
มาโครที่รับอาร์กิวเมนต์
ต่อไปนี้คือมาโครที่รับนิพจน์ ($e:expr) และพิมพ์ค่าของนิพจน์นั้น ส่วน :expr คือตัวระบุรูปแบบ
จากนั้น $e ที่จับมาได้จะพร้อมใช้งานในเนื้อหาของมาโคร มาโคร stringify! จะแปลงนิพจน์ให้เป็นตัวแทนในรูปสตริง
macro_rules! debug_print {
($e:expr) => {
println!("Debug: {} = {:?}", stringify!($e), $e);
};
}
fn main() {
let x = 10;
debug_print!(x + 5);
debug_print!("Rust macros are fun");
}จัดการอินพุตหลายรายการ
หากต้องการให้แมโครรับอาร์กิวเมนต์หลายรายการที่มีชนิดเดียวกัน คุณสามารถใช้ตัวดำเนินการทำซ้ำได้ดังนี้: $()*
$(): เนื้อหาภายในคือรูปแบบที่จะทำซ้ำ*: ทำซ้ำตั้งแต่ศูนย์ครั้งขึ้นไป+: ทำซ้ำตั้งแต่หนึ่งครั้งขึ้นไป- คุณยังสามารถระบุตัวคั่นได้ เช่น
$(...),*สำหรับรายการที่คั่นด้วยจุลภาค
แมโครที่มีอาร์กิวเมนต์ทำซ้ำ
มาสร้างแมโครที่รับนิพจน์หลายรายการซึ่งคั่นด้วยจุลภาค และพิมพ์แต่ละรายการแยกกัน ความสามารถนี้มีประโยชน์อย่างมากสำหรับการสร้างโครงสร้างที่มีลักษณะเหมือนรายการ
macro_rules! print_all {
( $( $x:expr ),* ) => {
$( // This $(...)* repeats the `println!` call
println!("Item: {:?}", $x);
)*
};
}
fn main() {
print_all!(1, "hello", true, 3.14);
print_all!("Just one item");
}ทำความเข้าใจความเป็นระเบียบของแมโคร
แมโครของ Rust มี "ความเป็นระเบียบ" ซึ่งหมายความว่า ตัวแปรที่กำหนดภายในแมโครจะไม่ชนกับตัวแปรภายนอกโดยไม่ได้ตั้งใจ แม้ว่าจะใช้ชื่อเดียวกันก็ตาม
คอมไพเลอร์จะเปลี่ยนชื่อสิ่งต่าง ๆ ภายในระหว่างการขยายแมโคร เพื่อป้องกันผลข้างเคียงที่ไม่ต้องการ ทำให้แมโครปลอดภัยและคาดเดาพฤติกรรมได้มากขึ้น
วิธีแก้ไขข้อบกพร่องของแมโคร
บางครั้งแมโครอาจไม่ขยายผลลัพธ์ตามที่คุณคาดไว้ Rust มีวิธีดูโค้ดที่ขยายแล้วดังนี้:
- เรียกใช้
cargo expand(ต้องติดตั้งเครื่องมือcargo-expandก่อน) - ใช้
rustc --pretty expandedกับไฟล์ต้นฉบับโดยตรง
วิธีนี้จะแสดงโค้ด Rust ดิบที่แมโครของคุณสร้างขึ้น ซึ่งมีประโยชน์อย่างยิ่งต่อการแก้ไขข้อบกพร่องและทำความเข้าใจพฤติกรรมของแมโครที่ซับซ้อน
แบบทดสอบการจับคู่รูปแบบของแมโคร
พิจารณาการกำหนดแมโครต่อไปนี้:
macro_rules! make_tuple {
( $x:expr, $y:expr ) => {
($x, $y)
};
}บรรทัดใดต่อไปนี้จะคอมไพล์และใช้แมโคร make_tuple! ได้สำเร็จ
ทบทวน: แมโครแบบประกาศ
ในบทเรียนนี้ คุณได้เรียนรู้เกี่ยวกับแมโครแบบประกาศโดยใช้ macro_rules!:
- แมโครเหล่านี้สร้างโค้ดขณะคอมไพล์ และช่วยลดรูปแบบโค้ดที่ต้องเขียนซ้ำ
- แมโครใช้การจับคู่รูปแบบเพื่อรับอินพุตตามไวยากรณ์
- ตัวระบุรูปแบบ เช่น
$exprและ$identใช้ระบุชนิดของไวยากรณ์ที่คาดว่าจะได้รับ - ตัวดำเนินการทำซ้ำ เช่น
$()*รองรับอาร์กิวเมนต์หลายรายการและตัวคั่นที่ยืดหยุ่น - แมโครมีความเป็นระเบียบ จึงป้องกันการขัดแย้งของชื่อโดยไม่ได้ตั้งใจ
แมโครเป็นเครื่องมือที่ทรงพลังสำหรับลดโค้ดส่วนซ้ำซ้อน และสร้าง API ใน Rust ที่ยืดหยุ่นและใช้งานสะดวก
คำถามที่พบบ่อย
บทเรียน “มาโครแบบประกาศ (`macro_rules!`)” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “มาโครแบบประกาศ (`macro_rules!`)” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Learn Rust Coding ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Learn Rust Coding มีบทเรียนทั้งหมด 3 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “มาโครแบบประกาศ (`macro_rules!`)”
เรียนรู้การเขียนมาโครแบบประกาศเพื่อแยกรูปแบบโค้ดที่ซ้ำกันเป็นนามธรรมและสร้างโค้ดขณะคอมไพล์ คุณปฏิบัติ Learn Rust Coding ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Learn Rust Coding หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน Learn Rust Coding บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 1 จากทั้งหมด 3 บทเรียน
บทเรียน “มาโครแบบประกาศ (`macro_rules!`)” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน Learn Rust Coding นี้ได้ไหม
ได้ บทเรียน Learn Rust Coding ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- มาโครแบบประกาศ (`macro_rules!`)
- มาโครเชิงกระบวนการ: Derive, Function
- การทำงานร่วมกับ Rust แบบไม่ปลอดภัย