I recently mentioned that RemObjects have placed their OS X native IDE – a.k.a. Fire – into public beta. I haven’t been using it myself (yet) but have been following developments in the RemObjects Talk forums with interest, and a new feature in the Elements 8.0 compiler (also part of the Fire beta) caught my eye this week.
The major new feature in the Elements 8.0 compiler is a new front end language. Called “Silver” in the Elements language stable. As Oxygene is to Pascal and Hydrogene is to C#, so Silver is to Swift, the new language from Apple.
But I already mentioned that, and this isn’t what caught my eye.
Rather it was mention of support for Not Nullable Types.
I am sure most people are already familiar with the concept of a nullable type, so only a brief recap is needed, to set the scene as it were.
When we declare a variable of a simple type with some underlying machine storage, then that type has a range of values, typically defined by that storage. So, with reference to some simple types:
Type | Range |
---|---|
Boolean | FALSE or TRUE |
Byte | 0 .. 255 |
Int16 | –32,768 .. 32,767 |
Int32 | –2,147,483,648 .. 2,147,483,647 |
Where things usually get a bit sticky is when dealing with storing or retrieving such values in a database where a table might allow a NULL to be stored for a value that the application code is storing in a variable of one of these or similar types.
What typically happens is that some convention is adopted whereby some specific value from the possible range of the underlying type is elected to represent NULL. Usually this is 0 or -1 or some other value that is not expected to otherwise occur in values of that type.
Obviously this can lead to mistakes, and in some cases isn’t even possible most obviously with Boolean values where there are no “unused” values available to represent NULL.
So the concept was devised of a type of value that could also “store” null, as well as the valid range of values. In COM this was dealt with by the catch-all Variant type with all the headaches and overhead that Variant types entailed.
But in .NET and elsewhere, “nullability” has been added to the fundamental types (or rather, has contrived to give the appearance of having done so):
Type | Range |
---|---|
Boolean? | FALSE or TRUE or NULL |
Byte? | 0 .. 255 or NULL |
Int16? | –32,768 .. 32,767 or NULL |
Int32? | –2,147,483,648 .. 2,147,483,647 or NULL |
In the table above I have used the C# style shorthand notation to indicate the nullable form of the corresponding types. In Oxygene the distinction when declaring such variables is (imho) helpfully less subtle:
void SomeMethod() { int parentID; // not nullable, auto-initialised to 0 int? childID; // nullable, null by default .. }
procedure SomeClass.SomeMethod; var parentID: Integer; // not nullable, auto-initialised to 0 childID: nullable Integer; // nullable, null by default begin .. end;
Needless to say, Oxygene provides excellent support both for declaring and working with Nullable Types.
This is all well and good for such value types.
The situation used to be that such values were not nullable and some mechanism to make them capable of “storing” null was needed, or at least useful. But for reference types the situation is slightly different.
Inverted Expectations
Reference types have effectively always been nullable since, by definition a reference is either a reference to something (not null) or it is not (null). An invalid reference, e.g. a “bad pointer” is still a reference to something, just not the right thing or even a valid thing.
Very often however, we have code that expects and requires that assigned references are provided and end up writing a lot of “gatekeeper” code to ensure that this is the case:
procedure Gramble(const aDoohickey: TDoohickey); begin if NOT Assigned(aDoohickey) then raise Exception.Create('A Doohickey is required for Grambling'); // Gramble the Doohickey ... end;
In Oxygene this can be made a deal more elegant with a method contract, taking the “noise” of the gatekeeping code out of the method body:
procedure Gramble(aDoohickey: Doohickey); require assigned(aDoohickey); begin // Gramble the Doohickey ... end;
But with Elements 8.0, RemObjects are going further and introducing Not Nullable references types. That is, the declaration of a variable dictates that it must hold a reference and cannot be null.
So if we replace the int “ID” variables in the previous example of declarations of nullable types, with object references, then we would need to make the parent explicitly not nullable and the child becomes implicitly nullable (being a reference type):
void SomeMethod() { Foo! parent = this.MyFoo; // not nullable, must be initialised Foo child; // nullable, initially null (not assigned) .. }
procedure SomeClass.SomeMethod; var parent: not nullable Foo = self.MyFoo; // must be initialised childID: Foo; // nullable, initially null (not assigned) begin .. end;
Obviously, as illustrated above, such values must be initialised at the time of declaration or, in the case of member variables, be initialised in all possible constructor paths.
Further Reading
There is more information about the feature in the Elements Wiki, though it should probably be borne in mind that this is a preview technology and so is potentially subject to change.
You are deluded because you live in a world of alternative software. Get a life, loser!
“You are deluded”
This seems harsh.
Unless it’s some kind of inside joke.
I may have been mistaken, but I interpreted this as sarcasm. 😉
Just a thought: wouldn’t it be nice if an explicit initialisation is not mandatory, and the no-arguments constructor of the type is used to create a new object in that case? It would cause a compiler error, or maybe a runtime exception, if no no-arguments constructor was available. I was thinking about ORM frameworks which do the same thing if they need a new object.
I believe that is how it works, yes.
Local variables must be initialised when declared.
Member variables may be initialised when declared, but if not must be initialised by all constructor paths. This would of course include any no parameter/default constructor, but also any other constructors.
Whether failure to do so results in a compiler error or a runtime exception, I have not yet tried (too busy making apps with the 7.x compiler to try the 8.x compiler as yet). I would have thought that not initialising a local variable would be a compiler error. Member variables without initialisation in one or more possible constructor paths might be harder to determine at compile time, but I wouldn’t rule it out. The RO guys are a clever bunch. 🙂
Every time I scan the title of this post in Delphi feeds my brain says “nubile types”. My eyesight must be going, can’t imagine why.
“nubile types”
That’s a whole other blog…
wonder a lot that you dont get bored with your halfhearted cloaked RemObjects marketing campaigns (sometimes looks indeed a little bit redicoulous, sorry, really! ) 😉
did they pay that well, would you bother mentioning a numbered hint ? 😉
I really struggle to see how it is “ridiculous” that someone would choose to write on their own blog about that they find interesting. Isn’t that what blogs are for ? I get nothing from anybody for what I write on my blog (quite the opposite – it costs me hundreds of dollars in hosting and bandwidth charges). I pay full retail for my RO software and get no consideration in respect of anything I blog about. As a result, you can be sure that what I write is what I think, not what I am being paid to write.
I simply happen to think that RO have a great product that is well worth talking about.
What is curious is that I don’t remember anyone ever suggesting that my enthusiasm for Delphi in days past meant that I was in Borland’s pocket as a result, or dismissing my enthusiasm as “ridiculous”. Strange, eh ? 🙂
Sadly, times have changed and it’s become common for people to question the intentions of Delphi enthusiasts.
Jolyon makes plenty of odd and onsupportable claims, but it seems unfair to give him grief over a constructive blog post.