I want to convert a value from {integer}
to f32
:
struct Vector3 {
pub x: f32,
pub y: f32,
pub z: f32,
}
for x in -5..5 {
for y in -5..5 {
for z in -5..5 {
let foo: Vector3 = Vector3 { x: x, y: y, z: z };
// do stuff with foo
}
}
}
The compiler chokes on this with a type mismatch error (expecting f32
but getting {integer}
). Unfortunately I can not simply change Vector3
. I'm feeding a C-API with this.
Is there any easy and concise way I can convert x
, y
and z
from {integer}
to f32
?
I guess there is no builtin conversion from i32
or {integer}
to f32
because it could be lossy in certain situations. However, in my case the range I'm using is so small that this wouldn't be an issue. So I would like to tell the compiler to convert the value anyways.
Interestingly, the following works:
for x in -5..5 {
let tmp: i32 = x;
let foo: f32 = tmp as f32;
}
I'm using a lot more that just one foo and one x so this turns hideous really fast.
Also, this works:
for x in -5i32..5i32 {
let foo: f32 = x as f32;
// do stuff with foo here
}
But with my usecase this turns into:
for x in -5i32..5i32 {
for y in -5i32..5i32 {
for z in -5i32..5i32 {
let foo: Vector3 = Vector3 {
x: x as f32,
y: y as f32,
z: z as f32,
};
// do stuff with foo
}
}
}
Which I think is pretty unreadable and an unreasonable amount of cruft for a simple conversion.
What am I missing here?
I'm not sure why you felt the need to specify the i32
s when using as
, since this works fine (playground):
for x in -5..5 {
for y in -5..5 {
for z in -5..5 {
let foo = Vector3 { // no need to specify the type of foo
x: x as f32,
y: y as f32,
z: z as f32,
};
// etc.
}
}
}
As Klitos Kyriacou's answer observes, there is no such type as {integer}
; the compiler gives that error message because it couldn't infer a concrete type for x
. It doesn't actually matter, because there are no implicit conversions from integer types to floating-point types in Rust, or from integer types to other integer types, for that matter. In fact, Rust is quite short on implicit conversions of any sort (the most notable exception being Deref
coercions).
Casting the type with as
permits the compiler to reconcile the type mismatch, and it will eventually fill in {integer}
with i32
(unconstrained integer literals always default to i32
, not that the concrete type matters in this case).
Another option you may prefer, especially if you use x
, y
and z
for other purposes in the loop, is to shadow them with f32
versions instead of creating new names:
for x in -5..5 {
let x = x as f32;
for y in -5..5 {
let y = y as f32;
for z in -5..5 {
let z = z as f32;
let foo = Vector3 { x, y, z };
// etc.
}
}
}
(You don't have to write x: x, y: y, z: z
-- Rust does the right thing when the variable name is the same as the struct member name.)
Another option (last one, I promise) is to convert the iterators instead using map
:
for x in (-5..5).map(|x| x as f32) {
for y in (-5..5).map(|y| y as f32) {
for z in (-5..5).map(|z| z as f32) {
let foo = Vector3 { x, y, z };
// etc.
}
}
}
However it is a little more dense and may be harder to read than the previous version.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With