以下Rust代码编译和运行时没有任何问题。
fn main() {
let text = "abc";
println!("{}", text.split(' ').take(2).count());
}
在那之后,我尝试了这样的东西....但它没有编译
fn main() {
let text = "word1 word2 word3";
println!("{}", to_words(text).take(2).count());
}
fn to_words(text: &str) -> &Iterator<Item = &str> {
&(text.split(' '))
}
主要问题是,我不确定函数<code>to_words()
error[E0599]: no method named `count` found for type `std::iter::Take<std::iter::Iterator<Item=&str>>` in the current scope
--> src/main.rs:3:43
|
3 | println!("{}", to_words(text).take(2).count());
| ^^^^^
|
= note: the method `count` exists but the following trait bounds were not satisfied:
`std::iter::Iterator<Item=&str> : std::marker::Sized`
`std::iter::Take<std::iter::Iterator<Item=&str>> : std::iter::Iterator`
运行该程序的正确代码是什么?....而我的知识差距在哪里?
添加到@Shepmaster答案。如果你需要闭包和闭包捕获一些参数,你可以使用这个例子
fn find_endpoint<'r>(
descriptors: &'r mut rusb::EndpointDescriptors<'r>,
direction: rusb::Direction,
) -> FilterMap<
&mut rusb::EndpointDescriptors<'_>,
impl FnMut(rusb::EndpointDescriptor<'r>) -> Option<u8>,
> {
descriptors.filter_map(move |ep| {
if ep.direction() == direction {
Some(ep.address())
} else {
None
}
})
}
我发现让编译器来指导我很有用:
fn to_words(text: &str) { // Note no return type
text.split(' ')
}
编译给出:
error[E0308]: mismatched types
--> src/lib.rs:5:5
|
5 | text.split(' ')
| ^^^^^^^^^^^^^^^ expected (), found struct `std::str::Split`
|
= note: expected type `()`
found type `std::str::Split<'_, char>`
help: try adding a semicolon
|
5 | text.split(' ');
| ^
help: try adding a return type
|
3 | fn to_words(text: &str) -> std::str::Split<'_, char> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
按照编译器的建议,将它复制粘贴为我的返回类型(稍加清理):
use std::str;
fn to_words(text: &str) -> str::Split<'_, char> {
text.split(' ')
}
问题是你不能返回像< code>Iterator这样的特征,因为特征没有大小。这意味着Rust不知道为该类型分配多少空间。您也不能返回对局部变量的引用,所以返回< code >
从Rust 1.26开始,您可以使用< code>impl trait:
fn to_words<'a>(text: &'a str) -> impl Iterator<Item = &'a str> {
text.split(' ')
}
fn main() {
let text = "word1 word2 word3";
println!("{}", to_words(text).take(2).count());
}
如何使用它有限制。您只能返回一种类型(没有条件!)并且它必须在自由函数或固有实现上使用。
如果您不介意损失一点效率,您可以返回一个Box
fn to_words<'a>(text: &'a str) -> Box<dyn Iterator<Item = &'a str> + 'a> {
Box::new(text.split(' '))
}
fn main() {
let text = "word1 word2 word3";
println!("{}", to_words(text).take(2).count());
}
这是允许动态调度的主要选项。也就是说,代码的确切实现是在运行时决定的,而不是在编译时决定的。这意味着这适用于需要根据条件返回多个具体类型的迭代器的情况。
use std::str;
struct Wrapper<'a>(str::Split<'a, char>);
impl<'a> Iterator for Wrapper<'a> {
type Item = &'a str;
fn next(&mut self) -> Option<&'a str> {
self.0.next()
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.0.size_hint()
}
}
fn to_words(text: &str) -> Wrapper<'_> {
Wrapper(text.split(' '))
}
fn main() {
let text = "word1 word2 word3";
println!("{}", to_words(text).take(2).count());
}
如reem所指出的
use std::str;
type MyIter<'a> = str::Split<'a, char>;
fn to_words(text: &str) -> MyIter<'_> {
text.split(' ')
}
fn main() {
let text = "word1 word2 word3";
println!("{}", to_words(text).take(2).count());
}
当
impl Trait
无法使用时,闭包会使事情变得更加复杂。闭包创建匿名类型,并且这些类型不能在返回类型中命名:
fn odd_numbers() -> () {
(0..100).filter(|&v| v % 2 != 0)
}
found type `std::iter::Filter<std::ops::Range<{integer}>, [closure@src/lib.rs:4:21: 4:36]>`
在某些情况下,这些闭包可以用函数替换,这些函数可以命名为:
fn odd_numbers() -> () {
fn f(&v: &i32) -> bool {
v % 2 != 0
}
(0..100).filter(f as fn(v: &i32) -> bool)
}
found type `std::iter::Filter<std::ops::Range<i32>, for<'r> fn(&'r i32) -> bool>`
并遵循上述建议:
use std::{iter::Filter, ops::Range};
type Odds = Filter<Range<i32>, fn(&i32) -> bool>;
fn odd_numbers() -> Odds {
fn f(&v: &i32) -> bool {
v % 2 != 0
}
(0..100).filter(f as fn(v: &i32) -> bool)
}
如果您需要有条件地选择迭代器,请参阅有条件地迭代几个可能的迭代器之一。
问题内容: 为什么?将迭代器项指针移到第一位置的最佳方法是什么? 问题答案: 为什么? 因为如果强制迭代器具有重置方法,则 每个 迭代器都必须具有重置方法。这给每个迭代器编写者额外的工作。再加上一些迭代器确实很难重置(或者真的很昂贵),并且您不希望用户对其调用reset。文件或流上的迭代器就是很好的例子。 将迭代器项指针移到第一位置的最佳方法是什么? 创建一个新的迭代器。它很少比重置昂贵。
我可以看到返回。但是现在已经添加到C++20标准中,为什么返回?cppreference指定: 返回值 等于last的迭代器。 这个选择背后的理性是什么? 与相比,用例的优势是什么?
问题内容: 据我了解,使用生成器是实现此类目标的最佳方法,但我愿意提出建议。 具体来说,一个用例是这样的:我想在另一个列表的旁边打印任意长度的一些项目,并在必要时截断初始迭代器。 这是有效的python代码,演示了我想要的确切示例行为: 问题/我的问题 您可能已经注意到,这仅适用于实现的列表/元组/可迭代对象(如果我没记错的话)。理想情况下,我希望能够传递任何可迭代的对象,并接收可以正确循环其内容
我有一个实用函数,它从您的数组中返回一个值。但是,您的数组显然可以包含任何类型的元素,那么如何记录返回类型是混合的呢? 在PHPdoc中,我将使用: JSDoc等价物是什么?
我已经阅读了很多Java8可选版本,我确实理解这个概念,但在我的代码中尝试实现它时仍然会遇到困难。 虽然我在网上搜索了一些好的例子,但我没有找到一个解释得很好的例子。 我有下一个方法: 这个简单的方法通过传递文件路径来返回文件的md5。正如您所注意到的,如果文件路径不存在(或键入错误),将抛出NoSuchFileException,该方法返回Null。 我希望使用Optional,而不是返回nul