Description
So based on what I understand about cppfront and Cpp2 as it stands, there's a union
keyword that effectively infers / uses an std::variant
wherever it's used, and it's invisible to the end-user-- I think that's great and a good choice.
However, it looks like when using optionals, you still have to declare them with the original C++ syntax… I think there's a missed opportunity here that has been well treaded in C# (via "Nullables"), JavaScript / TypeScript, and Swift.
If you look at Swift's Optionals, we have declaration like this:
var a: Int // int type
var b: Int? // Optional Int type
var c: Dog? // Optional class type
And accessing values are like this (the last two lines are called "optional chaining" in most languages):
print(b ?? 7) // prints the value of "b" if non-optional, otherwise prints "7"
let h = c?.height // accessing member variables from an optional class
c?.bark() // calls "bark" method on c if c is not null, does nothing otherwise
d?.data?.dog?.bark() // Similar to above, but you have a hierarchy of optional members
Swift also provides the concept of "unwrapping" an optional; I don't want to muck up the above with this, but it would be negligent of me not to mention it:
if var c = c { // try to "unwrap" the optional into a non-optional type
c.bark() // optional was successfully "unwrapped", c is now a non-optional type, and "bark" method can be called
}
In my opinion, Swift is a very "Optional first" type of language, meaning you often want to see if something "can be" an optional before you even consider a non-optional type, and I think this kind of thinking might also benefit C++… and maybe a good vector to do this would be through Cpp2 / cppfront.
If for nothing else the syntax sugar of using a declaration of type?
to imply std::optional<type>
and providing support for optional chaining (the c?.bark()
instead of writing if (*c) { c->bark(); }
would be tremendous in my opinion.
One other thing to consider about Optionals in general (as well as how they currently stand in Cpp2), is that the absence of a value is typically represented as null
or nil
or (in the case of C++)nullopt
. I do agree (and totally support) the idea of eliminating NULL
in Cpp2, but I think they track you'll find here is similar to Swift, where nil
(their version of null
) only exists to support the "absense of a value in an optional."
Whether or not you wanted to go down a similar "unwrap" path would be up to you (and dependent on if you even wanted to go down this "syntax sugar" idea or not), but I think there's lots to learn from other languages that do optionals that C++ can't do without considerable effort that are worth considering here.
tl;dr:
- Consider treating optional types like you treat
union
->std::variant
- Learn from other languages (C#, TypeScript, Swift), and provide syntax sugar:
- For declaration:
b: Int?
- For chaining:
c?.bark()
- For defaults:
b ?? 5
- For declaration:
- Consider having a "null" but only for optional types (
nullopt_t
is okay, but maybe there's a better long-term naming solution) - Consider advanced ideas like optional unwrapping from Swift