问题描述
我以前有类似的东西:
struct Foo {
pub foo: |uint| -> uint,
}
现在闭包语法已过时。我可以做如下:
Now the closure syntax is obsolete. I can do something like:
struct Foo<F: FnMut(uint) -> uint> {
pub foo: F,
}
Foo
我创建的对象?
let foo: Foo<???> = Foo { foo: |x| x + 1 };
我也可以使用引用:
struct Foo<'a> {
pub foo: &'a mut FnMut(uint) -> uint
}
但我认为它更慢,因为a)指针deref,现在没有专门用于 FnMut
类型的实际上最终被使用。
But I think it's slower because a) the pointer deref, and b) now there's no specialization for the type of FnMut
that actually ends up being used.
推荐答案
这是错误的:等效的是 Box< FnMut(uint) - > uint>
。
更正:正如dbaupp指出的那样,这是不正确的。使用 ||
语法的旧式闭包是对存储在堆栈上的闭包的引用,使它们等效于&'a mut FnMut(uint ) - > uint
。它是被堆分配的 proc
,并且等效于 Box< FnOnce(uint) - > uint>
(您只能调用 proc
一次)。
Correction: As dbaupp pointed out, that isn't correct. Old-style closures that used the ||
syntax were references to closures stored on the stack, making them equivalent to &'a mut FnMut(uint) -> uint
. It was proc
s that were heap-allocated, and were equivalent to Box<FnOnce(uint) -> uint>
(you can only call a proc
once). My apologies for the mistake.
对于您在第三个程式码片段中使用的类型,不是 闭包类型是匿名的,不能直接命名。您可以这样写:
As for what type you'd use in your third code snippet, there isn't one; closure types are anonymous and cannot be directly named. Instead, you'd write:
let foo = Foo { foo: |x| x + 1 };
如果您要在需要 你想要 Foo
,你会写:
If you're writing code in a context where you need to specify that you want a Foo
, you'd write:
let foo: Foo<_> = Foo { foo: |x| x + 1 };
_
告诉类型系统
按照 使用的一般经验法则,按照降序排列:
The general rule of thumb as to which to use, in descending order:
- 通用参数:
struct Foo< F:FnMut(uint) - > uint>
。这是最有效的,但它的确意味着一个特定的Foo
实例只能存储一个闭包,因为每个闭包都有不同的具体类型 - 性格参考:
&'a mut FnMut(uint) - > uint
。有一个指针间接,但现在你可以存储对任何具有兼容调用签名的闭包的引用。 - 盒子闭包:
Box< FnMut(uint) ; uint>
。这涉及到在堆上分配闭包,但是你不必担心生命周期。与引用一样,您可以存储具有兼容签名的任何关闭。
- Generic parameters:
struct Foo<F: FnMut(uint) -> uint>
. This is the most efficient, but it does mean that a specificFoo
instance can only ever store one closure, since every closure has a different concrete type. - Trait references:
&'a mut FnMut(uint) -> uint
. There's a pointer indirection, but now you can store a reference to any closure that has a compatible call signature. - Boxed closures:
Box<FnMut(uint) -> uint>
. This involves allocating the closure on the heap, but you don't have to worry about lifetimes. As with a reference, you can store any closure with a compatible signature.
这篇关于如何在Rust中存储闭包?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!