我有第三方库,代码如下:
pub struct Foo<T> { t: T }
impl<'a, T> Foo<T> where T: 'a + FnMut() -> &'a [u8] {
pub fn from_callback(closure: T) -> Self {
Foo { t: closure }
}
}
关闭时效果很好:
let buffer = vec![0; 100];
Foo::from_callback(move || &buffer)
但是我想从我的函数返回Foo
。因为我不能使用闭包,所以我决定使用自己的结构来实现FnMut
。
我已经定义了struct:
pub struct Func {
buffer: Vec<u8>,
}
然后为它实施FnMut
:
#![feature(unboxed_closures)]
impl FnMut<()> for Func {
extern "rust-call" fn call_mut(&mut self, _: ()) -> Self::Output {
&self.buffer
}
}
然后需要实施FnOnce
:
impl FnOnce<()> for Func {
type Output = &[u8];
^~~~ error: missing lifetime specifier [E0106]
extern "rust-call" fn call_once(self, _: ()) -> Self::Output {
unimplemented!();
}
}
但我不知道在Output
中作为生命周期使用什么作为参考。
答案 0 :(得分:1)
@MatthieuM。是正确的。如果没有更高级别的类型,这是不可能做到的,即使它们可用,我也不能完全确定Fn*
特征可以改变以支持它。
问题是,你希望你的函数在这个函数中返回一个向量切片。但是,这需要call_mut()
具有以下签名:
fn call_mut<'a>(&'a mut self, _: ()) -> Self::Output<'a>
lifetime参数是必需的,因为它是指定函数调用的结果与函数本身一样长的唯一方法。这反过来要求Output
关联类型具有生命周期参数:
trait FnOnce<A> {
type Output<'a>;
...
}
这正是香港电讯所允许的。但是,我不确定是否可以将HKT用于功能。请记住,每个FnMut
也是FnOnce
:如果您有一个可以多次调用的函数,那么它也可以被调用一次。当然,FnMut
和FnOnce
的结果应该是等效的。但是,没有办法从FnOnce
返回借来的数据,因为它按值获取函数。在你的情况下,向量将被移动到函数,因为函数返回一个切片,而不是一个向量,它将无处可去,因此它将被销毁。因此,此类更改需要允许某些函数为FnMut
/ Fn
,而不是FnOnce
;我不确定这是否可取,甚至可能。
答案 1 :(得分:0)
这个问题可以通过使用trait
本身来表达可能的功能来解决。
trait CallbackTrait {
fn call(&mut self) -> &[u8];
}
fn make_callback() -> impl CallbackTrait {
struct MyData(Vec<u8>);
impl CallbackTrait for MyData {
fn call(&mut self) -> &[u8] { &self.0 }
}
MyData(vec![0; 100])
}
而且,当您希望将其更通用地传递时,可以将其装箱。
fn make_another_callback() -> Box<dyn MyCallback> {
Box::new<make_callback()>
}
由于没有API ,因此期望任何Fn(Once|Mut|)
会在函数自身的生存期内返回某些内容,问题本身就是框架问题。您可能希望使用此功能的情况可以改用trait
,但只需稍作更改即可,其好处是具有更大的灵活性,例如需要其他trait
或具有多个功能。至于为什么语言本身不支持此概念,@ Vladimir Matveev对此做了解释。