Можно ли назначить замыкание для переменной типа impl Fn ()? - PullRequest
0 голосов
/ 19 января 2019

Мне удалось заставить этот код работать:

fn twice<T: Clone>(fst: impl Fn(T), snd: impl Fn(T)) -> impl Fn(T) {
    move |t| {
        fst(t.clone());
        snd(t)
    }
}

Однако я хочу вот что (без бокса):

fn sub<T: Clone>(mut fst: impl Fn(T), snd: impl Fn(T)) {
    fst = move |t: T| {
        fst(t.clone());
        snd(t)
    };
}

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

Ответы [ 2 ]

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

Отвечая на вопрос, который вы задали , нет, вы еще не можете назначить закрытие переменной с типом impl Fn, потому что вы еще не можете объявить такую ​​переменную:

fn foo() {
    let x: impl Fn() = move || println!("Hello");
}
error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
 --> src/lib.rs:2:12
  |
2 |     let x: impl Fn() = move || println!("Hello");
  |            ^^^^^^^^^

"Но подожди!"Вы говорите: «У меня есть такой тип в аргументе моей функции!».Правда в том, что нет, у вас нет.

Этот синтаксис:

fn foo(x: impl Fn()) {}

Это просто сокращение для этого:

fn foo<F>(x: F)
where
    F: Fn(),
{}

Вы просто сконструировали универсальный тип и применили к нему привязанную черту.

См. Также:

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

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

Коробочная версия может выглядеть так:

use std::mem;

fn sub<'a, T: Clone + 'a>(fst: &mut Box<dyn Fn(T) + 'a>, snd: impl Fn(T) + 'a) {
    // Replace the original fst with a dummy closure while the new closure is being
    // constructed, to avoid the reference being temporarily invalid
    let fst_orig = mem::replace(fst, Box::new(|_| {}));
    *fst = Box::new(move |t: T| {
        fst_orig(t.clone());
        snd(t)
    });
}


fn main() {
    let mut f1: Box<dyn Fn(i32)> = Box::new(|x| println!("f1: {}", x));
    let f2 = |x| println!("f2: {}", x);

    sub(&mut f1, f2);

    f1(42);
}

Но я действительно не уверен, почему вы захотите это сделатьэто!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...