如何编写转发到 vec 的可变参数 Rust 宏!宏观?

问题描述 投票:0回答:2

在 Rust 2021 中,我有一个名为

Intersection
的结构类型,我希望将它存储在一个可变长度列表中,所以可能是一个
Vec<Intersection>
。我可以轻松构建一个新容器:

#[derive(Debug)]
struct Intersection {
    t: f64,
    // ...
}

fn main () {
    
    let i0 = Intersection { t: 0.1 };
    let i1 = Intersection { t: 0.2 };
    
    let vs = vec!(i0, i1);
    
    for v in vs {
        println!("{:?}", v);
    }
}

铁锈游乐场

这使用了

vec!
宏。

我现在想做的是稍微抽象一下容器类型,将实现(

Vec<>
)与 API 的用户分离。现在,为了以最少干扰的方式做到这一点,我可以只使用类型别名来鼓励解耦:

type Intersections = Vec<Implementation>;

为了补充这一点,我还想定义一个辅助函数,从可变数量的

Intersection
对象中创建这样一个集合。所以像这样使用的东西:

fn main () {

    let i0 = Intersection { t: 0.1 };
    let i1 = Intersection { t: 0.2 };
    let i2 = Intersection { t: 0.3 };

    let vs = intersections(i0, i1, i2);  // <--- what can this be?

    for v in vs {
        println!("{:?}", v);
    }
}

换句话说,我希望将函数

intersections()
的可变数量的参数转发给
vec!
宏。但是我知道 Rust 不支持可变参数,所以我需要编写一个在内部调用
vec!
的宏,也许称之为
intersections!(&i0, &i1, ...)
.

我看过标准库对

vec!
的实现,但我不确定如何将项目列表转发给
vec!
宏。

我很感激,因为我使用的是类型别名,所以我可以直接调用

vec!(...)
,但是我想将接口与 Vector 分离,这样如果我更改容器实现,我可以更改
intersections()
功能或
intersections!
宏以适应新的实现。这是在 C、C++、Haskell 等语言中很常见的事情,因此类型可以在以后重新定义。

rust vector macros variadic
2个回答
1
投票

您可以简单地编写一个包装器宏,转发到

vec!
宏的现有规则:

macro_rules! intersection {
    () => { vec![] };
    ($elem:expr; $n:expr) => { vec![$elem; $n] };
    ($($x:expr),+ $(,)?) => { vec![$($x),+] };
}

然后你可以像这样调用你的

intersection!
宏,例如:

let vs = intersection![i0, i1];
// requires Intersection to implement Clone
let vs = intersection![Intersection { t: 0.1} ; 2]; 
let vs: Intersections = intersection![];

游乐场。


1
投票

您可以将

vec
重新导出为
intersections

pub use std::vec as intersections;

fn main() {
    println!("{:?}",intersections!(1,2));
}
© www.soinside.com 2019 - 2024. All rights reserved.