3 ms·
Why not explicit Option.map (fun l -> Array.nth l n) your_optional_list And why treat something nullable as a special entity when it's just a container? A
by ernst_klim 7y ago
Why not explicit
Option.map (fun l -> Array.nth l n) your_optional_list
And why treat something nullable as a special entity when it's just a container?
And why would anybody want a nullable collection or a special syntax for 'em, when any collection is already nullable, and an empty list or array is basically the same thing as None/Null?
- the_duke 7y agoFor 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.
- masklinn 7y agoBecause most of these languages started from ubiquitous nullability and had to work from there. Also these safe dereference operators are not Option.map, they act as both Option.map and Option.flatMap "for convenience". Finally they tend to be method-oriented, which creates namespacing issues & is problematic when their null isn't a dedicated singleton (à la smalltalk / ruby / python).
- TheSoftwareGuy 7y agoI'm pretty sure Python's `None` is a singleton object
- masklinn 7y agoYes? I'm mentioning it as an example of "singleton object" nulls. As opposed to non-object nulls like Java or JS's.
- TheSoftwareGuy 7y agoAhh, whoops. I misread your comment. I thought you were saying the opposite
- masklinn 7y agoYeah I can see where my wording would be unclear, sorry about that.