当前位置: 首页 > 知识库问答 >
问题:

动态闭包Vec的坏类型推断

丁翰海
2023-03-14

我正在尝试获取部分应用的函数的列表,如下所示:

fn partially_applied() -> Vec<Box<dyn Fn(u32) -> u32>> {
    let xs = vec![1_u32, 2, 3];

    xs.into_iter().map(|x| Box::new(move |y| x + y)).collect() 
}

编译器向我产生一个错误:

错误[E0277]:类型std::vec::Vec的值

随后的尝试也没有成功:

1.

fn partially_applied_with_explicit_collect_type() -> Vec<Box<dyn Fn(u32) -> u32>> {
    let xs = vec![1_u32, 2, 3];

    xs.into_iter().map(|x| Box::new(move |y| x + y)).collect::<Vec<Box<dyn Fn(u32) -> u32>>>() 
}
fn partially_applied_with_explicit_vec_type() -> Vec<Box<dyn Fn(u32) -> u32>> {
    let xs = vec![1_u32, 2, 3];

    let mut res: Vec<Box<dyn Fn(u32) -> u32>> = xs.into_iter().map(|x| Box::new(move |y| x + y)).collect(); 
    res 
}
fn partially_applied_with_explicit_push() -> Vec<Box<dyn Fn(u32) -> u32>> {
    let xs = vec![1_u32, 2, 3];

    let mut res = vec![];

    for x in xs { 
        res.push(Box::new(move |y| x + y)); 
    }

    res 
}

也只有这一次尝试最终成功了!

fn partially_applied_with_explicit_push_and_vec_type() -> Vec<Box<dyn Fn(u32) -> u32>> {
    let xs = vec![1_u32, 2, 3];

    let mut res: Vec<Box<dyn Fn(u32) -> u32>> = vec![];

    for x in xs { 
        res.push(Box::new(move |y| x + y)); 
    }

    res 
}

为什么在动态闭包方面类型推断如此糟糕?

为什么收集在第一次尝试中不起作用?

有没有更好的方法来利用类型推理来表达这样的想法?

共有1个答案

阎宾实
2023-03-14

潜在的问题是每个闭包都有它自己的不可命名的类型,它是唯一的成员。此外,编译器可以自动将特定的装箱闭包转换成< code>Box

因此,以下是确定的:

fn closure() -> Box<dyn Fn(u32) -> u32> {
    Box::new(|x| x)
}

但这不是:

fn partially_applied() -> Vec<Box<dyn Fn(u32) -> u32>> {
    let xs = vec![1_u32, 2, 3];
    xs.into_iter().map(|x| Box::new(move |y| x + y)).collect() 
}

为什么不呢?

value of type `Vec<Box<dyn Fn(u32) -> u32>>` cannot be built from
`std::iter::Iterator<Item=Box<[closure@src/main.rs:12:37: 12:51]>>`

help: the trait `FromIterator<Box<[closure@src/main.rs:12:37: 12:51]>>`
is not implemented for `Vec<Box<dyn Fn(u32) -> u32>>`

这是因为< code>Vec的< code>FromIterator中绑定的trait是

impl<T> FromIterator<T> for Vec<T> {
    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Vec<T> { ... }
}

和<代码>框

所以问题不在于“为什么 Rust 的类型推断在这里失败了”,而是“为什么 Vec 没有实现以下内容”:

impl<T, U> FromIterator<T> for Vec<U>
where T: Into<U> {
    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Vec<U> { ... }
}

我不知道。我怀疑当存在多对<code>T,U</code>时,这会导致其自身的类型推断问题。

注意:您可以按以下方式将您的盒子转换为正确的类型:

fn partially_applied() -> Vec<Box<dyn Fn(u32) -> u32>> {
    let xs = vec![1_u32, 2, 3];

    xs.into_iter()
        .map(|x| Box::new(move |y| x + y) as Box<dyn Fn(u32) -> u32>)
        .collect()
}
 类似资料:
  • 在第七章我们粗略介绍了一下Vec的用法。实际上,作为Rust中一个非常重要的数据类型,熟练掌握Vec的用法能大大提升我们在Rust世界中的编码能力。 特性及声明方式 和我们之前接触到的Array不同,Vec具有动态的添加和删除元素的能力,并且能够以O(1)的效率进行随机访问。同时,对其尾部进行push或者pop操作的效率也是平摊O(1)的。 同时,有一个非常重要的特性(虽然我们编程的时候大部分都不

  • 为什么可以推断闭包表达式的参数类型和返回类型,而不是rust中的函数?

  • 我认为以下代码可以工作: 但是我得到了一个编译器错误(见这里):

  • 前面说泛型的时候,提到了C++模板的实现方式是动态特性静态化,在实际情况中,这是一个提高效率的好办法。动态性的好处是灵活,开发简便,静态性的特性是效率高,编译期检查较好,因此很自然地就有一个问题,能不能各取所长,达到两全其美?应该说,在一定程度上是可以的,比如这篇即将讨论的静态类型推导,简称类型推导,因为动态类型无所谓什么推导。个人认为类型推导是编译原理最复杂的东西之一,其他复杂的有垃圾回收,代码

  • 闭包从封闭的作用中域捕获变量简单明了。这样会有某些后果吗?当然会。观察一下使用闭包作为函数参量的方式是要求为泛型的,它们定义的方式决定了这是必要的(原文:Observe how using a closure as a function parameter requires generics, which is necessary because of how they are defined):

  • 问题内容: 在下面函数的第三行,出现以下错误: 无法在当前上下文中推断闭包类型 我该如何解决? 问题答案: 它不推断闭包类型的原因是因为未处理该语句。这意味着关闭预期会出现错误,但是在您的情况下,您忘记了规则。 因此,您可以尝试使用以下答案来捕获您的错误: 然后,您可以断言错误(用于测试),或者我个人会设置警报。 这样,应用程序不会崩溃,而是通知用户。我发现这在旅途中 非常 有用,而且我的设备未插