Есть ли способ заставить макрос заменить вещи в строках?

Этот макрос должен иметь возможность заменять записи в строке с помощью аргумента. Например, это сработает:

let string = "Hello, world!";
replace_macro!(string, "world", "Rust"); // Hello, Rust!

Я не уверен, как это сделать, так как все мои предыдущие попытки просто написать обычную функцию и вызвать ее внутри макросов не работают. Если возможно, я бы хотел использовать macro_rules вместо макроса proc.

Макрос macro_rules не может видеть внутреннюю часть строк; он только видит, что ему был передан литерал (даже не строковый литерал). Это определенно потребует макроса proc.

BallpointBen 10.04.2022 00:21

Я видел другой поток StackOverflow, который делает что-то подобное, поэтому мне было интересно, можно ли его адаптировать. stackoverflow.com/questions/55951472/…

salvage_dev 10.04.2022 00:23

@salvage_dev а) Идентификаторы могут быть проверены, а литералы - нет. б) Макрос не создает новый идентификатор, а только заменяет его заранее определенным. Для создания новых идентификаторов также требуется макрос proc.

Chayim Friedman 10.04.2022 00:29
Формы 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.
Четыре эффективных способа центрирования блочных элементов в CSS
Четыре эффективных способа центрирования блочных элементов в CSS
У каждого из нас бывали случаи, когда нам нужно отцентрировать блочный элемент, но мы не знаем, как это сделать. Даже если мы реализуем какой-то...
0
3
45
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Это невозможно. Макросы не могут проверять и/или изменять значение переменных.

Это возможно, если литерал встроен в вызов (replace_macro!("Hello, world!", "world", "Rust");), но требует proc-макроса: macro_rules! макросы не могут проверять и/или изменять литералы.

Это довольно просто с макросом proc:

use quote::ToTokens;
use syn::parse::Parser;
use syn::spanned::Spanned;

type Args = syn::punctuated::Punctuated<syn::LitStr, syn::Token![,]>;

#[proc_macro]
pub fn replace_macro(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
    let input_span = input.span();

    let args = match Args::parse_terminated.parse(input) {
        Ok(args) => Vec::from_iter(args),
        Err(err) => return err.into_compile_error().into(),
    };
    let (original, text, replacement) = match args.as_slice() {
        [original, text, replacement] => (original.value(), text.value(), replacement.value()),
        _ => {
            return syn::Error::new(
                input_span,
                r#"expected `"<original>", "<text>", "<replacement>"`"#,
            )
            .into_compile_error()
            .into()
        }
    };

    original
        .replace(&text, &replacement)
        .into_token_stream()
        .into()
}

Он анализирует список из трех строковых литералов, разделенных запятыми, а затем вызывает str::replace() для выполнения реальной работы.

Похоже, это сделает именно то, что мне нужно. Однако вы не можете написать proc-макрос и использовать его в том же крейте, и я не очень хочу, чтобы вы просто публиковали работу, которую я не писал. Вы знаете какие-нибудь ящики, которые делают это? Быстрый поиск ничего не дает.

salvage_dev 10.04.2022 00:54

@salvage_dev Не знаю, но я не против, если вы используете этот код :)

Chayim Friedman 10.04.2022 01:14

Ах, я оставлю ссылку на этот ответ, спасибо за помощь!

salvage_dev 10.04.2022 01:39

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