rust

Rustのマクロ中で定シンボルを繰り返す

More than 1 year has passed since last update.

Introduction

Rustのマクロ中の変数繰り返し$( $val ),*で、$valでなく定シンボルを$valと同じ数だけ繰り返したいことがあったのですが、The bookによるとそのままではできないようでした。
そこでうまくやるためのワークアラウンドを考えてみました。

ソース例

例えば、以下のようなマクロを書きたいわけです。

macro_rules! def_func {
    ( $name:ident, $( $x:expr ),* ) => {
        fn $name<T: Fn($( i64 ),*) -> i64> (f: T) -> i64 {
            f($( $x ),*)
        }
    };
}

fn main() {
    def_func!(foo, 1i64);
    println!("{}", foo(|x| x + 2i64));
}

これをやると、Fn($( i64 ),*) -> i64$(),*中にマクロ変数を含まないのでコンパイルエラーになります。

対策

マクロのオーバーロードを活用します。

macro_rules! def_func {
    ( $name:ident, $( $x:expr ),* ) => {
        def_func!($name, $( $x; i64 ),*);
    };

    ( $name:ident, $( $x:expr; $i64:ty ),* ) => {
        fn $name<T: Fn($( $i64 ),*) -> i64> (f: T) -> i64 {
            f($( $x ),*)
        }
    };
}

fn main() {
    def_func!(foo, 1i64);
    println!("{}", foo(|x| x + 2i64));
}

まあ、言われてみればかなり自明です。

結論

もしもっとまともな方法がありそうでしたら教えてください。

この他にもマクロのオーバーロードを使えば表現力を増すことができそうですね。

自分のブログからの転載