gpt4 book ai didi

rust - 高阶宏

转载 作者:行者123 更新时间:2023-11-29 07:43:08 25 4
gpt4 key购买 nike

是否可以在 Rust 中编写一个创建其他宏的宏。例如,假设我定义了以下两个宏:

macro_rules! myprint(
($a:expr) => (print!("{}", $a))
)

macro_rules! myprintln(
($a:expr) => (println!("{}", $a))
)

由于这两个宏重复了很多代码,所以我可能想写一个宏来生成宏。

我试过生成这样一个 meta macro .

#![feature(macro_rules)]

macro_rules! metamacro(
($i:ident) => (
macro_rules! $i (
($a:expr) => ({println!("hello {}", $a)})
)
);
)

metamacro!(foo)

fn main() {
foo!(1i);
}

但出现以下错误:

<anon>:6:13: 6:14 error: unknown macro variable `a`
<anon>:6 ($a:expr) => ({println!("hello {}", $a)})
^
playpen: application terminated with error code 101
Program ended.

编辑:在进一步研究宏之后,我发现如果返回的宏没有接收到任何参数,高阶宏会按预期工作。比如下面的code

#![feature(macro_rules)]

macro_rules! metamacro(
($i:ident) => (
macro_rules! $i (
() => ({println!("hello")})
)
);
)

metamacro!(foo)

fn main() {
foo!();
}

打印你好

最佳答案

这最近在 #34925 中成为可能.下面的答案是指旧版本的 Rust。


这是 #6795#6994 ,目前还不能直接实现。例如。人们会尝试的第一件事是

#![feature(macro_rules)]

macro_rules! define {
($name: ident, $other: ident) => {
macro_rules! $name {
($e: expr) => {
$other!("{}", $e)
}
}
}
}

define!{myprintln, println}
define!{myprint, print}

fn main() {}

但这失败了

so8.rs:6:13: 6:14 error: unknown macro variable `e`
so8.rs:6 ($e: expr) => {
^

(已归档 #15640 关于插入符号指向 ( 而不是 $e。)

原因是宏扩展是“愚蠢的”:它天真地解释和替换所有标记,甚至在嵌套宏调用内部也是如此(macro_rules! 是一个宏调用)。因此,它无法判断内部 macro_rules! 中的 $e 实际上应该保留为 $e:它只是在尝试在扩展 define 时替换它们。

人们可能会尝试的第二件事是将额外的参数传递给 define 以放置在内部定义中,这样 $e 就不会直接出现在嵌套的调用:

#![feature(macro_rules)]

macro_rules! define {
($name: ident, $other: ident, $($interior: tt)*) => {
macro_rules! $name {
($($interior)*: expr) => {
$other!("{}", $($interior)*)
}
}
}
}

define!{myprintln, println, $e}
define!{myprint, print, $e}

fn main() {}

也就是说,我添加了 $interior: tt 以允许捕获 $ett 代表 token tree,它是一个非分隔符的原始 token(例如 $some_ident)或者由匹配的分隔符包围的一系列 token (例如 (foo + bar fn "baz"))。不幸的是,扩展似乎非常渴望 $e 扩展也被扩展:

so8.rs:8:13: 8:14 error: unknown macro variable `e`
so8.rs:8 ($($interior)*: expr) => {
^

当嵌套宏本身没有参数时,它工作正常,因为没有嵌套的 $... 非终端,所以扩展阶段永远不会遇到上述定义问题。


最后,您可以获得一些类似的代码共享,因为您可以按名称扩展到宏调用:

#![feature(macro_rules)]

macro_rules! my {
($name: ident, $e: expr) => {
$name!("{}", $e)
}
}

fn main() {
my!(print, 1i);
my!(println, 2i);
}

打印12

关于rust - 高阶宏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24718256/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com