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 {
panic!("Square ID not found");
}else {
point
}
}
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);
}
}
}
panic!("Square ID not found");
}
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,
)
}
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.
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.