Shorter smarter nullable code

Small question.
I have one var m which is computed when needed.
And computing m must be never or once.
Can we write this smarter / shorter in some nice oneliner?

var m: ?i32 = null;

// ...
// earlier code maybe computiing m, maybe not
// ...

if (m == null) {
    m = compute_m(...);
}
if (m.? <= 300) {
    // code
}

there used to be std.once which did this. it was removed with the move to std.Io iirc, but you could model your thing on it, with the knowledge that it was removed for good reason

// …
// earlier code maybe computiing m, maybe not
// …

Let this work be some function foo that returns the result of compute_m() or null otherwise.

var m: i32 = foo(&loc_var1, &local_var2) orelse compute_m(...);
2 Likes
fn compute() i32 {
    return 2332;
}

fn ensureValue(val: *?i32) i32 {
    val.* = compute();
    return val.*.?;
}

pub fn main() !void {
    var m: ?i32 = null;

    const value = m orelse ensureValue(&m);
    if (value != 2332) @panic("wrong value!");
}

But I agree with @gavin-mcdiarmid that restructuring the code is likely better.

2 Likes

Ok. thanks. Yes something like that entered my mind. But it still feels hm.. how do i say that. clunky?
Whatever solution there is, it involves extra variables / functions.
I think I will let it be the way it is.
here

edit: altough looking again… i think i can indeed change it logically to calculate once when needed.

Consider also:

var m: i32 = blk: {
    var n: ?i32 = null;
    // Do some work
    break :blk n orelse compute_m(...);
}
1 Like

I believe the following qualifies as a nice oneliner:

var m: ?i32 = null;

// some work...

// if we want to update m for later use
m = m orelse compute_m();
if (m.? <= 300) {
    // ...
}

// if we don't care for updating it
if (m orelse compute_m() <= 300) {
    // ...
}
1 Like

Another choice would be label blocks, depending on how much code you need to run.

fn foo() ?i32 {
    return null;
}

fn example() void {
    var m: i32 = foo() orelse default: {
        // Compute
        break :default 5;
    };
    
    _ = &m;
    
    if (m <= 300) {
        // code
    }
}