【问题标题】:What is the iterator type returned by this Rust function?这个 Rust 函数返回的迭代器类型是什么?
【发布时间】:2015-06-03 00:31:02
【问题描述】:

所以我在这里有这个示例代码:

use std::iter::Filter;
use std::slice::Iter;

fn main() {
    let numbers = vec![12i32, 26, 31, 56, 33, 16, 81];

    for number in ends_in_six(numbers) {
        println!("{}", number);
    }
}

fn ends_in_six(numbers: Vec<i32>) /* -> ??? */ {
    numbers.iter().filter(|&n| *n % 10 == 6)
}

我正在尝试返回一个迭代器,从我收集的内容来看,它在 Rust 中一直很麻烦。运行代码here 给我这个错误:

<anon>:13:5: 13:45 error: mismatched types:
 expected `()`,
    found `core::iter::Filter<core::slice::Iter<'_, i32>, [closure <anon>:13:27: 13:44]>`
(expected (),
    found struct `core::iter::Filter`) [E0308]
<anon>:13     numbers.iter().filter(|&n| *n % 10 == 6)
              ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

现在,解决这个问题(并且基于我对这一切如何运作的相对有限的了解),似乎我应该做一些类似的事情:

fn ends_in_six<'a>(numbers: Vec<i32>) -> Filter<Iter<'a, i32>, /* ??? */> {

但现在我又被卡住了,因为我得到的是 [closure &lt;anon&gt;:13:27: 13:44] 而不是实际的类型。即使我尝试使用函数here 来尝试找出类型,我也得到了:

core::iter::Filter<core::slice::Iter<i32>, [closure((&&i32,)) -> bool]>

所以,我试图自己弄清楚,并基于上一行,我尝试:

fn ends_in_six<'a>(numbers: Vec<i32>) -> Filter<Iter<'a, i32>, Fn(&&i32) -> bool> {

并得到更多错误,因为 Fn 在编译时不是常量(即不实现 Sized)。这是有道理的,但我有点茫然,还有什么可以尝试的。

编辑:我只是tried

fn ends_in_six<'a, F>(numbers: Vec<i32>) -> Filter<Iter<'a, i32>, F>
  where F: Fn(&&i32) -> bool {

现在我遇到了这些错误:

<anon>:7:19: 7:30 error: unable to infer enough type information about `_`; type annotations required [E0282]
<anon>:7     for number in ends_in_six(numbers) {
                           ^~~~~~~~~~~
<anon>:14:32: 14:34 error: the type of this value must be known in this context
<anon>:14     numbers.iter().filter(|&n| *n % 10 == 6)
                                         ^~
<anon>:14:27: 14:44 error: mismatched types:
 expected `F`,
    found `[closure <anon>:14:27: 14:44]`
(expected type parameter,
    found closure) [E0308]
<anon>:14     numbers.iter().filter(|&n| *n % 10 == 6)
                                    ^~~~~~~~~~~~~~~~~

【问题讨论】:

  • “我正在尝试返回一个迭代器,它一直很麻烦” - 它不是返回一个复杂的迭代器,它通常返回一个迭代器适配器,其中包含一个关闭。或者返回一个实现Iterator 的非具体类型,它没有已知的大小。
  • 返回一个包含闭包的迭代器很容易,如果你不介意装箱:is.gd/nBad0O --- 一旦我们得到impl Trait return types,摆脱装箱也很容易。

标签: types iterator rust type-inference return-type


【解决方案1】:

每个闭包都有自己独特的类型(闭包是结构和FnFnMutFnOnce 实现的糖,具体取决于确定)并且无法写出闭包的类型。

您可以做的一件事是将其编写为函数,然后将其转换为函数指针,如下所示。

另一件事是使用盒装函数 (Box&lt;Fn(&amp;&amp;i32) -&gt; bool&gt;),例如 Box::new(|&amp;&amp;n| n % 10 == 6)。这涉及堆分配,因此不是最有效的,但在现实生活中您无需担心性能差异。

你所做的泛型尝试不起作用,因为泛型是关于允许 调用者 指定一个类型,任何类型,在这种情况下你希望 被调用者指定一个唯一类型。

use std::iter::Filter;
use std::slice::Iter;

fn main() {
    let numbers = vec![12i32, 26, 31, 56, 33, 16, 81];

    for number in ends_in_six(numbers) {
        println!("{}", number);
    }
}

fn ends_in_six(numbers: Vec<i32>) Filter<Iter<'a, i32>, fn(&&i32) -> bool> {
    fn filterer(&&n: &&i32) -> bool { n % 10 == 6 }
    numbers.iter().filter(filterer as fn(&&i32) -> bool)
}

【讨论】:

  • 最后的代码不起作用,如果我修复琐碎的语法错误,numbers 的寿命不够长,这不足为奇。最好使用&amp;[i32] 而不是Vec&lt;i32&gt;
  • 解释很有帮助,加上delnan的代码解决了我的问题,所以谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多