tact icon indicating copy to clipboard operation
tact copied to clipboard

Unboxing(unwrapping) of optionals

Open 0kenx opened this issue 1 year ago • 5 comments

The current semantics of options is Tact is quite lengthy. It would be nice if it could be improved.

Reference: https://doc.rust-lang.org/std/option/enum.Option.html

To begin with, having unwrap_or would be very nice.

let a: Int?;
let b: Int = 5;

// Current semantics
if (a != null) {
    b = b + a!!;
} else {
    b = b + 3;
}

// with `unwrap_or`
b = b + a.unwrap_or(3);

0kenx avatar Apr 15 '24 16:04 0kenx

I tried to solve it with a library:

extends inline fun unwrap_or(self: Int?, default: Int): Int {
    if (self == null) {
        return default;
    }
    return self!!;
}

but the compiler says Extend functions must have a non-optional type as the first argument 😂

0kenx avatar Apr 15 '24 16:04 0kenx

This works though:

inline fun unwrap_or(opt: Int?, default: Int): Int {
    if (opt == null) {
        return default;
    }
    return opt!!;
}

b = b + unwrap_or(a, 3);

but then functions can't be overloaded so other types can't be unwrapped this way.

0kenx avatar Apr 15 '24 16:04 0kenx

I have a slightly awkward solution:

extends inline fun or_unwrap(self: Int, opt: Int?): Int {
    if (opt == null) {
        return self;
    }
    return opt!!;
}

b = b + 3.or_unwrap(a);

0kenx avatar Apr 15 '24 16:04 0kenx

This is a nice suggestion! I was thinking of introducing new syntax to do that: the so-called nullish coalescing operator ?? (and we can support the nullish coalescent assignment operator ??= too).

Incidentally, we might add the optional chaining operator ?..

anton-trunov avatar Apr 15 '24 22:04 anton-trunov

So your example will become

let a: Int?;
let b: Int = 5;

b += a ?? 3;

anton-trunov avatar Apr 15 '24 22:04 anton-trunov