2017-03-13 3 views
2

私は(一般的なパラメータと寿命が不足している、すなわち構造体名)不完全タイプの2セットを持っている、と私は組み合わせの可能な各ペアに対して実行いくつかのコードを持っている必要があります:直積試合

// 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 >)。このため、汎用関数などを使って解決策を見つけることができませんでした。

私はこの問題がマクロで簡単に解決できると信じています。以下のようなもの:

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を実装するに失敗しました。繰り返しを入れ子にする簡単な方法は見つけられませんでした。唯一の解決策はマクロを使ってマッチ・ケースのリストをネストされた値のタプルに変換し、それらを繰り返し返すことですが、実装することは非常に困難です。

ビルドスクリプトを使用して大きなコードmatchを生成している可能性もありますが、このソリューションはかなり汚れているようです。

私が逃したこの問題の簡単な解決法はありますか? product_match!を実装する簡単な方法はありますか?論理を実装するにはどうすればよいですか?

+2

痛い、痛い見えます:(私はあなたの幸運を祈って –

+0

*私は問題はマクロ*で容易に解けるかもしれないと信じている - 。マクロは錆の機能を任意の本当の魔法を追加しない、彼らは単に定型を削除しかし、あなたは*私たちにボイラープレート*を見せてくれていません。代わりに、あなたは問題の肉を '...'で省略しました。私はあなたが私たちが拡大するマクロを作成したくないと確信していますリテラル '...'に変換するのですが、どうすればいいのか分かりません。[MCVE]の作成方法を見直してみましょう。まず、2つのタイプの2セットと – Shepmaster

+0

@Shepmaster by '... A ... X ...'私が思った 'f(A、X)'を意味していました。最小限で完全で検証可能な例。私の特定のケースでは、 '$ first'によって実装された特性に関連する型を送信し、次に' $ second'をインスタンス化して関数( 'f1')に渡すスレッドを開始するチャネルを作成する必要があります。メインスレッドの '$ first'に関数(' f2')を呼び出します。 'f2'は、' $ first'が '$ second'の形質実装の関連型でなければならない形質を実装する必要があり、' f1'は '$ second'を必要とします。 – peoro

答えて

1

マクロを使用してデカルト積を実装するというあなたの考えが最適です。

私はmatch式をどのようにしたいのかよくわからないので、代わりに関数呼び出しをimplementedにしました。マクロ配管は、しかし、同じでなければなりません。うまくいけば、ここからそれを取ることができます。

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