Должен ли я использовать Fn, FnMut и FnOnce только для закрытия?

Сценарий: я хочу написать алгоритм оптимизатора, который принимает одномерную функцию в качестве аргумента. Я хочу, чтобы он работал как с замыканиями, так и со структурами, реализующими какой-то метод для вычисления значения оптимизированной функции. Должен ли я объявить свой оптимизатор принимающим аргумент FnMut или какую-то другую черту, которая будет реализована любой структурой, которую я хочу передать оптимизатору?

Это не имеет ничего общего с тем, сколько аргументов принимает функция, но с тем, каким образом функция может захватить свое окружение. Fn захватывают свою среду с помощью общей ссылки или не захватывают ее вообще (что делает каждый fnFn), FnMut могут захватывать свою среду с помощью изменяемой ссылки, а FnOnce могут перемещать значения из своей среды в замыкание. Кроме того, не берите замыкания по ссылке, берите их по значению. Ссылки на замыкание автоматически реализуют трейт замыкания.

isaactfa 21.11.2022 13:20

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

quant_dev 21.11.2022 13:23

Надеюсь, это понятнее...

quant_dev 21.11.2022 13:26

Вы не можете (пока) самостоятельно реализовать трейты Fn на стабильной версии Rust (проблема с отслеживанием). Вероятно, вам следует определить свой собственный трейт, который выполняет вычисления, которые вы затем можете реализовать для своих структур и для любого типа, реализующего Fn (или FnMut).

isaactfa 21.11.2022 13:36

Ясно спасибо. Это проясняет ситуацию. Как реализовать трейт X для любого типа, который реализует трейт Y?

quant_dev 21.11.2022 13:39

Я опубликую это как ответ.

isaactfa 21.11.2022 13:39
Шаблоны Angular PrimeNg
Шаблоны Angular PrimeNg
Как привнести проверку типов в наши шаблоны Angular, использующие компоненты библиотеки PrimeNg, и настроить их отображение с помощью встроенной...
Создайте ползком, похожим на звездные войны, с помощью CSS и Javascript
Создайте ползком, похожим на звездные войны, с помощью CSS и Javascript
Если вы веб-разработчик (или хотите им стать), то вы наверняка гик и вам нравятся "Звездные войны". А как бы вы хотели, чтобы фоном для вашего...
Документирование API с помощью Swagger на Springboot
Документирование API с помощью Swagger на Springboot
В предыдущей статье мы уже узнали, как создать Rest API с помощью Springboot и MySql .
Начала с розового дизайна
Начала с розового дизайна
Pink Design - это система дизайна Appwrite с открытым исходным кодом для создания последовательных и многократно используемых пользовательских...
Шлюз в PHP
Шлюз в PHP
API-шлюз (AG) - это сервер, который действует как единая точка входа для набора микросервисов.
14 Задание: Типы данных и структуры данных Python для DevOps
14 Задание: Типы данных и структуры данных Python для DevOps
проверить тип данных используемой переменной, мы можем просто написать: your_variable=100
0
6
52
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Вы не можете (пока) реализовать трейты Fn самостоятельно на стабильной версии Rust. Вероятно, вам следует определить свой собственный трейт, который выполняет вычисления, которые вы затем можете реализовать для своих структур и для любого типа, реализующего Fn (или FnMut):

// I'm opting for `&mut self` here as it's more general
// but this might not be necessary for your use case
trait Calculate<T, U> {
    fn calculate(&mut self, t: T) -> U;
}

// Because `Fn: FnMut` this will also implement `Calculate` for `Fn`.
impl<F, T, U> Calculate<T, U> for F
where F: FnMut(T) -> U {
    fn calculate(&mut self, t: T) -> U {
        (self)(t)
    }
}

struct State {
    flag: bool,
}
impl<T, U> Calculate<T, U> for State
where T: Into<U> {
    fn calculate(&mut self, t: T) -> U {
        self.flag = true;
        // or whatever calculation you actually need to do here
        t.into()
    }
}

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