手続き型マクロ: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フィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- 宣言的マクロ(`macro_rules!`)
- 手続き型マクロ:Derive、Function
- Unsafe Rustを扱う