简体   繁体   English

从 function 返回一个泛型类型,在 rust 中没有泛型参数

[英]Returning a generic type from a function without generic parameters in rust

I'm currently trying to write a small function in Rust that returns a iterator over the tokens of a simple LISP-style calculator language.我目前正在尝试在 Rust 中编写一个小的 function ,它在简单的 LISP 样式计算器语言的标记上返回一个迭代器。 I ran into a compile error when I didn't expect to.当我没想到时遇到了编译错误。

My first attempt to write the function was:我第一次尝试编写 function 是:

fn tokenizer_for<'a, I>(s: &'a str) -> Peekable<I> where I: Iterator<Item=&'a str> {
    s.split_whitespace()
        .flat_map(
            |word| {
                word.replace("(", "( ").replace(")", " )").split_whitespace()
            }
        )
        .peekable()
}

However rustc replies:然而 rustc 回复:

error[E0308]: mismatched types
  --> src/lib.rs:4:5
   |
3  |   fn tokenizer_for<'a, I>(s: &'a str) -> Peekable<I> where I: Iterator<Item=&'a str> {
   |                        -                 ----------- expected `std::iter::Peekable<I>` because of return type
   |                        |
   |                        this type parameter
4  | /     s.split_whitespace()
5  | |         .flat_map(
6  | |             |word| {
7  | |                 word.replace("(", "( ").replace(")", " )").split_whitespace()
8  | |             }
9  | |         )
10 | |         .peekable()
   | |___________________^ expected type parameter `I`, found struct `std::iter::FlatMap`
   |
   = note: expected struct `std::iter::Peekable<I>`
              found struct `std::iter::Peekable<std::iter::FlatMap<std::str::SplitWhitespace<'_>, std::str::SplitWhitespace<'_>, [closure@src/lib.rs:6:13: 8:14]>>`
   = help: type parameters must be constrained to match other types
   = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters

I found that using impl in the return type worked (which I prefer):我发现在返回类型中使用impl是有效的(我更喜欢):

fn tokenizer_for(s: &str) -> Peekable<impl Iterator<Item=&str>> {
    s.split_whitespace()
        .flat_map(
            |word| {
                word.replace("(", "( ").replace(")", " )").split_whitespace()
            }
        )
        .peekable()
}

But I had expected to be able to choose between either option, even though it appears that the latter attempt that worked might not even be producing a generic function.但我曾期望能够在任一选项之间进行选择,即使看起来后一种有效的尝试甚至可能不会产生通用的 function。

Why can I not use a where clause to specify a generic type in the former case?为什么我不能在前一种情况下使用where子句来指定泛型类型?

I have used where clauses to constrain generic parameters that appear in return types before.我之前使用where子句来约束出现在返回类型中的泛型参数。 Does that only work when the generic parameter also appears in the function's parameters?仅当泛型参数也出现在函数的参数中时才有效吗?

Any references that explain more about the details of this distinction would be particularly helpful.任何能更多解释这种区别细节的参考资料都会特别有帮助。

In Rust, when you have lifetimes or type parameters specified in the Item<...> list, those lifetimes or type parameters are chosen at the use site.在 Rust 中,当您在Item<...>列表中指定了生命周期或类型参数时,将在使用现场选择这些生命周期或类型参数。

This function signature says that the caller of the function can choose what type I is:这个 function 签名说 function 的调用者可以选择I是什么类型:

fn tokenizer_for<'a, I>(s: &'a str) -> Peekable<I> where I: Iterator<Item=&'a str>;

but that doesn't compile because the return type is actually the return type of the call to Iter::peekable() (ie, the type from your error message std::iter::Peekable<std::iter::FlatMap<std::str::SplitWhitespace<'_>, std::str::SplitWhitespace<'_>, [closure@src/lib.rs:6:13: 8:14]>> ).但这不会编译,因为返回类型实际上是调用Iter::peekable()的返回类型(即错误消息中的类型std::iter::Peekable<std::iter::FlatMap<std::str::SplitWhitespace<'_>, std::str::SplitWhitespace<'_>, [closure@src/lib.rs:6:13: 8:14]>> )。

On the other hand, this signature says that the return type is merely something that implements Iterator<Item=&str>> :另一方面,这个签名表示返回类型只是实现Iterator<Item=&str>>东西

fn tokenizer_for(s: &str) -> Peekable<impl Iterator<Item=&str>>;

The caller cannot choose what type that is;调用者不能选择那是什么类型; the compiler infers the actual type from the function body.编译器从 function 主体推断出实际类型。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM