[英]Create sum of ones till N using macro in Rust
我想創建一個宏來將count!(5)
轉換為1+1+1+1+1
。 最后一個原因是在結構定義中使用count!(N) - 1
,其中N
是一個 const generics。
macro_rules! count {
(1) => {0};
(2) => { 1 + count!(1)};
($n: tt) => { 1 + count!($n - 1)};
}
struct WindowIterator<I, Item, const N: usize> {
iter: I,
values: Box<[Item; count!(N) - 1 ]>,
index: usize,
}
有了這個定義,我收到一個錯誤,就像no rules expected the token
N
.
如何更改我的代碼以使其正確?
宏擴展發生在類型推導之前,因此如果您不觸摸N
,它就可以工作。
macro_rules! count {
($n: tt) => { $n };
}
struct WindowIterator<I, Item, const N: usize> {
iter: I,
values: Box<[Item; count!(N) ]>,
index: usize,
}
實際上,您甚至不需要宏。
struct WindowIterator<I, Item, const N: usize> {
iter: I,
values: Box<[Item; N]>,
index: usize,
}
宏擴展適用於原始令牌。 如果您遵循宏擴展過程...
#![feature(log_syntax)]
macro_rules! count {
(1) => {{
log_syntax!(MatchOne count!(1));
0
}};
(2) => {{
log_syntax!(MatchTwo count!(2));
0
}};
($n:tt) => {{
log_syntax!(MatchNumber count!($n));
1 + count!($n - 1)
}};
($($n:tt)*) => {{
log_syntax!(MatchAny count!($($n)*));
}};
}
游樂場。
輸出:
MatchNumber count! (5)
MatchAny count! (5 - 1)
第二次調用沒有得到4
,而是5 - 1
,原始標記。
你想要的可以用過程宏來完成,例如:
extern crate proc_macro;
use itertools::Itertools; // When std's intersperse() will be stable, can get rid of this.
use proc_macro::{Delimiter, Group, Literal, Punct, Spacing, TokenStream, TokenTree};
#[proc_macro]
pub fn count(number: TokenStream) -> TokenStream {
let number = number.to_string().parse().expect("expected a number"); // A simple way to parse int literal without `syn`
let result = if number == 0 {
TokenTree::Literal(Literal::u64_unsuffixed(0))
} else {
TokenTree::Group(Group::new(
Delimiter::None,
std::iter::repeat(TokenTree::Literal(Literal::u64_unsuffixed(1)))
.take(number)
.intersperse(TokenTree::Punct(Punct::new('+', Spacing::Alone)))
.collect(),
))
};
result.into()
}
但是,這可能不是您想要的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.