มาโครเชิงกระบวนการ: Derive, Function
เจาะลึกมาโครเชิงกระบวนการ รวมถึงมาโคร `#[derive]` แบบกำหนดเองและมาโครรูปแบบฟังก์ชัน เพื่อสร้างโค้ดที่ซับซ้อนยิ่งขึ้น
มาโครเชิงกระบวนการ: Derive, Function เป็นบทเรียน Learn Rust Coding ฟรีบน CoddyKit นี่คือบทเรียนที่ 2 จากทั้งหมด 3 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Learn Rust Coding และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Learn Rust Coding มีบทเรียนทั้งหมด 3 บทเรียน
รู้จักแมโครแบบกระบวนการ
ยินดีต้อนรับสู่โลกของแมโครแบบกระบวนการ! ต่างจากแมโครแบบประกาศ (macro_rules!) แมโครแบบกระบวนการทำงานคล้ายฟังก์ชันที่ประมวลผลโค้ด Rust โดยตรง
แมโครเหล่านี้รับ TokenStream เป็นอินพุต ประมวลผล แล้วส่งคืน TokenStream อีกชุดหนึ่ง ทำให้สามารถสร้างโค้ดที่ซับซ้อนกว่ามากได้
ชนิดของแมโครแบบกระบวนการ
Rust มีแมโครแบบกระบวนการหลักสามชนิด:
- แมโครคล้ายฟังก์ชัน: มีรูปแบบและการทำงานคล้ายการเรียกฟังก์ชันทั่วไป เช่น
my_macro!(...) - แมโคร derive: ช่วยให้คุณนำ trait ไปใช้กับโครงสร้างและ enum ได้โดยอัตโนมัติผ่าน
#[derive(MyTrait)] - แมโครแอตทริบิวต์: ช่วยให้คุณกำหนดแอตทริบิวต์แบบกำหนดเองที่นำไปใช้กับรายการต่าง ๆ ได้ เช่น
#[route("/path")]
คร rate `proc-macro`
แมโครแบบกระบวนการต้องอยู่ใน crate ชนิดพิเศษของตนเอง ใน Cargo.toml ให้ประกาศดังนี้:
การประกาศนี้แจ้งให้ Cargo ทราบว่า crate มีแมโครที่ใช้แปลงโค้ดขณะคอมไพล์
[package]
name = "my_macros"
version = "0.1.0"
edition = "2021"
[lib]
proc-macro = trueอธิบายแมโครคล้ายฟังก์ชัน
แมโครคล้ายฟังก์ชันกำหนดด้วยแอตทริบิวต์ #[proc_macro] บนฟังก์ชันที่รับ proc_macro::TokenStream และส่งคืนค่าชนิดเดียวกัน
แมโครประเภทนี้มีประโยชน์สำหรับ DSL แบบกำหนดเอง (ภาษาที่เจาะจงโดเมน) หรือการทำซ้ำโค้ดที่ซับซ้อน ซึ่ง macro_rules! ไม่สามารถจัดการได้
use proc_macro::TokenStream;
#[proc_macro]
pub fn my_function_macro(input: TokenStream) -> TokenStream {
// Logic to transform input TokenStream
// ...
input // For example, return the input unchanged
}ตัวอย่างแมโครคล้ายฟังก์ชัน
ต่อไปนี้คือตัวอย่างเชิงแนวคิด แมโคร `greet_name!` ที่สร้างคำสั่งพิมพ์ผล การใช้งานจริงจะต้องแยกวิเคราะห์อินพุต TokenStream เพื่อดึงชื่อออกมา
แม้ว่าการกำหนดแมโครจะซับซ้อน แต่การใช้งานนั้นเรียบง่ายและทรงพลัง
/* In 'my_macros/src/lib.rs' */
use proc_macro::TokenStream;
#[proc_macro]
pub fn greet_name(input: TokenStream) -> TokenStream {
// Imagine parsing 'input' to get a name like 'World'
// and generating: println!("Hello, World!");
"println!(\"Hello, {}!\", \"CoddyKit\");".parse().unwrap()
}
/* In 'my_app/src/main.rs' */
use my_macros::greet_name;
fn main() {
greet_name!("CoddyKit");
}ทำความเข้าใจแมโคร `#[derive]`
แมโคร derive เป็นชนิดที่พบบ่อยที่สุด ช่วยให้คุณนำ trait ไปใช้กับโครงสร้างหรือ enum ได้โดยอัตโนมัติ
เมื่อคุณเขียน #[derive(Debug)] แมโครจะทำงานขณะคอมไพล์เพื่อสร้างโค้ดที่จำเป็นสำหรับให้ชนิดของคุณนำ trait Debug ไปใช้ได้
การนำ `#[derive]` ไปใช้ (แนวคิด)
โดยทั่วไป แมโคร derive แบบกำหนดเองจะสร้างโดยใช้ไลบรารี เช่น syn (สำหรับแยกวิเคราะห์โค้ด Rust เป็น AST) และ quote (สำหรับสร้างโค้ด Rust จาก AST)
คุณจะกำหนดฟังก์ชันที่มีคำอธิบายกำกับด้วย #[proc_macro_derive(MyTrait)] ฟังก์ชันนี้รับ TokenStream ที่แทนโครงสร้างหรือ enum และส่งคืนการนำ trait ที่สร้างขึ้นไปใช้
/* In 'my_macros/src/lib.rs' */
use proc_macro::TokenStream;
use syn::{parse_macro_input, DeriveInput};
use quote::quote;
#[proc_macro_derive(MyDebug)] // MyDebug is the trait name
pub fn my_debug_derive(input: TokenStream) -> TokenStream {
let ast = parse_macro_input!(input as DeriveInput);
let name = &ast.ident;
let expanded = quote! {
impl std::fmt::Debug for #name {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct(stringify!(#name)).finish()
}
}
};
expanded.into()
}ตัวอย่างการใช้ `#[derive(Debug)]`
มาดูตัวอย่างการใช้งานจริงของแมโคร derive ที่คุณน่าจะเคยใช้ นั่นคือ Debug เมื่อเพิ่ม #[derive(Debug)] ให้กับโครงสร้าง Point ของเรา Rust จะนำ trait Debug ไปใช้โดยอัตโนมัติ ทำให้เราพิมพ์เนื้อหาของโครงสร้างได้อย่างเป็นระเบียบ
#[derive(Debug)]
struct Point {
x: i32,
y: i32,
}
fn main() {
let p = Point { x: 10, y: 20 };
println!("My point is: {:?}", p);
}แมโครแอตทริบิวต์: `#[my_attribute]`
แมโครแอตทริบิวต์ คล้ายกับแมโคร derive แต่สามารถนำไปใช้กับรายการใด ๆ ได้ เช่น ฟังก์ชัน โครงสร้าง และโมดูล แมโครเหล่านี้รับรายการที่ผูกอยู่ด้วย รวมถึงอาร์กิวเมนต์ใด ๆ ในวงเล็บ เป็นอินพุต
การใช้งานทั่วไป ได้แก่ การกำหนดเส้นทางของเฟรมเวิร์กเว็บ เช่น #[get("/users")] หรือการตั้งค่าการทดสอบ เช่น #[test]
/* In 'my_macros/src/lib.rs' */
use proc_macro::TokenStream;
#[proc_macro_attribute]
pub fn log_calls(attr: TokenStream, item: TokenStream) -> TokenStream {
// Imagine adding println! statements to 'item'
item
}
/* In 'my_app/src/main.rs' */
use my_macros::log_calls;
#[log_calls("entry_point")]
fn my_function() {
println!("Inside my_function");
}
fn main() {
my_function();
}ควรใช้แมโครชนิดใดเมื่อใด
- แมโครคล้ายฟังก์ชัน: ใช้สำหรับภาษาขนาดเล็กแบบกำหนดเอง หรือการแปลงบล็อกโค้ดใด ๆ ที่ซับซ้อน
- แมโคร derive: ใช้สำหรับนำ trait ไปใช้กับโครงสร้างและ enum โดยอัตโนมัติ
- แมโครแอตทริบิวต์: ใช้สำหรับแก้ไขหรือสร้างโค้ดรอบรายการเฉพาะ เช่น ฟังก์ชันหรือโครงสร้าง โดยอิงตามแอตทริบิวต์แบบกำหนดเอง
แมโครแต่ละชนิดมีจุดประสงค์เฉพาะในการขยายไวยากรณ์และความสามารถของ Rust
ตรวจสอบความเข้าใจอย่างรวดเร็ว: ชนิดของแมโคร
ข้อความใดต่อไปนี้เกี่ยวกับแมโครแบบกระบวนการเป็นจริง
ทบทวน: พลังของการสร้างโค้ด
คุณได้สำรวจโลกขั้นสูงของแมโครแบบกระบวนการแล้ว
- เราได้เรียนรู้เกี่ยวกับแมโครคล้ายฟังก์ชันสำหรับไวยากรณ์แบบกำหนดเอง
- ทำความเข้าใจว่าแมโคร
#[derive]ช่วยทำให้การนำ trait ไปใช้เป็นอัตโนมัติได้อย่างไร - ได้กล่าวถึงแมโครแอตทริบิวต์โดยสังเขป ซึ่งใช้สร้างโค้ดในระดับรายการ
แมโครแบบกระบวนการเป็นเครื่องมือที่ทรงพลังสำหรับลดโค้ดส่วนซ้ำซ้อนและขยายความสามารถของ Rust ทำให้คุณสามารถเขียนโค้ดที่เขียนโค้ดได้
คำถามที่พบบ่อย
บทเรียน “มาโครเชิงกระบวนการ: Derive, Function” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “มาโครเชิงกระบวนการ: Derive, Function” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Learn Rust Coding ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Learn Rust Coding มีบทเรียนทั้งหมด 3 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “มาโครเชิงกระบวนการ: Derive, Function”
เจาะลึกมาโครเชิงกระบวนการ รวมถึงมาโคร `#[derive]` แบบกำหนดเองและมาโครรูปแบบฟังก์ชัน เพื่อสร้างโค้ดที่ซับซ้อนยิ่งขึ้น คุณปฏิบัติ Learn Rust Coding ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Learn Rust Coding หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน Learn Rust Coding บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 2 จากทั้งหมด 3 บทเรียน
บทเรียน “มาโครเชิงกระบวนการ: Derive, Function” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน Learn Rust Coding นี้ได้ไหม
ได้ บทเรียน Learn Rust Coding ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- มาโครแบบประกาศ (`macro_rules!`)
- มาโครเชิงกระบวนการ: Derive, Function
- การทำงานร่วมกับ Rust แบบไม่ปลอดภัย