How do I use the yield keyword in Rust? [duplicate]
Asked Answered
A

1

7

I'm trying to make a function that will return an iterator of all the files in a directory, including all the files in the subdirectories. As I don't know the size of an array that would contain all the files' paths, I thought that it would be easier to have the function return an iterator instead of an array. It's simple enough to do in Python:

def func():
    for i in range(0, 100):
        yield i

for i in func():
    print(i)

But when I try to do something similar in Rust, I get compiler errors and/or compiler panics. Here, I tried some basic syntax that's close to what it is in Python:

fn func() -> Iterator {
    for i in 0..100 {
        yield i;
    }
}

fn main() {
    for i in func() {
        println!("{}", i);
    }
}

But when I compiled it, it caused two errors and a warning:

error[E0658]: yield syntax is experimental
 --> src/main.rs:3:9
  |
3 |         yield i;
  |         ^^^^^^^
  |
  = note: see issue #43122 <https://github.com/rust-lang/rust/issues/43122> for more information

warning: trait objects without an explicit `dyn` are deprecated
 --> src/main.rs:1:14
  |
1 | fn func() -> Iterator {
  |              ^^^^^^^^ help: use `dyn`: `dyn Iterator`
  |
  = note: `#[warn(bare_trait_objects)]` on by default
  = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
  = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>

error[E0191]: the value of the associated type `Item` (from trait `Iterator`) must be specified
 --> src/main.rs:1:14
  |
1 | fn func() -> Iterator {
  |              ^^^^^^^^ help: specify the associated type: `Iterator<Item = Type>`

Some errors have detailed explanations: E0191, E0658.
For more information about an error, try `rustc --explain E0191`.
warning: `problem` (bin "problem") generated 1 warning
error: could not compile `problem` due to 2 previous errors; 1 warning emitted

I've been playing around with using different return types, like dyn Iterator<Item = i32>, impl Iterator, etc. according to the help in the error messages, and I either get errors, compiler panics, or both. Sorry if this is a stupid question; I've only been working with Rust for around three months. But somehow, it feels like this should be simpler.

So my question: what's the correct syntax for a function returning an iterator generated using the yield keyword? I've looked in the Rust Documentation and The Book, but I've found nothing useful.

Athalie answered 3/12, 2021 at 17:44 Comment(2)
The error says "yield syntax is experimental" - are you looking for an answer that demonstrates how to use this syntax in its experimental form or are you more interested in idiomatic solutions for what you're trying to achieve?Eastbound
@Eastbound I know that the syntax is experimental, but I thought that it had come farther than was evident in the error messages. I would like to use the yield keyword if it's simpler than any other solutions. If it's not, than any other solutions are welcome. My ultimate goal is to be able to return an iterator that was created by an iteration.Athalie
H
10

An iterator needs to implement Iterator trait. Rust doesn't use of the yield keyword for generators (for now, Rust 1.57), so you cannot use it. Direct translation of your code would be:

fn func() -> impl Iterator<Item=u32> {
    0..100u32
}

fn main() {
    for i in func() {
        println!("{}", i);
    }
}

The (0..100) is a Range object that implements Iterator

References

  1. Iterator
  2. Generators (Unstable)
  3. Walkdir (solving a similar problem)
Hammerfest answered 3/12, 2021 at 17:57 Comment(1)
Alright, it looks like Walkdir solved the problem. This question is really not what I intended, but I can't delete it. I think I'll just rollback that edit I just did, and leave the question as it is. Thanks for the recommendation! I'll accept your answer as soon as I get the rollback done.Athalie

© 2022 - 2024 — McMap. All rights reserved.