Проверьте, определен ли параметр макроса в необязательном захвате (Декларативный синтаксис макросов)

#rust #rust-macros

Вопрос:

Я создаю довольно сложный макрос и не могу использовать синтаксис перегрузки для создания своих макросов. Я пытаюсь условно проверить, была ли опора определена в дополнительной группе захвата или нет:

 macro_rules! foo {
    (name: $name: ident$(, media: $media: tt)?) => {
        pub struct $name;
        impl $name {
            // how do i use media here and also provide default
            // const MEDIA: amp;str = IF_DEFINED $media { $media } ELSE { "DEFAULT" };
        }
    };
}

foo! {
    name: Hey,
    media: "hey"
}

foo! {
    name: Hey2
}
 

Ссылка на игровую площадку

Комментарии:

1. «не могу использовать синтаксис перегрузки» — почему бы и нет? Мне это кажется естественным выбором

2. @kmdreko, потому что мой синтаксис параметров использует необязательную вещь в группе повторов, поэтому я не могу ее перегружать

3. Почему вы делаете $media в макросе повтор? Ссылаясь на const MEDIA: amp;str то, что я считаю, что нужен только один.

4. @rustyhu, потому что мой макрос сложнее, чем в примере, и использует много другого кода в моем ящике, поэтому я перечислил ограничения, а затем дал минимальное воспроизведение

5. @sno2 Не могли бы вы опубликовать более реалистичный пример, который показывает, почему вы предполагаете, что не можете использовать синтаксис перегрузки? Может быть, есть подвох, позволяющий вам действительно использовать его.

Ответ №1:

В рамках упомянутых вами ограничений вы можете выполнить условную проверку следующим обходным путем:

 macro_rules! foo {
    (name: $name: ident$(, media: $media: tt)?) => {
        
            pub struct $name;
     
            impl $name {
                const MEDIA: amp;'static str = [$($media ,)? "DEFAULT"][0];
            }
    };
}

foo! {
    name: Hey,
    media: "hey"
}

foo! {
    name: Hey2
}

fn main() {
    println!("{}", Hey::MEDIA);
    println!("{}", Hey2::MEDIA);
}
 

Ссылка на игровую площадку