Как захватить по ссылке в макросе ржавчины - PullRequest
0 голосов
/ 01 октября 2018

У меня есть макрос для генерации match оружия:

macro_rules! sort_by {
    ( $query:ident, $sort_by:expr, { $( $name:pat => $column:path,)+ } ) => {
        match $sort_by.column {
            $(
                $name => if $sort_by.descending {
                    $query = $query.order_by($column.desc());
                } else {
                    $query = $query.order_by($column.asc());
                },
            )+
        }
    }
}

, и я хочу назвать его так:

sort_by!(query, sort_by.unwrap_or(Sort::desc("id")), {
    "id" => table::id,
    "customerName" => table::customer_name,
});

Но я получаю ошибку:

sort_by!(query, &sort_by.unwrap_or(Sort::desc("id")), {
                ^^^^^^^ value moved here in previous iteration of loop

Итак, я должен назвать это так:

let sort = sort_by.unwrap_or(Sort::desc("id"));
sort_by!(query, &sort, {
    "id" => table::id,
    "customerName" => table::customer_name,
});

Что я должен изменить, чтобы иметь возможность использовать выражение непосредственно в вызове макроса?

1 Ответ

0 голосов
/ 01 октября 2018

Использование макроса эквивалентно замене кода, который он расширяет, на свой сайт вызова.Это означает, что если расширение макроса содержит $sort_by несколько раз, код оценит переданное вами выражение как $sort_by несколько раз.Если выражение использует некоторую переменную, это будет недопустимым.

Это отличается от того, как работают вызовы функций.Если вы передадите выражение в функцию, оно будет оценено перед вызовом функции, и в функцию будет передан только результат.

Если это источник вашей проблемы, вы можете исправить его, назначив $sort_by на локальную переменную внутри вашего макроса, и только затем обращайтесь к локальной переменной:

macro_rules! sort_by {
    ($query:ident, $sort_by:expr, { $($name:pat => $column:path,)+ }) => {
        let sort_by = $sort_by;
        match sort_by.column {
            $(
                $name => if sort_by.descending {
                    $query = $query.order_by($column.desc());
                } else {
                    $query = $query.order_by($column.asc());
                },
            )+
        }
    }
}

(Обратите внимание, что я не смог проверить это, так как ваш пример неполон.)

...