0x90

一回休み

Using constant symbol in rust macro repetition

Since I cannot find this workaround anywhere, I also note this in English.

バッドノウハウくさいですが。

たまにマクロ繰り返しの中で定シンボルを使いたいときがあります:

Sometimes I want to repeat constant in rust macro like this:

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の繰り返しの中には$の変数が一個もないので、rustcはどの変数繰り返しかわからずコンパイルエラーになります。(この場合、繰り返しは一個しかないですが。)

However, Fn($( i64 ),*) -> i64 is invalid, since this repetition does not include any $ variable and rustc cannot tell which repetition it should use (although here we have only one loop).

マクロのオーバーロードを使えば、無理やり実装することができます。

Alternatively, we can use macro overloading:

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));
}

よかったですね。