标签: rust-decl-macros

从父模块导入宏

我在箱子里重复使用宏时遇到了麻烦.

如果在以下位置定义了宏./src/macros.rs:

#[macro_export]
macro_rules! my_macro {
    ...
}
Run Code Online (Sandbox Code Playgroud)

用于./src/lib.rs:

#[macro_use]
pub mod macros;
Run Code Online (Sandbox Code Playgroud)

我看不到这个宏./src/submod/lib.rs:

my_macro!(...);
Run Code Online (Sandbox Code Playgroud)

它会产生错误消息error: macro undefined: 'my_macro!'.

有没有办法在这个子模块中导入这个宏submod

rust rust-macros rust-decl-macros

9
推荐指数
1
解决办法
1464
查看次数

如何编写一个显示文件和行号以及可变数量参数的宏?

我在 Rust 中发现了几个有用的宏,即:file!(), line!(), stringify!()我还发现 Rust 允许带有可变参数的宏,如下所述

macro_rules! print_all {
    ($($args:expr),*) => {{
        $(
            println!("{}", $args);
        )*
    }}
}
Run Code Online (Sandbox Code Playgroud)

我的目标是以某种方式将所有这些宏合并到一个我将在故障排除/调试期间使用的宏中。trace!因此在以下示例中调用宏:

let a: i32 = 1;
let b: i32 = 2;
trace!(a,b)
Run Code Online (Sandbox Code Playgroud)

应该扩展到这样的东西:

println!("TRACE: file: {}, line: {}, a: {}, b: {}", file!(), line!(), a, b);
Run Code Online (Sandbox Code Playgroud)

是否可以?如果是,这样的宏将如何工作?

rust rust-macros rust-decl-macros

6
推荐指数
1
解决办法
2817
查看次数

@符号在声明性宏中的含义是什么?

我已经看到了@宏中使用的符号,但我在Rust Book或任何官方文档或博客文章中都找不到它.例如,在此Stack Overflow答案中,它的使用方式如下:

macro_rules! instructions {
    (enum $ename:ident {
        $($vname:ident ( $($vty: ty),* )),*
    }) => {
        enum $ename {
            $($vname ( $($vty),* )),*
        }

        impl $ename {
            fn len(&self) -> usize {
                match self {
                    $($ename::$vname(..) => instructions!(@count ($($vty),*))),*
                }
            }
        }
    };

    (@count ()) => (0);
    (@count ($a:ty)) => (1);
    (@count ($a:ty, $b:ty)) => (2);
    (@count ($a:ty, $b:ty, $c:ty)) => (3);
}

