Сценарий: я хочу написать алгоритм оптимизатора, который принимает одномерную функцию в качестве аргумента. Я хочу, чтобы он работал как с замыканиями, так и со структурами, реализующими какой-то метод для вычисления значения оптимизированной функции. Должен ли я объявить свой оптимизатор принимающим аргумент FnMut
или какую-то другую черту, которая будет реализована любой структурой, которую я хочу передать оптимизатору?
Это то, о чем я хотел спросить, но вижу, что мне нужно более четко сформулировать свой вопрос. попробую перефразировать.
Надеюсь, это понятнее...
Вы не можете (пока) самостоятельно реализовать трейты Fn на стабильной версии Rust (проблема с отслеживанием). Вероятно, вам следует определить свой собственный трейт, который выполняет вычисления, которые вы затем можете реализовать для своих структур и для любого типа, реализующего Fn
(или FnMut
).
Ясно спасибо. Это проясняет ситуацию. Как реализовать трейт X для любого типа, который реализует трейт Y?
Я опубликую это как ответ.
Вы не можете (пока) реализовать трейты 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()
}
}
Это не имеет ничего общего с тем, сколько аргументов принимает функция, но с тем, каким образом функция может захватить свое окружение.
Fn
захватывают свою среду с помощью общей ссылки или не захватывают ее вообще (что делает каждыйfn
Fn
),FnMut
могут захватывать свою среду с помощью изменяемой ссылки, аFnOnce
могут перемещать значения из своей среды в замыкание. Кроме того, не берите замыкания по ссылке, берите их по значению. Ссылки на замыкание автоматически реализуют трейт замыкания.