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.
Baby + Bath Water
Case insensitivity is A Good Thing.
Case sensitivity is insanity when it comes to programming languages, and suggesting it exposed a contradiction in your own pecadiloes....
On the one hand you dismiss the separate interface/implementation sections as flawed and point to the need for IDE support to make it workable as evidence of those flaws, and then invoke the wonder of IDE support to make case sensitivity more workable.
Just because everyone else in the room is smoking does not make it A Good Idea to take up smoking.
You also reveal a slight lack of familiarity with Delphi as IDE tools for not only navigating but CREATING missing interface/implementation declarations have existed for many, many versions already.
Ctrl+Shift+Up/Down will navigate between interface/implementation
Ctrl+Shift+C will complete the declaration of the type under the cursor
And without separate interface/implementation, further IDE support is needed to make code browsing and navigation an acceptably efficient - and dare I say pleasant - task. The lack of separation between declaration and implementation in C#/C++/Java is the principle reason that code created in those languages becomes intensely difficult and cumbersome to navigate.
Sure it makes it "easier" to CREATE code but code spends a far greater time merely existing and having to be maintained than it does being created.
Similarly the lack of clearly defined declarative areas for variables and the like.
You stumble across some code using some variable - it's type may not be immediately apparent to you (sidebar: type inferencing is great for compilers who have the gift of perfect knowledge at compilation time, and a real PITA for developers having to MAINTAIN code created in a whimsical nano-second of creative joy, but which then has to sit around being maintained and understood for years after that not-that-much-more-brief moment of labour-reduced intensity) .
With the ability to declare variables whilly-nilly and hither and thither, where is the poor maintenance developer to go to seek out that declaration? They have to go spelunking (or invoke yet more IDE scaffolding).
I agree that garbage collection isn't a good fit in Delphi. But there are occasions when the compiler could be coerced into taking the drudgery out of our miserable existence as developers without involving the overhead of reference counting.
Some time ago I suggested co-opting the existing but now long since out of use "automated" keyword to mark a local variable (of object reference type) as following the interface type semantics.
list: TList automated;
list := TList.Create;
The "automated" keyword would simply direct the compiler to:
- initialise the variable as NIL
- call "Free" using the object reference when the variable leaves scope
Currently interface reference type variables follow an almost identical pattern:
- initialise the variable as NIL
- call "_Release" using the interface reference when the variable leaves scope if the reference is non-NIL
(note that for object references the non-NIL test is redundant as it is handled by the implementation of Free, which is already NIL-safe - this is not the case for interfaces)
The same approach could be extended to member variable declarations and, less usefully but for consistency, unit variables (so called - incorrectly so - "global" variables).
This small change would make an immense difference to everyday programming jobs, but equally could be completely ignored by those who enjoy creating try/finally constructs.
There's lot's more that could be said, but suffice to say at this point that for a "dead" language, Delphi seems still to be doing a lot more than just twitching.
Case-sensitive languages are a tool of the devil!
Case-sensitivity is to a programming language or an operating systen what gendered nouns are to a spoken/writen language - a bloody stupid pain in the arse.
I totally agree. We should get rid of programmer laziness and ambiguity. Keywords like 'with' and 'reintroduce' appear more like kludges than language enhancements.