instructions! {
    enum Instruction {
        None(),
        One(u8),
        Two(u8, u8),
        Three(u8, u8, u8) …
Run Code Online (Sandbox Code Playgroud)

syntax rust rust-macros rust-decl-macros

5
推荐指数
1
解决办法
270
查看次数

如何在 Rust 中对宏进行字符串化之前进行扩展?

我正在尝试仅使用宏在 Rust 中编写一个 quine。为了做到这一点,我将main函数嵌入到 macro 中f1,并尝试嵌入f1in f2with的文字表示stringify!

到目前为止,这是我的代码:

macro_rules!f1{()=>(fn main(){println!("macro_rules!{}\nmacro_rules!f2{{($x:expr)=>(stringify!($x))}}\nf1!();",f2!(f1));})}
macro_rules!f2{($x:expr)=>(stringify!($x))}
f1!();
Run Code Online (Sandbox Code Playgroud)

不出所料,输出是:

macro_rules!f1
macro_rules!f2{($x:expr)=>(stringify!($x))}
f1!();
Run Code Online (Sandbox Code Playgroud)

我需要的是f1在字符串化之前进行扩展以使程序成为quine。我怎样才能做到这一点?

rust rust-macros rust-decl-macros

5
推荐指数
0
解决办法
204
查看次数

如何在声明性宏中生成特征边界?

我有一个具有大量关联类型的特征。我想要一个在 where 子句绑定的两侧使用这些关联类型的函数:

trait Kind {
    type A;
    type B;
    // 20+ more types
}

trait Bound<T> {}

fn example<K1, K2>()
where
    K1: Kind,
    K2: Kind,
    K1::A: Bound<K2::A>,
    K1::B: Bound<K2::B>,
    // 20+ more bounds
{
}
Run Code Online (Sandbox Code Playgroud)

输入所有边界会有点脆弱,所以我想创建一个宏来生成这个:

fn example<K1, K2>()
where
    K1: Kind,
    K2: Kind,
    how_do_i_write_this!(K1, K2, Bound, [A, B, /* 20+ more types */])
{
}
Run Code Online (Sandbox Code Playgroud)

但是,在 where 子句绑定的右侧调用宏会导致错误:

macro_rules! bound {
    () => { std::fmt::Debug };
}

fn another_example() 
    where
    u8: bound!(),
{}
Run Code Online (Sandbox Code Playgroud)
error: expected one of `(`, …
Run Code Online (Sandbox Code Playgroud)

type-bounds rust rust-decl-macros

5
推荐指数
2
解决办法
126
查看次数

在声明性宏中构建所有元素对(二次集)

我有一个标识符列表,我想为该列表中的每对标识符调用一个宏.例如,如果我有a,b并且c,我想生成这个:

println!("{} <-> {}", a, a);
println!("{} <-> {}", a, b);
println!("{} <-> {}", a, c);
println!("{} <-> {}", b, a);
println!("{} <-> {}", b, b);
println!("{} <-> {}", b, c);
println!("{} <-> {}", c, a);
println!("{} <-> {}", c, b);
println!("{} <-> {}", c, c);
Run Code Online (Sandbox Code Playgroud)

当然,这是一个虚拟的例子.在我的真实代码中,标识符是类型,我想生成impl块或类似的东西.

我的目标是仅列出每个标识符一次.在我的实际代码中,我有大约12个标识符,并且不想手动写下所有12²= 144对.所以我认为宏可能会帮助我.我知道它可以通过所有强大的过程宏来解决,但我希望它也可以使用声明式宏(macro_rules!).


我尝试了我认为直观的处理方法(两个嵌套的"循环")(Playground):

macro_rules! print_all_pairs {
    ($($x:ident)*) => {
        $(
            $(
                println!("{} <-> {}", $x, $x);  // `$x, $x` feels awkward... …
Run Code Online (Sandbox Code Playgroud)

rust rust-macros rust-decl-macros

4
推荐指数
1
解决办法
83
查看次数

如何从声明性宏返回新字符串?

所以我在这里,和 Rustlings 一起用卡车运输,直到我在测试 4 中遭到猛烈攻击。

它要求我编写一个满足以下代码的宏:

fn main() {
    if my_macro!("world!") != "Hello world!" {
        panic!("Oh no! Wrong output!");
    }
}
Run Code Online (Sandbox Code Playgroud)

所以,我写了这个:

macro_rules! my_macro {
    ($val:expr) => {
        println!("Hello {}", $val);
    }
}
Run Code Online (Sandbox Code Playgroud)

Rustlings 吐出了这一点:

fn main() {
    if my_macro!("world!") != "Hello world!" {
        panic!("Oh no! Wrong output!");
    }
}
Run Code Online (Sandbox Code Playgroud)

哪个,你知道。我明白了。我明白问题是什么,但我不明白如何编写一个满足代码的宏。我可以更改正在测试的代码,但这不是测试想要我做的。我只是写一个宏。我很困惑。我也不明白将宏封装在模块中有何帮助,但测试表明这是对模块和宏的测试。

string rust rust-macros rust-decl-macros

4
推荐指数
1
解决办法
1452
查看次数

将整个宏输入传递给另一个宏

我正在尝试创建一个简单的宏,vec!无论它接收到什么都会调用,然后在返回新向量之前执行一些简单的处理:

macro_rules! sorted_vec {
    ($x:expr) => {
        {
            let v = vec![$x];
            v.sort();
            v
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

问题是我的宏试图解析语法,所以它抱怨逗号等等.这是有道理的,但我不知道如何解决它.我认为不是expr正确的片段说明符.如何在vec!不进行处理的情况下将原始输入传递给它?

rust rust-macros rust-decl-macros

3
推荐指数
1
解决办法
385
查看次数