未为 Fn 类型实现 Sized [英] Sized is not implemented for the type Fn

查看:20
本文介绍了未为 Fn 类型实现 Sized的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想构建一个将列表拆分为两个的函数:一个列表包含原始列表中满足某个谓词的元素,另一个包含所有不满足的元素.以下是我的尝试:

I want to build a function that splits a list into two: one list that contains the elements of the original list that satisfy a certain predicate, and another that contains all the ones which do not. Below is my attempt:

fn split_filter<T: Clone + Sized>(a: &Vec<T>, f: Fn(&T) -> bool) -> (Vec<T>, Vec<T>) {
    let i: Vec<T> = vec![];
    let e: Vec<T> = vec![];
    for u in a.iter().cloned() {
        if f(&u) {
            i.push(u)
        } else {
            e.push(u)
        }
    }

    return (i, e);
}

fn main() {
    let v = vec![10, 40, 30, 20, 60, 50];
    println!("{:?}", split_filter(&v, |&a| a % 3 == 0));
}

但是,我收到两个错误:

However, I get two errors:

error[E0277]: the trait bound `for<'r> std::ops::Fn(&'r T) -> bool + 'static: std::marker::Sized` is not satisfied
 --> src/main.rs:1:47
  |
1 | fn split_filter<T: Clone + Sized>(a: &Vec<T>, f: Fn(&T) -> bool) -> (Vec<T>, Vec<T>) {
  |                                               ^ `for<'r> std::ops::Fn(&'r T) -> bool + 'static` does not have a constant size known at compile-time
  |
  = help: the trait `std::marker::Sized` is not implemented for `for<'r> std::ops::Fn(&'r T) -> bool + 'static`
  = note: all local variables must have a statically known size

error[E0308]: mismatched types
  --> src/main.rs:17:39
   |
17 |     println!("{:?}", split_filter(&v, |&a| a % 3 == 0));
   |                                       ^^^^^^^^^^^^^^^ expected trait std::ops::Fn, found closure
   |
   = note: expected type `for<'r> std::ops::Fn(&'r {integer}) -> bool + 'static`
              found type `[closure@src/main.rs:17:39: 17:54]`

第二个错误似乎暗示闭包不是 Fn.我尝试使用语法 f: |&T|->我在网上某处找到的 bool,但这似乎不适用于最新版本的 Rust.

The second error seems to imply that a closure is not a Fn. I tried using the syntax f: |&T| -> bool which I found online somewhere, but that does not seem to work in the latest version of Rust.

对于第一个错误,我曾希望使 T Sized 能够使函数具有已知大小,但显然它没有.

As for the first error, I had hoped that making T Sized would make it so that the function has a known size, but apparently it doesn't.

推荐答案

你应该阅读 Rust 的官方书籍,尤其是 关于闭包的章节.你的函数声明不正确;您指定 f 具有裸特征类型,这是不可能的;这正是关于 Sized 的错误的内容.您应该改用泛型类型参数:

You should read the official Rust book, especially the chapter on closures. Your function declaration is incorrect; you are specifying that f has a bare trait type, which is impossible; that's exactly what the error about Sized is about. You should use a generic type parameter instead:

fn split_filter<T: Clone, F>(a: &[T], f: F) -> (Vec<T>, Vec<T>)
where
    F: for<'a> Fn(&'a T) -> bool,

我也将 a 的类型从 &Vec 更改为 &[T];在任何情况下,您都更喜欢前者而不是后者.&Vec 会在必要时自动强制转换为 &[T].请参阅 为什么不鼓励接受对 String (&String) 或 Vec (&Vec) 的引用作为函数参数?

I have also changed the type of a from &Vec<T> to &[T]; there is no situation in which you would prefer the former to the latter. &Vec<T> is automatically coerced to &[T] when necessary. See Why is it discouraged to accept a reference to a String (&String) or Vec (&Vec) as a function argument?

第二个错误与函数声明中的错误密切相关;您的原始函数声明指定了一个裸特征类型,但闭包没有这种类型,它们只是实现了函数特征.

The second error is closely tied to the mistake in the function declaration; your original function declaration specified a bare trait type, but closures do not have this type, they just implement the function trait.

最终的程序是这样的:

fn split_filter<T: Clone, F>(a: &[T], f: F) -> (Vec<T>, Vec<T>)
where
    F: Fn(&T) -> bool,
{
    let mut i: Vec<T> = vec![];
    let mut e: Vec<T> = vec![];
    for u in a.iter().cloned() {
        if f(&u) {
            i.push(u);
        } else {
            e.push(u);
        }
    }

    return (i, e);
}

fn main() {
    let v = vec![10, 40, 30, 20, 60, 50];
    println!("{:?}", split_filter(&v, |&a| a % 3 == 0));
}

游乐场上试试.

这篇关于未为 Fn 类型实现 Sized的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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