0Pricing
Learn Rust Coding · レッスン

手続き型マクロ:Derive、Function

カスタム`#[derive]`マクロや関数風マクロなど、より複雑なコード生成を行う手続き型マクロについて詳しく学びます。

「手続き型マクロ:Derive、Function」はCoddyKit上の無料Learn Rust Codingレッスンです。 これはレッスン2/3です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはLearn Rust Coding学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Learn Rust Codingコースには全3レッスンが含まれています。

手続き型マクロ入門

手続き型マクロの世界へようこそ。宣言的マクロ(macro_rules!)とは異なり、手続き型マクロはRustのコード自体を操作する関数のようなものです。

入力として TokenStream を受け取り、処理したうえで別の TokenStream を返します。これにより、より複雑なコード生成が可能になります。

手続き型マクロの種類

Rustには、主に3種類の手続き型マクロがあります。

  • 関数風マクロ:通常の関数呼び出しのように見え、同じように動作します。例:my_macro!(...)。
  • deriveマクロ:#[derive(MyTrait)] を使用して、構造体や列挙型にトレイトを自動的に実装できます。
  • 属性マクロ:項目に適用できるカスタム属性を定義できます。例:#[route("/path")]。

`proc-macro` クレート

手続き型マクロは、専用のクレート種別に置く必要があります。Cargo.toml では、次のように宣言します。

これにより、そのクレートにコンパイル時にコードを変換するマクロが含まれていることをCargoに伝えます。

[package]
name = "my_macros"
version = "0.1.0"
edition = "2021"

[lib]
proc-macro = true

関数風マクロの説明

関数風マクロは、proc_macro::TokenStream を受け取り、別の TokenStream を返す関数に #[proc_macro] 属性を付けて定義します。

カスタム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マクロは、最もよく使われる種類です。構造体や列挙型にトレイトを自動的に実装できます。

#[derive(Debug)] と記述すると、コンパイル時にマクロが実行され、型が Debug トレイトを実装するために必要なコードが生成されます。

`#[derive]` の実装(概念)

カスタムderiveマクロは通常、syn(RustコードをASTに解析するためのライブラリ)や quote(ASTからRustコードを生成するためのライブラリ)などを使用して構築します。

#[proc_macro_derive(MyTrait)] が付いた関数を定義します。この関数は構造体または列挙型を表す TokenStream を受け取り、生成したトレイト実装を返します。

/* 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 を見てみましょう。Point 構造体に #[derive(Debug)] を追加すると、Rustが 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マクロに似ていますが、あらゆる項目(関数、構造体、モジュールなど)に適用できます。適用先の項目と、括弧内に指定された引数を入力として受け取ります。

一般的な用途には、Webフレームワークのルーティング(例:#[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マクロ:構造体や列挙型にトレイトを自動実装する場合に使用します。
  • 属性マクロ:カスタム属性に基づいて、特定の項目(関数や構造体など)のコードを変更または生成する場合に使用します。

それぞれの種類には、Rustの構文と機能を拡張するうえで固有の役割があります。

クイックチェック:マクロの種類

手続き型マクロについて、次の記述のうち正しいものはどれでしょうか。

振り返り:コード生成の力

手続き型マクロの高度な世界を学びました。

  • カスタム構文のための関数風マクロについて学びました。
  • #[derive] マクロによってトレイトの実装を自動化する方法を理解しました。
  • 項目単位のコード生成に使用する属性マクロについて簡単に学びました。

手続き型マクロは、定型コードを減らし、Rustの機能を拡張するための強力なツールです。コードを書くコードを作成できるようになります。

よくある質問

「手続き型マクロ:Derive、Function」レッスンは無料ですか?

はい。「手続き型マクロ:Derive、Function」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Learn Rust Codingコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Learn Rust Codingコースには全3レッスンが含まれています。

「手続き型マクロ:Derive、Function」で何を学びますか?

カスタム`#[derive]`マクロや関数風マクロなど、より複雑なコード生成を行う手続き型マクロについて詳しく学びます。 ブラウザで直接実行するハンズオンコードでLearn Rust Codingを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

Learn Rust Codingを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのLearn Rust Codingは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン2/3です。

「手続き型マクロ:Derive、Function」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このLearn Rust Codingレッスンでコードを書いて実行できますか?

はい。すべてのLearn Rust Codingレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. 宣言的マクロ(`macro_rules!`)
  2. 手続き型マクロ:Derive、Function
  3. Unsafe Rustを扱う
← Learn Rust Codingに戻る