Ceylon and Kotlin both came out in 2011 and neither was popular. I was hoping Ceylon would come out on top as giving the most without incurring the complexity of Scala (which can co-exist for other uses/users).
From Ceylon Wikipedia[0]
> Null safety
> Union and intersection types are used to provide null safety. The top type of the Ceylon type hierarchy is the class Anything, which has two subclasses: Object, the superclass of all normal classes and all interfaces, and Null, with the only instance null. Since Object and Null are disjoint types, most regular types like Integer or List<String> are not nullable; a nullable type is the union Integer|Null, abbreviated Integer?.
So not only do we get null safety, we get both intersection and union types. The emphasis on immutability is also a great selling feature, but perhaps that limited its interoperability with Java collections and adoption.
Is there a language for the JVM with union types that's gaining any popularity? [Edit: Scala 3+ any others?]
TypeScript is a bit of an outlier in this respect of being widely adopted with this particularly useful feature. Null-safety is basically a corner case of union types.
1. Languages generally release with this (ie Swift, PHP), rather than add it later
2. There is a risk that it won't be accepted because of bad assumptions that can either be technical or social. ie This feature exists and is criticized in other languages like PHP
3. There is no proof that it's any more important than any other feature being discussed.
> Languages generally release with this (ie Swift, PHP), rather than add it later
PHP did not get nullable types until 7.1 [0]. Function arguments (only) supported it in PHP 5 with the syntax `function(stdClass $arg = null)` but I would hardly call that nullable type support.
That requires protected memory and zero isn’t unique in that. The OS could make many more addresses special in that respect.
On most (¿all?) OSes it also won’t work if you make your structure large enough, and try to access a field at an offset (let’s say your OS makes the first 4kB of memory unaccessible by user code, you declare p as a pointer to an array of a million integers, but don’t initialize it and then access p[999999])
It also is an implementation detail. A compiler could compile something like Either[Foo,Null] (with Foo a type and Null a value or a type that’s guaranteed to have only one instantiation) to either a pointer to a Foo or a null bit pattern.
Even better, an implementation _could_ hide the “it’s not a Foo” bit in any unused bit inside a Foo object (say inside padding, or in a byte storing an enumeration that has less than 256 values)
(aside: are there languages that represent Either[FooPtr,BarPtr] as a pointer-sized field holding either a pointer to a Foo or one plus a pointer to a Bar, using the fact that top bits of pointers to objects always are zero to discriminate between the two?)
I know. I was so happy to see real mode DOS go away.
> an implementation _could_ hide the “it’s not a Foo” bit in any unused bit
Yes, it could. But it requires extra instructions to check it. Null gets checked for free (no extra instructions or time) by the hardware. A seg fault isn't any more dangerous than an assert failure.
nullable pointers can take up the same amount of memory at runtime, vs optionals that can be nested, so you need to represent .none from .some(.none), which means you need at least another bit
Most languages including Java and C++ have “non-null” and “nullable” annotations. These types work exactly like Kotlin’s afaik, where if they’re not specified the compiler is flexible and assumes whatever works.
In fact Swift and C# seem to have this same feature or at least something similar. And I know C# added it way before Kotlin.
> Most languages including Java and C++ have “non-null” and “nullable” annotations
I thought this too until I gave them a try 6 or 7 years ago. And nope, it was just advisory in the Java case. May as well have been a comment. At best, it's shorthand for: throw a runtime exception if-and-only-if this method was called (directly) by Spring-or-similar.
What would a variable marked with Nullable mean anyway? That the other variables are not nullable?
From Ceylon Wikipedia[0]
> Null safety
> Union and intersection types are used to provide null safety. The top type of the Ceylon type hierarchy is the class Anything, which has two subclasses: Object, the superclass of all normal classes and all interfaces, and Null, with the only instance null. Since Object and Null are disjoint types, most regular types like Integer or List<String> are not nullable; a nullable type is the union Integer|Null, abbreviated Integer?.
So not only do we get null safety, we get both intersection and union types. The emphasis on immutability is also a great selling feature, but perhaps that limited its interoperability with Java collections and adoption.
[0] https://en.wikipedia.org/wiki/Ceylon_(programming_language)