tact-lang / tact

Tact compiler main repository
https://tact-lang.org
MIT License
373 stars 104 forks source link

Unboxing(unwrapping) of optionals #259

Open 0kenx opened 5 months ago

0kenx commented 5 months ago

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 commented 5 months ago

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 commented 5 months ago

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 commented 5 months ago

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);
anton-trunov commented 5 months ago

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 commented 5 months ago

So your example will become

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

b += a ?? 3;