A snippet from my chess program:
I have a nullable eval variable which is only filled if not is_check.
We know eval is filled when is_check is false.
Is using eval.? the best way to code it?
Does it have any performance implications to read eval.? instead of a raw int (in release mode)?
const eval: ?i32 = if (is_check) null else evaluate(); // correct edited example
// const eval: i32 = if (!is_check) null else evaluate(); // wrong first example
// ...
// lots of code in between.
// ...
if (!is_check and some_other_conditions) {
if (eval.? == 42) { do something }
}
if (!is_check and more_conditions) {
if (eval.? == 43) { do something }
}
Yes, that’s the intended use-case for foo.?.
From the language reference:
Equivalent to:
a orelse unreachable
(so it allows the compiler to optimize based on your guarantee that the value will never be null at that point)
9 Likes
I’d also consider this:
const eval: i32 = if (!is_check) undefined else evaluate();
// ...
// lots of code in between.
// ...
if (!is_check and some_other_conditions) {
if (eval == 42) { do something }
}
if (!is_check and more_conditions) {
if (eval == 43) { do something }
}
That way you don’t have to bother with unwrapping eval everywhere you need it and still get a runtime crash in safe modes if you accidentaly try to access eval anywhere you shouldn’t because it’ll be undefined.
3 Likes
True for a local as in the example.
However these evals are stored in a big stack of nodes and reused so I stick with nullable.
(To explain: when going deeper into the search-tree i compare current evals with previous evals (if available) to check improvement)
1 Like
Not to nitpick, but is your first line backwards? Feels like you want to set eval to null when is_check.
2 Likes
No it’d have to be ?i32 in the original snippet but i32 can be undefined (just like any other value)
I am failing to crash my program. What am I doing wrong?
var runtime_known = false;
runtime_known = !runtime_known;
const foo: i32 = if (runtime_known) undefined else 69;
if (foo == 42) {
std.debug.print("==42: {}\n", .{ foo });
}
if (foo != 43) {
std.debug.print("!=43: {}\n", .{ foo });
}
Output:
!=43: 1
It does not crash. It just uses garbage value.
P.S. I wonder why the garbage is not 0xAA pattern.
1 Like
Yeah sorry you’re right. That would be #211.
I also find it weird that the value is not 0xAA though, it’s 0 for me. This:
var foo: i32 = undefined;
if (!runtime_known) foo = 69;
does set foo to 0xAA so it might be a bug that your version doesn’t.
1 Like