Как создать макрос, который принимает функцию с несколькими параметрами и предоставляет первый аргумент для этой функции? - PullRequest
0 голосов
/ 16 января 2019

Я хочу иметь возможность создать функцию более высокого порядка (называемую g), которая принимает функцию (называемую f).g должен передать первый параметр в f и вернуть новую функцию.

Случай использования: я хочу инициировать соединение с базой данных в g и передать ему функции, которые принимают соединение с базой данных,

fn f1(a: i32, b: String) -> String {
    b
}

fn f2(a: i32, c: i64, d: i16) -> i32 {
    1000
}

fn g<T>(f: fn(a: i32, arbitrary_arguments_type) -> T) -> fn(arbitrary_arguments_type) -> T {
    move |arbitrary_arguments| f(1, arbitrary_arguments)
}

fn main() {
    g(f1)("hello".to_string());
    g(f2)(10, 11);
}

Как создать макрос, который принимает в качестве аргумента функцию с более чем одним параметром, где первый параметр имеет определенный тип, и предоставляет этот аргумент для этой первой функции?

1 Ответ

0 голосов
/ 16 января 2019

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

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

macro_rules! curry1 {
    ($func: ident, $($arg: expr),*) => {
        |a| $func($($arg),*, a)
    }
}

macro_rules! curry2 {
    ($func: ident, $($arg: expr),*) => {
        |a, b| $func($($arg),*, a, b)
    }
}

macro_rules! curry3 {
    ($func: ident, $($arg: expr),*) => {
        |a, b, c| $func($($arg),*, a, b, c)
    }
}

Что будет использоваться так:

fn f(a: i32, b: i32, c: i32) -> i32 {
    a + b + c
}

fn main() {
    // requires 2 extra args
    let f_2 = curry2!(f, 2);
    // requires 1 extra arg
    let f_2_1 = curry1!(f, 2, 1);

    println!("{}", f(2, 1, 3)); // 6
    println!("{}", f_2(1, 3));  // 6
    println!("{}", f_2_1(3));   // 6
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...