Born Again Delphi
A word in CodeGear's shell-like
By Verity Stob • In Verity Stob • At 12:15 GMT 4th February 2009
Mr Nick Hodges of CodeGear and Embarcadero and not Borland blogs amusingly about the obscure corners of Delphi syntax. Delphi Pascal apparently still implements a Jensen and Wirth era feature whereby [square brackets] can simulated by the sequences (. and .). In the olden days,
MyArray := 0;
could look like this (assuming my exotic characters aren't eaten by El Reg's CMS)
MyArrayÄ5Å := 0;
when displayed on a 1982, methylated spirits-burner powered, Ericsson video terminal. So Prof. Wirth decreed it that
MyArray(.5.) := 0;
should mean the same thing. (In my ancient and limited experience, the cure is worse than the disease - even more so with C's ghastly trigraphs. But I digress.)
Mr Hodges uses this as a leaping off point to discuss the future of Delphi. In essence, the plan is this: CodeGear is embarking upon a mega rewrite of the compiler. Henceforth it will be, he says, easier to target new platforms - CodeGear is thinking about a 64-bit version next, and who knows what after that. More interestingly, CodeGear is planning to split and duplicate the front end of the compiler so that it can handle both existing Object Pascal, and an incompatible variation of the language with 'a new, non-legacy syntax'.
In other words, future Delphis will support two dialects of Object Pascal, linkable at module level, but syntactically incompatible.
CodeGear is surely not doing all this to be rid of the obligation to support (.Wirthian simulated square brackets.). They are going for the Big One. But Mr H is silent on what extra features the newborn language will contain.
Therefore, now is a good time for an esteemed and respected tech columnist (or, failing that, me) to nail to CodeGear's door a list of all the changes, features and must-keeps that that esteemed and respected person (or I) would like to see in the new language.
Maybe this is not quite what Mr Hodges and friends would prefer at this juncture. Sorry, Mr H. The second best-known observation of Sir Michael Jagger is applicable in this context. Besides, you get to throw that gag back at me in a moment.
Enough chit-chat already. Here is my list of completely reasonable demands:
Compilation, compilation, compilation. One feature of Delphi and Turbo Pascal that has consistently distinguished it from inferior languages is that, in my experience, one can generally complete a Delphi build in less time than it takes Netbeans to coax the Java compiler's flabby backside off the magnetic media.
As I understand it, this speed advantage is in part achieved by the .DCU object file format, which is actually a raw-ish dump of the Delphi compiler's output buffer. On the one hand, it's really easy to write out and load quickly: it's already in the right format. On the other hand, change one teeny thing in the compiler and you wave goodbye to being able to read the previous version's files.
Mr H talks of 'fixing' the compiler-specific DCU format, which makes me anxious. I dare say the whole program is a great ball of elderly C++, pock-marked with globals and 1990s attempts at collection classes and God knows what. But I implore CodeGear to be careful to produce a new compiler that is actually as fast as the old, rather than just theoretically faster.
Declare methods once. We really should be able to declare methods inside a class, as in the Java model. All this
interface/implementation division stuff is alarmingly COBOL-like, and feels like a hangover from 1975 designed to make writing compilers slightly easier.
Besides, some of us are not as young as we once were; by the time we have scrolled down from the class declaration to the spot in the file where we had planned to implement the method, we have not only forgotten its name and its parameters, we have also forgotten what it was going to do and what we came here for and who is the prime minister again? Is it still that nice Mr Blair?
I know that there are various gizmos one can bolt into the editor to make this constant upwards and downwards motion easier for our fuzzy memories and arthritic fingers - the Stannah Stairlifts of Pascal editing - but it's time for a proper bungalow.
And declare variables anywhere. Again, a lurch away from the 'everything has its place' approach of 1960s languages. We should be able to write
for var I:integer := 0 to 10 do
and have that work as expected, with
I declared in the scope of the
By the way, did you notice that I smuggled in a second demand there: that we should be able to initialise stack variables in situ.
What about garbage collection, Verity? I am coming to that. Sheesh, give me a chance.
Case sensitivity in identifiers. As things stand, Object Pascal ignores case in identifiers. So if you want to register some home-brewed components, you can declare your registering procedure
according to taste.
Haha, got you! Neither will work, because Object Pascal ignores case in identifiers except the Register procedure which must be declared
Surely CodeGear can to do better than this. Case insensitivity is a pain in the elbow, again associated with Jurassic uppercase-only printers that made variables called '
PenIsDown' look rude. If one declares
MY_CONST in one scope and
my_const in another, you just don't expect one to hide the other.
And for another thing, we are always having to interface with languages that do take case seriously, starting with all the DLLs in the Windows API. I think it's time to throw in the towel on this one, siblings.
I recognise this is quite a big change, so when it hits an unidentified symbol, the compiler should search its hash table, suggest the intended spelling, and offer to correct the code and continue compiling. That will help contain the pain.
While we are on identifier confusion. The
with keyword. The most hideous, dangerous, blow-your-own-feet-off feature in the language. What's that you say, Sweep? You use
with to give the compiler a hint as to which variables to put in index registers? Ooh, you lying little hand-puppet, you.
OK, if it proves to be impossible to kill
with, at the very least limit it to one record at a time. And change the spelling of the keyword to
caution_stupid_programmer_with. And switch to the VB convention of requiring the programmer to prefix the fieldname with a period:
caution_stupid_programmer_with MyRecord do
.FMyField := 'Look, I''m Stupid!';
But what am I doing? Borrow a Visual Basic feature in order to improve Delphi? Better to go on a weekend winter waterboarding holiday with ex-president George W. Did we fight and win the great VBX war of 1998 for this? Sack the damn thing and be done.
A tweak to the system of overriding methods. Let's steal the
new method modifier from C# to do method hiding. Can't be bothered to explain it here - it adds a smidgen more expressivity to the language - just read it up in MSDN.
Well, why not? The C++/Java systems of overriding are stuff-ups, and Delphi is already better. But is it not a pleasure and duty to add another few ounces of Hejlsberg goodness? Who cares if we half-inched them? Great artists...
Do more with
const. Pretty well the only practical thing we do with
const in Object Pascal is apply it to parameter strings. This is ok as a piece of optimisation (have you seen the amount of guff that gets generated to cope with strings passed by value? Or what about a variant? Get thee to a disassembler...) but is limited as a tool for expressivity. I want to be able to write: 'this method promises not to poke its fingers into the state of its owning object'. No, really, it's enriches the design; it's one of the underrated virtues of C++.
So what about garbage coll... Yes, yes. In a minute.
On reflection... Delphi really should have wider support for reflection, and it should be more sincere - ie less fiddly to use, not buried away in an obscure unit. Waves hands vaguely. Make it so.
Closures. We really must get closures. Oh, wait - we already have them. (Excuse me, still on Delphi 7, haven't yet switched to D2009 in anger.) Anyway, take that, Java! Ha!
try...finally is not really a great way to protect resources. It is just too ad hoc. The problem is that sooner or later this happens:
A := nil; B := nil;
A := TSomething.Create;
B := TOther.Create;
// Lines of code using A and B
// But forgot B - easily done so far away from the Create
Others have had a go at this problem. The C#
IDisposable/using thing, explained here, feels like a bit of a kludge. I prefer C++'s 'Resource Acquisition Is Initialisation' idiom, which relies on the destructors of stack-allocated objects getting called automatically when they go out of scope. This idea can be extended to make so-called smart pointers, which use reference counters to produce allocated objects that not only do the right thing when under exception-stress (ie get freed at the right time without having to write special code).
Delphi doesn't have stack objects, but it does have objects with automatic reference counters - interfaces. These can be used to make C++-like smart pointers - here it is being done. Now, if only there were a little bit of syntactic sugar in the compiler, so that this scheme was a little more straightforward to implement and use, I reckon we could have a Delphi idiom that would do the trick nicely.
So with all this talk about smart pointers, I guess you are agin garbage collection? OK, I admit it. Garbage collection is in general a great liberating thing. But I don't think it is right for native Delphi.
Delphi Object Pascal is surely supposed to be a 'as close to the metal as is sensible without being rust' sort of language. This is what differentiates it from C# and Java, which emphasise portability and safety, but run in vast, cosy-but-stifling, virtual machines that arrive (in one case) as gargantuan downloads and (in the other) seem to need updating every 10 minutes. When you do garbage collection, you are handing off a piece of control that by rights belongs to the obsessed, micro-optimising programmer. This is not the Delphi way.
Remember: we already got some Pascal garbage collection in Delphi.NET - and that didn't work out brilliantly, did it? Also, if we get GC in native New Delphi, will it not introduce hideous data sharing problems with Olde Delf modules, like managed and unmanaged code in Visual C++?
On the other hand, the smart pointer design I cited back there was the work of one Barry Kelly. Mr Kelly is one of the doubtless vast team that CodeGear has assembled to work on the compiler, and he seems to be pro garbage collection (and points out, amusingly, that Jeff 'Coding Horror' Atwood apparently believes that stack-allocated items are garbage-collected), although we cannot know what he thinks in this specific case.
Mr Kelly is rather well placed to have an opinion on this matter; if he were to produce it and it ran contrary to mine, I would be happy to consider it seriously. I am sure he is very relieved to hear that.
In real life, the issue of memory management does not arise as much as you'd expect in practical Delphi code, because of the ownership system in the VCL framework.
Ah yes - what about the VCL? Ok, not actually a compiler issue per se, but in Delphi the twain are intertwined.
The VCL was a miracle of its time. It was eight trillion times better than MFC. It got things right about delegation and event handling and resource storage and organisation that are still regularly being got wrong. The VCL hierarchy is perhaps a little deeper than is fashionable nowadays... but so what? The thing works, and works a treat.
You will recall the design principle called 'separation of concerns', which says it is a good idea to minimise dependencies between different functions of your program. The VCL doesn't really 'do' separation of concerns. Its leanings are more towards consolidation of concerns into one honking big woe.
The solution to this, it seems to me, needn't be painful. The VCL is an excellent tool for implementing the 'V' part of the 'Model-View-Controller' pattern, and should be left alone.
All that is needed is a new, separate library to do the concern separating. And there is already an extremely elegant, compact and multi-lingual open source library called PureMVC. Although initially targeted at ActionScript and Flex, it already supports a dozen or so languages and platforms. I see no technical reason why New Object Pascal could not be added to the tally.
Among other advantages, it would mean that if CodeGear were to create a Delphi cross-compiler for, say, the Palm Pre, then they would not need to port the VCL at the same time (a highly desirable outcome in view of the Kylix and Delphi.NET fiascos, where many dollars were spent creating unsatisfactory re-implementations of the VCL). CodeGear could create a new front-end library specifically appropriate to the Pre device, and not backwards-compatible with anything, and they would be done.
Sure, users would have to rewrite the front-ends of their MVC structured programs - but realistically they would have to do that in any case, because a PC UI does not work well on a smartphone (don't believe me? Ask a Windows Mobile user). Everybody would be happy.
Other bits. Another library issue: we are very overdue for an officially-sanctioned regex library. This is a fundamental omission in the Web era. Even C++ is on the cusp of getting one, for heaven's sake. There's a PCRE wrapper in the excellent JEDI open source library - I suggest CodeGear starts negotiating for a borrow.
Tuples are record types that you make up on the fly, and can then pass around and interpret in distant pieces of code. They are like variant arrays with the stigma removed.
Andreas Hausladen is one of a coterie of Delphi nutters heroes who have made using it bearable during years of Borland neglect, and are still at it. For example, last week Mr Hausladen devised a patch for a key but sluggish Delphi database library that improves its performance by up to ten times. If Hausladen et al can regularly do this sort of thing by reverse engineering binaries, what could they achieve if a way was found to give them access to the code generator source? New thinking for new times, CodeGear.
Erlang has arbitrary-sized integer arithmetic, so one can calculate 12345678987654321 * 98765432123456789 precisely. I don't think this is particularly useful, but it is cool, and implementing it gives the CodeGear boys something to do with their endless free time.
One last thing. This brave new dialect of Pascal will need a new name. We need to move on from the old quarrels about whether it is called 'Delphi' or not. Nor will the anagrammatic approach of the aforementioned Erlang cut the mustard (had you spotted that? It's 'Angler' really, of course). We need to find a moniker that suggests freshness, goodness and respect. I have just the thing.
So, CodeGear, when do you think you will be ready to ship Obama Pascal? ®