我在箱子里重复使用宏时遇到了麻烦.
如果在以下位置定义了宏./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 中发现了几个有用的宏,即: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 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) 我正在尝试仅使用宏在 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。我怎样才能做到这一点?
我有一个具有大量关联类型的特征。我想要一个在 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) 我有一个标识符列表,我想为该列表中的每对标识符调用一个宏.例如,如果我有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) 所以我在这里,和 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)
哪个,你知道。我明白了。我明白问题是什么,但我不明白如何编写一个满足代码的宏。我可以更改正在测试的代码,但这不是测试想要我做的。我只是写一个宏。我很困惑。我也不明白将宏封装在模块中有何帮助,但测试表明这是对模块和宏的测试。
我正在尝试创建一个简单的宏,vec!无论它接收到什么都会调用,然后在返回新向量之前执行一些简单的处理:
macro_rules! sorted_vec {
($x:expr) => {
{
let v = vec![$x];
v.sort();
v
}
}
}
Run Code Online (Sandbox Code Playgroud)
问题是我的宏试图解析语法,所以它抱怨逗号等等.这是有道理的,但我不知道如何解决它.我认为不是expr正确的片段说明符.如何在vec!不进行处理的情况下将原始输入传递给它?