How do I use the yield keyword in Rust? [duplicate] - rust

This question already has answers here:
Lazy sequence generation in Rust
(4 answers)
Closed 1 year ago.
This post was edited and submitted for review 1 year ago and failed to reopen the post:
Original close reason(s) were not resolved
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.

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
Iterator
Generators (Unstable)
Walkdir (solving a similar problem)

Related

can't find gen_range method on rand::thread_rng [duplicate]

This question already has an answer here:
Why do I need to import a trait to use the methods it defines for a type?
(1 answer)
Closed 2 years ago.
I'm stuck on the first example given in the Rust book, the guessing game. I just cannot find the gen_range method on thread_rng() to generate the number. The only methods that show up are fill_bytes, next_u32, next_u64 and try_fill_bytes, and if I try to write it anyway I get an error saying the method doesn't exist. However, when I tried the random function, which according to the documentation is simply a shortcut for thread_rng().gen(), it works. I've tried other functions, updating and reinstalling everything but it still doesn't work and I really don't know what to do.
Welcome to Stack Overflow. In the future, please try to add more information to your question, including relevant links (which doc are you talking about), source code and error messages. This will make it easier for us to give relevant and useful answers.
I'm assuming you're doing something like this:
use rand::thread_rng;
fn main() {
let x = thread_rng().gen_range(0, 10);
println!("{}", x);
}
Playground
Which gives the following error:
error[E0599]: no method named `gen_range` found for struct `rand::rngs::thread::ThreadRng` in the current scope
--> src/main.rs:4:26
|
4 | let x = thread_rng().gen_range(0, 10);
| ^^^^^^^^^ method not found in `rand::rngs::thread::ThreadRng`
|
::: /playground/.cargo/registry/src/github.com-1ecc6299db9ec823/rand-0.7.3/src/lib.rs:212:8
|
212 | fn gen_range<T: SampleUniform, B1, B2>(&mut self, low: B1, high: B2) -> T
| ---------
| |
| the method is available for `std::boxed::Box<rand::rngs::thread::ThreadRng>` here
| the method is available for `std::sync::Arc<rand::rngs::thread::ThreadRng>` here
| the method is available for `std::rc::Rc<rand::rngs::thread::ThreadRng>` here
|
= help: items from traits can only be used if the trait is in scope
help: the following trait is implemented but not in scope; perhaps add a `use` for it:
|
1 | use rand::Rng;
|
Note that the Rust compiler is very good in giving suggestions for ways to fix your code. In this case, the last line from the error suggests adding use rand::Rng;, and now it works:
use rand::Rng;
use rand::thread_rng;
fn main() {
let x = thread_rng().gen_range(0, 10);
println!("{}", x);
}
Playground
This is because the gen_range method is not implemented directly on the ThreadRng struct, but instead it is implemented in the general Rng trait, which makes it automatically available for all random number generators. However methods from traits are only available if the trait itself is available, hence the need to import rand::Rng first.
You can try installing the the following version, works for me in this version.
Add this to your Cargo.toml dependencies:
rand = "0.7.3"
Import:
use rand::Rng;
Usage:
rand::thread_rng().gen_range(0, 10);

understanding error: trait `futures::future::Future` is not implemented for `()`

