gpt4 book ai didi

macros - 有没有办法用宏来计数?

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

我想创建一个打印“Hello”指定次数的宏。它的用法如下:

many_greetings!(3);  // expands to three `println!("Hello");` statements

创建该宏的简单方法是:

macro_rules! many_greetings {
($times:expr) => {{
println!("Hello");
many_greetings!($times - 1);
}};
(0) => ();
}

但是,这不起作用,因为编译器不计算表达式; $times - 1 不是计算出来的,而是作为新表达式输入到宏中。

最佳答案

虽然普通的宏系统不能让你多次重复宏展开,但是在宏中使用for循环是没有问题的:

macro_rules! many_greetings {
($times:expr) => {{
for _ in 0..$times {
println!("Hello");
}
}};
}

如果您真的需要重复宏,则必须查看程序宏/compiler plugins (从 1.4 开始不稳定,而且有点难写)。

编辑:可能有更好的方法来实现它,但我今天已经在这上面花费了足够长的时间,所以这里开始吧。 repeat!,一个实际上将一段代码重复多次的宏:

主要.rs

#![feature(plugin)]
#![plugin(repeat)]

fn main() {
let mut n = 0;
repeat!{ 4 {
println!("hello {}", n);
n += 1;
}};
}

库.rs

#![feature(plugin_registrar, rustc_private)]

extern crate syntax;
extern crate rustc;

use syntax::codemap::Span;
use syntax::ast::TokenTree;
use syntax::ext::base::{ExtCtxt, MacResult, MacEager, DummyResult};
use rustc::plugin::Registry;
use syntax::util::small_vector::SmallVector;
use syntax::ast::Lit_;
use std::error::Error;

fn expand_repeat(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree]) -> Box<MacResult + 'static> {
let mut parser = cx.new_parser_from_tts(tts);
let times = match parser.parse_lit() {
Ok(lit) => match lit.node {
Lit_::LitInt(n, _) => n,
_ => {
cx.span_err(lit.span, "Expected literal integer");
return DummyResult::any(sp);
}
},
Err(e) => {
cx.span_err(sp, e.description());
return DummyResult::any(sp);
}
};
let res = parser.parse_block();

match res {
Ok(block) => {
let mut stmts = SmallVector::many(block.stmts.clone());
for _ in 1..times {
let rep_stmts = SmallVector::many(block.stmts.clone());
stmts.push_all(rep_stmts);
}
MacEager::stmts(stmts)
}
Err(e) => {
cx.span_err(sp, e.description());
DummyResult::any(sp)
}
}
}

#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
reg.register_macro("repeat", expand_repeat);
}

添加到 Cargo.toml

[lib]
name = "repeat"
plugin = true

请注意,如果我们真的不想进行循环,而是想在编译时进行扩展,我们就必须做一些事情,比如要求文字数字。毕竟,我们无法在编译时评估引用程序其他部分的变量和函数调用。

关于macros - 有没有办法用宏来计数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33751796/

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