# Wondering if there is a better way to handle panic!

In the following code, 'point' is returned, but to avoid the 'possibly not initialized error' I initialized it to a ridiculous value and then invoked panic! with a bool. I don't want the caller of this function to handle an empty point since it should never be empty, so I use panic! in hopes of satisfying the compiler.

Is there a better way to implement panic here so I don't need the (-1,-1) initialization?

This function takes an x, y mouse coordinate and checks if it falls within any of 64 rectangles:

``````fn get_clicked_square_id(x: f64, y: f64, scalar: usize) -> (i32, i32) {
let mut counter = 0;
let x2 = scalar;
let y2 = scalar;
let x = x as usize;
let y = y as usize;
let mut point = (-1, -1);
let mut square_not_found = true;

for x1 in (0..456).step_by(scalar) {
for y1 in (0..456).step_by(scalar) {
counter += 1;
println!("value of iterator is: {}> ({}, {})", counter, x1, y1);
if x1 < x && x < x2 && y1 < y && y < y2 {
point = (x1 as i32, y1 as i32);
square_not_found = false;
break;
}
}
}
if square_not_found {
}else {
point
}
}
``````
1 Like

The easy thing to do would be just `return (x1 as i32, y1 as i32);` when you find the point. Then just panic if you ever leave the loop at the bottom.

``````fn get_clicked_square_id(x: f64, y: f64, scalar: usize) -> (i32, i32) {
let mut counter = 0;
let x2 = scalar;
let y2 = scalar;
let x = x as usize;
let y = y as usize;

for x1 in (0..456).step_by(scalar) {
for y1 in (0..456).step_by(scalar) {
counter += 1;
println!("value of iterator is: {}> ({}, {})", counter, x1, y1);
if x1 < x && x < x2 && y1 < y && y < y2 {
return (x1 as i32, y1 as i32);
}
}
}
}
``````
3 Likes

I'll also note that the loops here seem really inefficient. It seems like you're just computing the smallest multiples of `scalar` that are less than `x` and `y`. You should be able to just divide `x` by `scalar`, round away any fractional part, and then multiply by `scalar` to get the correct value for `x1`. And again for `y1`.

``````fn get_clicked_square_id(x: f64, y: f64, scalar: usize) -> (i32, i32) {
if x > 456.0 || y > 456.0 { panic!("No Square ID") }
let scalar = scalar as f64;
(
(x.div_euclid(scalar) * scalar) as i32,
(y.div_euclid(scalar) * scalar) as i32,
)
}
``````
2 Likes

Why would you make this a panicking function instead of making it a fallible function that returns a Result<Point,Error>? This seems like trying to use panic in an entirely inappropriate way that runs counter to proper, idiomatic Rust. Were I code reviewing it in a work environment, I would reject it.

2 Likes

And if the input values of function should never trigger a panic due to the logic of surrounding code (i.e. if the panic would really be a bug), the more semantically meaningful might be to use `unreachable!`.

@gbutler69 Would you please show me what the code look like doing it the idiomatic way? It would be truly educational. A fine example of right and wrong.

EDIT: Improved version using a single range instead of literally twice if the "if" of the match arm.

I'd recommend something similar to what @skysch posted above, but, changing it to use Option instead of Panic. Something like this (Playground Link):

1 Like

@gbutler69
Wow! That is amazing code! Thank you so much!

2 Likes

Thank you so very much for your great help on efficiency...very good.

2 Likes

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.