This question is about how to read the Rust documentation and improve my understanding of Rust so as to understand how to address this specific compiler error.
I've read the tokio docs and experimented with many of the examples. In writing my own code, I frequently run into compiler errors that I don't understand and often found I can fix the code, but don't understand why specific syntax is needed.
I reproduced with a very simple example based on tokio's hello world:
use futures::Future;
use tokio::net::TcpStream;
use tokio::prelude::*;
fn main() {
let addr = "127.0.0.1:6142".parse().unwrap();
let client = TcpStream::connect(&addr).and_then(|stream| {
println!("created stream");
// Process stream here.
// Ok(())
});
}
The above code is incorrect, requiring the commented out Ok(). I know that this is true, but not exactly why. This is perhaps the other half of a prior question How do I interpret the signature of read_until and what is AsyncRead + BufRead in Tokio? -- now I understand closures better, but can't quite parse the docs to understand the expected return value.
When I attempt to compile the incorrect code above, I get the following error:
error[E0277]: the trait bound `(): futures::future::Future` is not satisfied
--> tokio-chat-client/src/main.rs:8:42
|
8 | let client = TcpStream::connect(&addr).and_then(|stream| {
| ^^^^^^^^ the trait `futures::future::Future` is not implemented for `()`
|
= note: required because of the requirements on the impl of `futures::future::IntoFuture` for `()`
There are two parts to my question:
What is the error message trying to tell me?
How would I use the docs for and_then to understand the expected return value?
The docs for and_then state that:
fn and_then<F, B>(self, f: F) -> AndThen<Self, B, F> where
F: FnOnce(Self::Item) -> B,
B: IntoFuture<Error = Self::Error>,
Self: Sized,
This means that:
Your closure must accept an argument of type Self::Item and return some type B
The type B returned by your closure must be convertible into a future.
And if that future returns an error, then that error must have type Self::Error.
Moreover, if you look at the doc for IntoFuture, you will see that it is implemented for Result, so it works for Ok(()), but that it is not implemented for (), so it doesn't work if your closure returns nothing.
Basically the closure you pass to and_then has the wrong type. It expects:
F: FnOnce(Self::Item) -> B
But you give it a closure of unit type, i.e. returns no value. Hence the error.
That said, the rustc error message isn't optimal here. It would be much better if it reads:
let client = TcpStream::connect(&addr).and_then(|stream| {
println!("created stream");
// error: mismatched types: expected `IntoFuture` but found `()`
});
The rust-lang project has this ticket to track the progress on said diagnostics issue.

How to implement a trait for a function

I have the following code
let hazard_predicate = predicate::function(|x: &String| {
if (x == "You got it right!" || x == "You got it wrong!") {
return true;
} else {
return false;
}
});
let mut cmd = Command::cargo_bin("rust-starter").expect("Calling binary failed");
cmd.arg("hazard").assert().stdout(hazard_predicate);
It doesn't compile. It complains that hazard_predicate doesn't implement a particular trait.
Here is the error message
error[E0277]: the trait bound
`predicates::function::FnPredicate<[closure#core/tests/test_cli.rs:31:48: 37:6], std::string::String>: assert_cmd::assert::IntoOutputPredicate<_>` is not satisfied
--> core/tests/test_cli.rs:39:32
|
39 | cmd.arg("hazard").assert().stdout(hazard_predicate);
| ^^^^^^ the trait `assert_cmd::assert::IntoOutputPredicate<_>` is not implemented for `predicates::function::FnPredicate<[closure#core/tests/test_cli.rs:31:48: 37:6], std::string::String>`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0277`.
So How do I implement that trait for my predicate function?
Let's look at the documentation for the types and traits in question. Usually the required traits are implemented automatically on all the types where it is possible, and, in fact, if the type in question is not your own, the trait has to be implemented by the library. So, first of all we check the assert_cmd docs to see what types can be used here.
There are two implementations which can be of interest for us:
impl<P> IntoOutputPredicate<StrOutputPredicate<P>> for P
where
P: Predicate<str>
impl<P> IntoOutputPredicate<P> for P
where
P: Predicate<[u8]>
Let's see now, what is the Predicate. This ends in the predicates-core crate, so it seems that at least some of the items from the predicates crate (based on this core) will be possible to use.
Now, let's try the other way round - look through the docs for predicate::function:
pub fn function<F, T>(function: F) -> FnPredicate<F, T>
where
F: Fn(&T) -> bool,
T: ?Sized,
Well then, we've got the type FnPredicate mentioned in the error message, so what traits are implemented by it?
impl<F, T> Predicate<T> for FnPredicate<F, T>
where
F: Fn(&T) -> bool,
T: ?Sized,
Here it is! You've passed a closure taking &String, so the T in this definition is inferred to be String, i.e. the implemented trait is Predicate<String>.
Now, if you recall the first part, you'll see that there is no Predicate<String> there in implementations!
How to resolve this?
I see two possibilities, as for now:
You can use the second implementation and make your predicate take reference to a byte slice &[u8]. I can't test it with the library itself, since it isn't on the playground, but if I make this change just in closure, I immediately get the error:
error[E0277]: can't compare `[u8]` with `str`
--> src/lib.rs:3:15
|
3 | if (x == "You got it right!" || x == "You got it wrong!") {
| ^^ no implementation for `[u8] == str`
|
= help: the trait `std::cmp::PartialEq<str>` is not implemented for `[u8]`
= note: required because of the requirements on the impl of `std::cmp::PartialEq<&str>` for `&[u8]`
Fortunately, this is fairly easily fixed by changing string literals to byte strings (playground):
let _ = |x: &[u8]| {
x == b"You got it right!" || x == b"You got it wrong!"
};
Note that I also took advantage of Clippy hints to simplify the code in question (on playground it is under Tools button on the right side).
Now, if you pass this closure into predicate::function, all should work fine.
Another way is to use the first implementation - you can see that Predicate<str>, i.e. function predicate receiving &str, is also supported, although in a bit more complex way. But for now this doesn't seem to be a problem, since the trait is implemented anyway - that's just one internal layer of indirection, but this is not your problem (assert_cmd crate should handle this itself). This code, in particular, compiles well:
use assert_cmd::{assert::OutputAssertExt, cargo::CommandCargoExt};
use predicates::prelude::*;
use std::process::Command;
fn main() {
let hazard_predicate =
predicate::function(|x: &str| x == "You got it right!" || x == "You got it wrong!");
let mut cmd = Command::cargo_bin("rust-starter").expect("Calling binary failed");
cmd.arg("hazard").assert().stdout(hazard_predicate);
}
Side note
There is a long-standing question here describing why this is bad to have the functions require &String (or &Vec, or &Box - a reference to the owned container, it is). In short - you can replace &String by &str, and this will not be a restriction. Of course, library authors know that too and usually force you to have the most general way, where you have to work with the least indirection possible.

What allows the implicit conversion from a struct to its reference when calling a method? [duplicate]

This question already has answers here:
What are Rust's exact auto-dereferencing rules?
(4 answers)
Closed 4 years ago.
Which rule makes the following code work?
struct Dummy(i32);
impl Dummy {
pub fn borrow(&self) {
println!("{}", self.0);
}
}
fn main() {
let d = Dummy(1);
(&d).borrow();
d.borrow();
}
I expect d.borrow() won't work as it passes in self which doesn't match the method signature borrow(&self).
From the reference :
A method call consists of an expression (the receiver) followed by a
single dot, an expression path segment, and a parenthesized
expression-list
When looking up a method call, the receiver may be automatically
dereferenced or borrowed in order to call a method.
Note:
Automatic dereference or borrow is only valid for the receiver. If there is no expression as receiver it will not work. Compiler will expect the borrowed type.
Example:
fn main() {
let d = Dummy(1);
let borrowed = Dummy::borrow(d);
}
Compiler will show an error:
error[E0308]: mismatched types
--> src/main.rs:12:34
|
12 | let borrowed = Dummy::borrow(d);
| ^
| |
| expected &Dummy, found struct `Dummy`
| help: consider borrowing here: `&d`
|
= note: expected type `&Dummy`
found type `Dummy`

Borrow checker and function arguments in Rust, correct or over zealous? [duplicate]

This question already has an answer here:
Cannot borrow as immutable because it is also borrowed as mutable in function arguments
(1 answer)
Closed 4 years ago.
When a mutable argument is passed as a function argument, the borrow checker doesn't allow this to be used to construct other arguments, even when those arguments clone values without holding a reference.
While assigning variables outside the function is always an option1, logically this seems over zealous and something the borrow checker could take into account.
Is this working as intended or something that should be resolved?
#[derive(Debug)]
struct SomeTest {
pub some_value: f64,
pub some_other: i64,
}
fn some_fn(var: &mut SomeTest, other: i64) {
println!("{:?}, {}", var, other);
}
fn main() {
let mut v = SomeTest { some_value: 1.0, some_other: 2 };
some_fn(&mut v, v.some_other + 1);
// However this works!
/*
{
let x = v.some_other + 1;
some_fn(&mut v, x);
}
*/
}
Gives this error:
--> src/main.rs:14:21
|
14 | some_fn(&mut v, v.some_other + 1);
| - ^^^^^^^^^^^^ use of borrowed `v`
| |
| borrow of `v` occurs here
See: playpen.
[1]: Even though one-off assignments do sometimes improve readability, being forced to use them for arguments encourages use of scopes to avoid single use variables polluting the name-space, causing function calls that would otherwise be one line - being enclosed in braces and defining variables... I'd like to avoid this if possible especially when the requirement seems like something the borrow checker could support.
This is an artifact of the current implementation of the borrow checker. It is a well known limitation, dating back to at least 2013, and no one is overjoyed by it.
Is this working as intended
Yes.
something that should be resolved?
Yes.
The magic keywords are "non-lexical lifetimes". Right now, lifetimes are lexical - they correspond to the blocks of source that we type. Ideally, foo.method(foo.mutable_method()) would see that the borrow ends "inside the parenthesis", but for a myriad of reasons, it is tied to the entire statement.
For tons of further information see RFC issue 811 and everything linked from there.

Resources