Reputation: 2936
Here is my struct:
pub(crate) struct Graph {
outbound: HashMap<isize, Vec<isize>>,
inbound: HashMap<isize, Vec<isize>>,
edges: Vec<Edge>,
}
and what I tried:
fn get_edge_mut(&mut self, from_id: isize, to_id: isize) -> Result<&mut Edge, GraphError> {
let mut edges = self
.edges
.iter_mut()
.filter(|edge| edge.get_from() == from_id && edge.get_to() == to_id)
.collect::<Vec<_>>();
match edges.len() {
0 => Err(GraphError(format!(
"edge from {} to {} does not exist",
from_id, to_id
))),
1 => Ok(edges[0]),
_ => panic!(
"wrong graph structure - edge from {} to {} exists multiple times",
from_id, to_id
),
}
}
The problem is here: Ok(edges[0])
It fails with cannot return value referencing local variable "edges"
I understand that edges
is owned by the current function and I cannot return a reference to it because it goes out of scope, but what would be a better way to return a mutable reference to an element in the "edges" Vec (of the struct) based on some condition?
Upvotes: 1
Views: 737
Reputation: 36
I would suggest using:
fn get_edge_mut(&mut self, from_id: isize, to_id: isize) -> Result<&mut Edge, GraphError> {
self.edges.iter_mut()
.find(|edge| edge.get_from() == from_id && edge.get_to() == to_id)
.ok_or(GraphError(format!("edge from {} to {} does not exist", from_id, to_id)))
}
It skips your "wrong graph structure check", but if it's needed, you could go with
fn get_edge_mut(&mut self, from_id: isize, to_id: isize) -> Result<&mut Edge, GraphError> {
let mut edges_matching = self.edges.iter_mut()
.filter(|edge| edge.get_from() == from_id && edge.get_to() == to_id);
let edge = edges_matching.next()
.ok_or(GraphError(format!("edge from {} to {} does not exist", from_id, to_id)));
assert_eq!(edges_matching.count(), 0,
"wrong graph structure - edge from {} to {} exists multiple times",
from_id, to_id);
edge
}
It seems like the issue might stem from edges[0]
ultimately calling SliceIndex::index
, which basically returns an Option<&&mut Edge>
, where that first &
is actually a reference to the current function.
trendcl is right, edges.pop()
works too.
Upvotes: 2