Переменная все еще повторяется на этой глубине ошибки в макросе - PullRequest
0 голосов
/ 13 июня 2019

Я написал простой макрос:

macro_rules! my_macro {
    {
        f($x:expr, $y:expr, $z:expr);
        $($c:expr => {
            $($m:expr => {
               $($s:expr => $b:expr),+
            }),+
        }),+
    } => {{
            match ($x, $y, $z) {
                $(
                ($c, $m, $s => $b),
                )+
            }
          }};
}

fn main(){

    let c = 0;
    let m = 0;
    let s = 0; 
    my_macro! {
        f (c, m, s);
        cc => {
            mm => {
                ss => b
            }
        }
    }

}

и он получает ошибки компилятора:

error: variable 'm' is still repeating at this depth
  --> project/src/mod.rs
   |
39 |                 ($c, $m, $s => $b),
   |                              ^^^^^^^

Я не совсем понимаю, почему это произошло.Почему и как это починить?

1 Ответ

0 голосов
/ 13 июня 2019

В вашем правиле для вашего макроса

f($x:expr, $y:expr, $z:expr);
$($c:expr => {
    $($m:expr => {
       $($s:expr => $b:expr),+
    }),+
}),+

$x, $y и $z связывают один expr.Тем не менее, весь список $c s связаны.Более того, с каждым $c связан целый список $m, поскольку $m все еще находится внутри блока $(...).+, связанного с $c.Для каждого из этих $m s связан весь список $s s.

Теперь в вашем выводе

{{
    match ($x, $y, $z) {
        $(
        ($c, $m, $s => $b),
        )+
    }
}};

вы распаковываете только один слой списков с $(...)+.После одного слоя $m остается списком выражений («повторяющихся»), поэтому его нельзя использовать напрямую.Помните, что $m - это действительно список списков (поскольку есть список $m для каждого $c), а $s - это действительно список списков.

Вы либо собираетесьнеобходимо реструктурировать правило так, чтобы для каждого $c (все в пределах одного $(...),+) был только один $m и один $s, или вам потребуется реструктурировать вывод так, чтобы $m и $s распаковывается соответствующее количество раз.

После попытки первого подхода (один $(...),+ в правиле ввода), я бы предложил создать шаблоны $c, $m и $sа не выражения (как в $c: pat вместо $c: expr).Это позволяет использовать их в левой части ветви матча.

macro_rules! my_macro {
    {
        f($x:expr, $y:expr, $z:expr);
        $($c:pat => {
            $m:pat => {
               $s:pat => $b:expr
            }
        }),+
    } => {
            match ($x, $y, $z) {
                $(
                    ($c, $m, $s) => $b,
                )+
            }
          };
}

Реальное решение во многом зависит от того, что именно вы пытаетесь достичь.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...