Почему передача закрытия функции, которая принимает указатель на функцию, не работает? - PullRequest
0 голосов
/ 08 октября 2018

Во втором издании Языка программирования Rust (выделено мое):

Функциональные указатели реализуют все три черты замыкания (Fn, FnMut и FnOnce), , поэтому вы всегда можете передать указатель функции в качестве аргумента для функции, которая ожидает замыкание .Лучше всего писать функции с использованием универсального типа и одной из черт замыкания, чтобы ваши функции могли принимать либо функции, либо замыкания.

Передача замыкания в функцию, которая принимает указатель функции в качестве аргумента, не компилируется:

fn main() {
    let a = String::from("abc");

    let x = || println!("{}", a);

    fn wrap(c: fn() -> ()) -> () {
        c()
    }

    wrap(x);
}
error[E0308]: mismatched types
  --> src/main.rs:10:10
   |
10 |     wrap(x);
   |          ^ expected fn pointer, found closure
   |
   = note: expected type `fn()`
              found type `[closure@src/main.rs:4:13: 4:33 a:_]`

Почему это не работает?

Ответы [ 2 ]

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

В некоторых случаях может передать закрытие в качестве указателя на функцию.Это работает:

fn main() {
    let x = || {
        let a = String::from("abc");
        println!("{}", a);
    };

    fn wrap(c: fn()) {
        c()
    }

    wrap(x);
}

Важным отличием является то, что закрытие не может захватывать что-либо из своего окружения.Это означает, что мы должны были предотвратить пересечение границ String границы замыкания.

Любое замыкание, которое не захватывает среду, может быть тривиально переписано как анонимная автономная функция, а затем преобразовано в указатель на функцию.

Как только вы добавляете среду, она больше не конвертируется, и все, начиная с , применяется существующий ответ .

Обратите внимание, что указание -> () не является идиоматическим, так как это значение по умолчанию, еслиничего не указано.

См. также:

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

Закрытие не является функцией.

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

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

Например:

let a = String::from("abc");

let x = || println!("x {}", a);

fn y() {
    println!("y")
}

fn wrap(c: impl Fn()) {
    c()
}

wrap(x); // pass a closure
wrap(y); // pass a function
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...