Any way to make this a single expression function?

I'm working on my first Rust program(!) and have the following two functions:

fn d8() -> u8 {
    rand::thread_rng().gen_range(1..8)
}

fn d8_dice(num: usize) -> Vec<u8> {
    let v: Vec<u8> = std::iter::repeat_with(|| d8()).take(num).collect::<Vec<_>>();
    v
}

The above compiles but I'm wondering if there's a way to make one of the functions, d8_dice(), a single expression function? (i.e. one line instead of two)

I tried:

std::iter::repeat_with(|| d8()).take(num).collect_vec();

but received the error "method not found in std::iter::Take<RepeatWith<[closure@src/main.rs:19:28: 19:35]>>"

I've also tried:

std::iter::repeat_with(|| d8()).take(num).collect::<Vec<_>>()

which highlighted an error on the Vec return type of the function saying:
"expected struct Vec, found ()"

1 Like

In the last thing you tried, did you happen to leave the semicolon at the end of the line? What you wrote should work

Your first attempt is probably that you were trying to use a method from the itertools crate which would require use itertools::Itertools to be able to use the methods from that trait.

Note:
In the future include the full error message and not just a snippet. It makes it much easier for people on this forum to understand the issue that you’re running into.

4 Likes

Ah - you're right. I had included a semi-colon and it even mentions the semi-colon in the error message. : /

And I'll include full error messages next time - thank you.

For the record, this works:

fn d8_dice(num: usize) -> Vec<u8> {
    std::iter::repeat_with(|| d8()).take(num).collect::<Vec<_>>();
}
1 Like

Didn't check it but ai'm pretty sure you can also omit the tpye specification after collect.

i.e. call collect() without the turbofish.
rustc should be able to infer Vec from the return type

2 Likes

And since d8 is already a fn() -> u8, you can even skip the closure:

    std::iter::repeat_with(d8).take(num).collect()

Also @rwat unless I'm mistaken you want an inclusive range in the definition of d8, so 1..=8 instead of 1..8—the latter doesn't include the right endpoint 8, so it would give you a d7 instead!

6 Likes

I swear I had tried that but compiling must have gotten hung up on another error I confused the two. It does indeed run that way - thanks.

Good catch! (x2)

1 Like

This is likely because you put a semicolon at the end. It isn't present in the code sample I quoted, but it is present in your OP.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.