如何在Rust中存储闭包? [英] How do I store a closure in Rust?

查看:169
本文介绍了如何在Rust中存储闭包?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我以前有类似的东西:

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 procs 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 specific Foo 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中存储闭包?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