s1n7ax
s1n7ax

Reputation: 3069

cannot return reference to temporary value error in iterator reduce

I'm trying to calculate the total of elements using a reducer.

// map: Map<(i8, i8), u8>
// row: Vec<u8>

row.push(
    *map
    .values()
    .reduce(|acc, curr| &(acc + curr))
    .unwrap_or(&0u8)
);

I get following compile error.

error[E0515]: cannot return reference to temporary value
   --> src/main.rs:173:46
    |
173 |                         .reduce(|acc, curr| &(acc + curr))
    |                                              ^-------------
    |                                              ||
    |                                              |temporary value created here
    |                                              returns a reference to data owned by the current function

Here, reduce is expecting &u8 but it can not be changed to a reference because it is a temporary value. How to resolve this?

Upvotes: 0

Views: 698

Answers (1)

Denys S&#233;guret
Denys S&#233;guret

Reputation: 382150

A generic solution would be to map the elements from reference to concrete values, which is possible and cheap here:

row.push(
    map
        .values()
        .copied() // shortcut for .map(|&v| v)
        .reduce(|acc, curr| (acc + curr))
        .unwrap_or(0)
);

But a cleaner solution would be to avoid reduce, which builds a result the type of the elements it receives, but to use fold:

row.push(
    map
        .values()
        .fold(0, |acc, &curr| (acc + curr))
);

This also lets you avoid the unwrap_or by using the initial value when the map is empty.

Until now, I was assuming you have a more complex computation than the one you show. If it's not the case, then just use sum:

row.push(map.values().sum());

Upvotes: 5

Related Questions