3 ms·
For Option types to work well and not be an awkward footgun (like C++ std::optional), you also need sum types and pattern matching. While Dart should gain thos
by the_duke 7y ago
For Option types to work well and not be an awkward footgun (like C++ std::optional), you also need sum types and pattern matching.
While Dart should gain those, that's a much more invasive language change I reckon.
- masklinn 7y ago> For Option types to work well and not be an awkward footgun (like C++ std::optional), you also need sum types and pattern matching. It works fine if you don't have these, though there are more tradeoffs (less convenience / compile-time safety). C++'s std::optional is footguny because it is not a type-safety feature, it's an optimisation feature (a stack allocated pointer, hence it having "a pointer interface").
- nybble41 7y ago> For Option types to work well and not be an awkward footgun (like C++ std::optional), you also need sum types and pattern matching. Which you can derive from lexical closures (which Dart has) using Church encoding: typedef Optional<T> = R Function<R>(R, R Function(T)); Optional<T> None<T>() { return <R>(R none, R some(T x)) => none; } Optional<T> Some<T>(T x) { return <R>(R none, R some(T x)) => some(x); } Optional<B> MapOptional<A,B>(B f(A), Optional<A> option) { return <R>(R none, R some(B x)) => option(none, (a) => some(f(a))); } String OptionalString<T>(Optional<T> option) { return option('None()', (x) => 'Some(${x.toString()})'); } void main() { Optional<num> opt1 = None(); Optional<num> opt2 = Some(4); print('opt1: ${OptionalString(opt1)}'); print('opt2: ${OptionalString(opt2)}'); Optional<num> opt3 = MapOptional((x) => 2*x, opt2); print('2*opt2: ${OptionalString(opt3)}'); } Optional<T> is a sum type, and you pattern match on it by calling the function and providing expressions for the None and Some cases as parameters. There may be some implementation limits... I managed to crash the compiler at https://dartpad.dartlang.org/ https://dartpad.dartlang.org/ with the first version which had the expression for opt3 inlined into the call to OptionalString(). Declaring it as a separate variable worked around the issue. It's also apparently disallowed to nest generic function types, so you can't have Optional<Optional<T>>; this might be circumvented by wrapping the function type in a class.