笛卡尔积匹配

peo*_*oro 5 macros nested match repeat rust

我有两组不完整的类型(即结构名称、缺少泛型参数和生命周期),我需要为每个可能的组合执行一些代码:

// these are my types
struct A<T> { ... }
struct B<'a, 'b, T> { ... }
struct C { ... }

struct X<T> { ... }
struct Y { ... }
struct W<'a> { ... }
struct Z<T, D> { ... }

// this is the code I need to generate
match (first_key, second_key) {
    ("a", "x") => { ... A ... X ... }
    ("a", "y") => { ... A ... Y ... }
    ("a", "w") => { ... A ... W ... }
    ("a", "z") => { ... A ... Z ... }
    ("b", "x") => { ... B ... X ... }
    ("b", "y") => { ... B ... Y ... }
    // ...
}
Run Code Online (Sandbox Code Playgroud)

第一组的结构 ( A, B, C) 和第二组的结构 ( X, Y, W, Z) 有一个相互依赖的通用参数(例如,对于这种情况("a", "x"),将使用的实际类型是A<X>and X< A<X>::Color >)。出于这个原因,我找不到任何使用通用函数或类似函数的解决方案。

我相信这个问题可以用宏轻松解决;就像是:

macro_rules! my_code {
    ( $first_type:tt), $second_type:tt ) => {
        // ... $first_type ... $second_type ...
    }
}

product_match!( (first_key, second_key) {
    { "a" => A, "b" => B, "c" => C },
    { "x" => X, "y" => Y, "w" => W, "z" => Z }
} => my_code )
Run Code Online (Sandbox Code Playgroud)

但我product_match已经工作了几个小时后未能实施。我找不到任何简单的方法来嵌套重复;我相信唯一的解决方案是使用宏将匹配案例列表转换为嵌套的值元组,然后对它们进行递归,但我发现这很难实现。

另一种选择可能是match使用构建脚本生成那么大的代码,但这个解决方案听起来很脏。

我错过的这个问题有什么简单的解决方案吗?有什么简单的实现方法product_match!吗?如何实现我的逻辑?

apt*_*002 4

我认为你使用宏实现笛卡尔积的想法是最好的。

我不太确定您想要的表达式match是什么,因此我实现了重复的函数调用。然而,宏观管道应该大致相同。希望你能从这里拿走它。

macro_rules! cp_inner {
    ($f: expr, $x: expr, [$($y: expr),*]) => {
        $($f($x, $y);)*
    }
}

macro_rules! cartesian_product {
    ($f: expr, [$($x: expr),*], $ys: tt) => {
        $(cp_inner!($f, $x, $ys);)*;
    }
}

fn print_pair(x: u32, y: &'static str) {
    println!("({}, {})", x, y);
}

pub fn main() {
    cartesian_product!(print_pair, [1, 2, 3], ["apple", "banana", "cherry"]);
}
Run Code Online (Sandbox Code Playgroud)