0Pricing
Learn Rust Coding · บทเรียน

มาโครเชิงกระบวนการ: 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 ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. มาโครแบบประกาศ (`macro_rules!`)
  2. มาโครเชิงกระบวนการ: Derive, Function
  3. การทำงานร่วมกับ Rust แบบไม่ปลอดภัย
← กลับไปที่ Learn Rust Coding