我试图得到一个部分应用函数的列表,如下所示:

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&lt;标准::盒装::盒装&lt;dyn std::ops::Fn(u32)-&gt;u32&gt&gt;无法从类型为std::boxed::Box&lt;的元素上的迭代器生成;[closure@src/梅因.rs:4:41:4:57]&gt;


随后的try 也没有成功:

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 
}

只有这个try 最终成功了!

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 
}

当涉及到动态闭包时,为什么类型推断如此糟糕?

为什么collect在第一次try 中不起作用?

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

推荐答案

根本的问题是,每个闭包都有自己的不可命名类型,它是唯一的成员.此外,虽然编译器可以自动将特定的盒式闭包转换为Box<dyn *closure's type*>,但它无法深入到泛型类型中执行向上转换.

所以以下是可以的:

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>>`

这是因为Vec分为FromIterator分的trait 是

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

Box<[closure@src/main.rs]>是与Box<dyn Fn(u32) -> u32>不同的类型.

所以问题不是"为什么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> { ... }
}

我不知道.我怀疑这会导致它自己的类型推断问题,当有多对T,U时,这会使事情顺利进行.

注意:您可以按以下方式将箱子铸造为正确的类型:

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()
}

Rust相关问答推荐

为什么单元类型(空元组)实现了`Extend`trait?

把Vector3变成Vector4的绝妙方法

如何将`Join_all``Vec<;Result<;Vec<;Foo&>;,Anywhere::Error&>;`合并到`Result<;Vec<;Foo&>;,Anywhere::Error&>;`

从Type::new()调用函数

为什么这是&q;,而让&q;循环是无限循环?

我如何制作一个变异迭代器来锁定内部数据直到删除?

如何将一个矩阵的列分配给另一个矩阵,纳尔代数?

我可以用 Rust 编写一个不可变变量

为什么我的trait 对象类型不匹配?

如何获取模块树?

rust 中不同类型的工厂函数

在运行时在 Rust 中加载字体

Rust 引用元组和引用元组

使用部分键从 Hashmap 中检索值

为什么 no_std crate 可以依赖于使用 std 的 crate?

在空表达式语句中移动的值

为什么 match 语句对引用类型比函数参数更挑剔?

为什么可以从闭包中返回私有 struct

为什么 std::iter::Peekable::peek 可变地borrow self 参数?

为什么我不能将元素写入 Rust 数组中移动的位置,但我可以在元组中完成