笛卡尔积匹配 [英] Cartesian product match

查看:170
本文介绍了笛卡尔积匹配的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两组 incomplete 类型(即结构名称,缺少通用参数和生存期),并且我需要为每对可能的组合对执行一些代码:

I have two sets of incomplete types (i.e. struct names, missing generic parameters and lifetimes), and I need to have some code executed for each possible pair of combinations:

// 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 ... }
    // ...
}

第一组(ABC)的结构和第二组(XYWZ)的结构具有通用参数彼此依赖(例如,对于("a", "x")情况,将使用的实际类型为A<X>X< A<X>::Color >).因此,我找不到使用泛型函数或类似函数的任何解决方案.

The structures of the first set (A, B, C) and the ones on the second set (X, Y, W, Z) have a generic parameter depending on each other (e.g. for the case ("a", "x"), the actual types that will be used are A<X> and X< A<X>::Color > ). For this reason I couldn't find any solution using generic functions or similar.

我认为,使用宏可以轻松解决该问题;像这样:

I believe that the problem could be easily solvable with a macro; something like:

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 )

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

but I failed at implementing product_match after working for several hours on it already. I couldn't find any easy way to nest repetitions; I believe that the only solution is using macros to turn the lists of match cases into nested tuples of values, and then recurse over them, but I found this very difficult to implement.

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

Another option could be generating the code of that big match using a build script, but this solution sounds quite dirty.

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

Is there any easy solution to this problem that I missed? Is there any easy way to implement product_match!? How can I implement my logic?

推荐答案

我认为您最好使用宏来实现笛卡尔积的想法.

I think your idea of implementing a Cartesian product using macros is best.

我不太确定您希望match表达式是什么,因此我

I'm not quite sure what you want the match expression to be, so I've implemented a repeated function call instead. The macro plumbing should be much the same, however. Hopefully you can take it from here.

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"]);
}

这篇关于笛卡尔积匹配的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