Ключ динамической структуры в макросе

Есть ли способ сделать эти два макроса одним макросом?

macro_rules! bg_color_test {
    ($($color:path, $flag:literal),*$(,)?) => {
        let mut options = Options::default();
        options.text = String::from("my text");

        $(
            options.background = $color;
            assert_eq!(
                parse_args(vec![
                    "path/to/bin".to_string(),
                    "my text".to_string(),
                    "-b".to_string(),
                    $flag.to_string()
                ]),
                options
            );
        )*
    }
}
// used like below:
bg_color_test!(
    Colors::Red,"red",
    Colors::Green,"green",
    Colors::Blue,"blue",
);

И этот:

macro_rules! color_test {
    ($($color:expr, $flag:literal),*$(,)?) => {
        let mut options = Options::default();
        options.text = String::from("my text");

        $(
            options.colors = $color;
            assert_eq!(
                parse_args(vec![
                    "path/to/bin".to_string(),
                    "my text".to_string(),
                    "-c".to_string(),
                    $flag.to_string()
                ]),
                options
            );
        )*
    }
}
// used like below:
color_test!(
    vec![Colors::Red],"red",
    vec![Colors::Green],"green",
    vec![Colors::Blue],"blue",
);

Я борюсь конкретно с этим битом: options.background = $color; против options.colors = $color;… понятия не имею, как я могу встроить это в макрос…

В макросе я попытался сделать ключ динамическим:

options.$kind = $color; // syntax error
options[$kind] = $color; // syntax error
options.$($kind)* = $color; // empty expression error

Я использую макрос следующим образом:

bg_color_test!(
    "background", Colors::Red,"red",
    "background", Colors::Green,"green",
    "background", Colors::Blue,"blue",
);

Что даст мне:

error: no rules expected the token `"background"`
   --> tests/parse_args_test.rs:491:3
    |
464 | macro_rules! bg_color_test {
    | ------------------------ when calling this macro
...
491 |         "background", BgColors::Red, "red",
    |         ^^^^^^^^^^^^ no rules expected this token in macro call

error: could not compile `lib` due to previous error

Как насчет того, чтобы взять один цвет в качестве аргумента в $color, а затем options.background = $color; и options.colors = vec![$color];?

BlackBeans 23.04.2022 11:18

Проблема не в том, что я здесь использую два разных типа. Проблема в том, что я не могу сделать ключ динамическим в options.background = $color;. Должно быть что-то вроде options.$kind = $color;, но это не работает.

Dominik 23.04.2022 11:23
3 метода стилизации элементов HTML
3 метода стилизации элементов HTML
Когда дело доходит до применения какого-либо стиля к нашему HTML, существует три подхода: встроенный, внутренний и внешний. Предпочтительным обычно...
Формы c голосовым вводом в React с помощью Speechly
Формы c голосовым вводом в React с помощью Speechly
Пытались ли вы когда-нибудь заполнить веб-форму в области электронной коммерции, которая требует много кликов и выбора? Вас попросят заполнить дату,...
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Будучи разработчиком веб-приложений, легко впасть в заблуждение, считая, что приложение без JavaScript не имеет права на жизнь. Нам становится удобно...
Flatpickr: простой модуль календаря для вашего приложения на React
Flatpickr: простой модуль календаря для вашего приложения на React
Если вы ищете пакет для быстрой интеграции календаря с выбором даты в ваше приложения, то библиотека Flatpickr отлично справится с этой задачей....
В чем разница между Promise и Observable?
В чем разница между Promise и Observable?
Разберитесь в этом вопросе, и вы значительно повысите уровень своей компетенции.
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Клиент для URL-адресов, cURL, позволяет взаимодействовать с множеством различных серверов по множеству различных протоколов с синтаксисом URL.
0
2
56
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я нашел ответ на Discord с помощью пользователя @pie_flavor.

Моя ошибка заключалась в том, что я рассматривал ключевой аргумент как str в вызове макроса, он должен быть ident в качестве аргумента для начала.

Итак, окончательный код объединения этих двух макросов:

macro_rules! color_test {
    ($($kind:ident, $color:expr, $flag:literal, $flag_value:literal),*$(,)?) => {
        let mut options = Options::default();
        options.text = String::from("my text");

        $(
            options.$kind = $color;
            assert_eq!(
                parse_args(vec![
                    "path/to/bin".to_string(),
                    "my text".to_string(),
                    $flag.to_string(),
                    $flag_value.to_string()
                ]),
                options
            );
        )*
    }
}

Используется следующим образом:

color_test!(
    colors, vec![Colors::Red], "-c", "red",
    background, Colors::Green, "-b", "green",
);

Другие вопросы по теме