Why does the closure return different result

fn main() {
    let n = number_to_vec(35231);
    let n2 = number_to_vec2(35231);
    println!("{:?}", n);
    println!("{:?}", n2);
}

fn number_to_vec(n: u64) -> Vec<u8> {
    n.to_string()
        .chars()
        .map(|c| c.to_digit(10).unwrap() as u8)
        .rev()
        .collect()
}

fn number_to_vec2(n: u64) -> Vec<u8> {
    n.to_string()
        .chars()
        .map(|c| {
            c.to_digit(10).unwrap();
            c as u8
        })
        .rev()
        .collect()
}

and it returns

[1, 3, 2, 5, 3]
[49, 51, 50, 53, 51]

Can someone explain why the closures in map behave differently please

Thank you in advance

Does not change c, it returns a digit, assuming it does not panic, created from c.
You are not assigning that returned digit to anything so it gets lost.
You then return the c, which has never been changed.

You would need:

let c = c.to_digit(10).unwrap();

See here: https://doc.rust-lang.org/std/primitive.char.html#method.to_digit

1 Like

Hmm....

Actually I find it a bit odd that Rust silently discards the result of

    c.to_digit(10).unwrap();

No error or warning from the compiler or clippy.

There's no warning because the return value is not marked #[must_use]. The compiler doesn't know whether the function has side effects, so it can't warn on things without them, and even if it did, ours does have side effects: panics.

Hmm... I'm not sure I follow that argument. I don't see what side effects has got to do with it?

There is a value being created by the return, which is casually dropped at the call site without warning. Surely this deserves a warning as much as declaring a variable that is never used?

This has caught me out a couple of times and I have seen others here trip over it.

If people think to_digit result should be used, someone have to file a PR to mark it as must_use.

@ZiCog Should you also get a warning for ignoring the return value of Vec::remove? You might call it just for its side-effect.

1 Like

In this case it wouldn't change anything due to the unwrap.

Hmm...thinks...

If you want that, you can turn it on:

https://doc.rust-lang.org/rustc/lints/listing/allowed-by-default.html#unused-results

Because moves are cheap, though, it's not uncommon for an API to return something because why not, even if the caller will often not use it. So this lint tends to be rather high on false positives.

1 Like

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.