2017-03-08 6 views
3

sym-linkingファイル用のマクロを書きました。最初はちょうど最初のパターンがありましたが、 "&フォーマット"と書かなくてもいいと思っていました!すべての時間。これらのパターンを持つのでマクロルールは最初のパターンにのみ一致します

macro_rules! syml { 
    ($a:expr, $b:expr) => { 
     Command::new("ln").args(&["-s", $a, $b]) 
    }; 
    (($a:expr, $($x:expr),+), ($b:expr, $($y:expr),+)) => { 
     Command::new("ln").args(&["-s", &format!($a, $($x),+), &format!($b, $($y),+)]) 
    } 
} 

私はこれらのケースを一致させたい:

syml!("from", "to"); 
syml!(("{}", from), "to"); 
syml!("from", ("{}", to)); 
syml!(("{}", from), ("{}", to)); 
syml!(("{}{}", from, here), ("{}{}", to, there)); 

しかし、これまでのところ、すべての時間が唯一の第一のパターンが一致したので、私のようなmismatched typesエラーを取得していますexpected reference, found tuple

最後の2つの例の場合でも、最初のパターンと一致しないようにしようとしているのは分かりません。

+0

ないマクロの専門家なので、私はよ(1)タプルは式なので、 "(x、y)"は '$ a:expr'にマッチすることができます(2)パターンは順番に試されると信じています。より具体的なパターンが最初にありますか? –

+1

問題には関係しませんが、標準ライブラリには['symlink'](https://doc.rust-lang.org/stable/std/os/unix/fs/fn.symlink.html)機能があります。 –

答えて

4

@MatthieuMがコメントで指摘しているように、タプルは式であり、マクロルールは順番に試されます。

だからあなたの場合:

macro_rules! syml { 
    ($a:expr, $b:expr) => { 
     Command::new("ln").args(&["-s", $a, $b]) 
    }; 
    (($a:expr, $($x:expr),+), ($b:expr, $($y:expr),+)) => { 
     Command::new("ln").args(&["-s", &format!($a, $($x),+), &format!($b, $($y),+)]) 
    } 
} 

最初のルールは常に秒がする任意の時間と一致します。解決策の周りにそれらを交換することです:これは、することができ

syml!(("{}", from), "to"); 
syml!("from", ("{}", to)); 

macro_rules! syml { 
    (($a:expr, $($x:expr),+), ($b:expr, $($y:expr),+)) => { 
     Command::new("ln").args(&["-s", &format!($a, $($x),+), &format!($b, $($y),+)]) 
    }; 
    ($a:expr, $b:expr) => { 
     Command::new("ln").args(&["-s", $a, $b]) 
    } 
} 

Playground

を上記のことは、あなたがタプルと文字列を混ぜ、あなたのテストケースのうちの2つをカバーしていません。新しい症例を(順番に)追加するだけで簡単に修正できます。 (私はタプル/文字列のマッチングを考慮することは可能かどうかわからないが、任意のソリューションを見ることに興味がある。)

macro_rules! syml { 
    (($a:expr, $($x:expr),+), ($b:expr, $($y:expr),+)) => { 
     Command::new("ln").args(&["-s", &format!($a, $($x),+), &format!($b, $($y),+)]) 
    }; 
    ($a:expr, ($b:expr, $($y:expr),+)) => { 
     Command::new("ln").args(&["-s", $a, &format!($b, $($y),+)]) 
    }; 
    (($a:expr, $($x:expr),+), $b:expr) => { 
     Command::new("ln").args(&["-s", &format!($a, $($x),+), $b]) 
    }; 
    ($a:expr, $b:expr) => { 
     Command::new("ln").args(&["-s", $a, $b]) 
    } 
} 

Playground)を

+0

もちろんタプルは式です!私はそれを完全に逃した、ありがとう。 @MatthieuMにも感謝します。 – DRogueRonin

+0

私の2つのカバーされていないテストケースの修正と修正を提供してくれてありがとう!ルールの少ないソリューションは、実際には面白いでしょう。たぶん私は錆びたマクロにもっと掘り下げた後で見つけることができます。 – DRogueRonin

+1

私の勘違いが正しかったことを見てよかったです。私は本当に多くのマクロで遊んでいない:) –

関連する問題