February 9, 2011, 5:13 pm
One annoying thing I’ve noticed in building my script compiler is the way the use of generic collections tends to bloat up the size of your EXE. I use generics for a lot of things; a compiler uses lists, stacks and lookup tables (dictionaries) all over the place. When I was building it with DeHL, the compiler plus a very simple test frontend compiled into a 36 MB behemoth of a binary, and a quick look at the mapfile shows that the vast majority of that was DeHL collections. Now that I’ve switched to the more simplified Collections library, it “only” takes 23 MB, a savings of about 33%. But that’s still huge. There has to be a better way.
Continue reading ‘Wish list: Generics collapsing’ »
November 20, 2010, 1:41 pm
I mentioned the new generic collection TThreadedQueue<T> in my First Look at Delphi XE. I decided to play around with it a little recently. It’s useful for passing data between one thread that produces output and another that consumes it, keeping the two in step by blocking if the consumer tries to pop from the queue while it’s empty.
The first thread goes through and pushes data into the queue however it wants to. The second has it easy; all it has to do is loop endlessly until the queue is shut down. And we all know how to do that:
[code lang="delphi"]
for value in queue do
process(value);
[/code]
Except that if you try to do that, the compiler will complain at you. There’s no enumerator. For some strange reason, out of all the collections in Generics.Collections, TThreadedQueue<T> alone does not descend from TEnumerable<T>.
Oh well. It’s not all that hard to add an enumerator to a class that doesn’t have one. Just use a class helper.
[code lang="Delphi"]
TThreadedQueueEnumerator = class
private
FQueue: TThreadedQueue;
FCurrent: T;
function GetCurrent: T;
public
constructor Create(queue: TThreadedQueue);
property Current: T read GetCurrent;
function MoveNext: Boolean;
end;
TThreadedQueueHelper = class helper for TThreadedQueue
public
function GetEnumerator: TThreadedQueueEnumerator;
end;
implementation
{ TThreadedQueueEnumerator }
constructor TThreadedQueueEnumerator.Create(queue: TThreadedQueue);
begin
FQueue := queue;
end;
function TThreadedQueueEnumerator.GetCurrent: T;
begin
result:= FCurrent;
end;
function TThreadedQueueEnumerator.MoveNext: Boolean;
begin
result := FQueue.PopItem(FCurrent) = wrSignaled;
end;
{ TThreadedQueueHelper }
function TThreadedQueueHelper.GetEnumerator: TThreadedQueueEnumerator;
begin
result := TThreadedQueueEnumerator.Create(self);
end;
[/code]
Well, that was easy. That’s probably the simplest enumerator I’ve ever written, because of the way the queue’s design makes it easy to implement MoveNext. Except… that doesn’t compile either. Apparently you can’t put generic type parameters on a class helper, which means that as far as I can tell, you can’t apply a class helper to a generic class at all.
I suppose I could subclass it and add the enumerator that way, but TEnumerableThreadedQueue<T> is a bit of a bulky name, don’t you think? I have to wonder why the enumerator was left off of this collection, though, especially since the standard enumerator pattern is basically the only reasonable way to use a class like this…
September 1, 2010, 12:41 am
This week’s just getting started, and it’s already had more than enough awesomeness to pack into a typical month. The new version of Delphi came out yesterday. Metroid: Other M and The Way of Kings, a new Brandon Sanderson book, were both released today. (I have a feeling I’m going to be more distracted than usual for a while…) But as awesome as Metroid games and anything by Sanderson tend to be, (if you’re into fantasy at all, check out Elantris and Mistborn and prepare to be blown away,) this is a programming blog, and I’m supposed to be talking about Delphi. So here’s the good, the bad, and the annoying about my first impressions with Delphi XE.
Continue reading ‘First look at Delphi XE’ »
June 22, 2010, 3:52 pm
Since some version of this question keeps showing up on StackOverflow, and the answer’s always basically the same, I figured I may as well write up a post on here that people can link to. Here’s the question, in simplified form:
“Why can’t I pass a TList<TMyDerivedObject> to a function that’s expecting a TList<TMyBaseObject>? You can pass a TMyDerivedObject to a parameter expecting TMyBaseObject, so why doesn’t it work for lists?”
Continue reading ‘Generics and the Covariance Problem’ »
March 9, 2010, 2:41 pm
I really loved when Delphi 2009 came out, how it fixed so many ugly problems in the Delphi IDE. The stability issues and memory leaks that plagued D2006 and D2007 were greatly reduced. And it just got better in D2010.
The tradeoff, though, seems to have been compiler stability. Trying to do anything with Generics in D2009 before Update 3 came out was a nightmare, and even after, (and even in D2010,) there were still plenty of dark corners where you can end up with an Internal Compiler Error or linker error on something that, syntactically speaking at least, is perfectly cromulent Object Pascal.
Continue reading ‘How to break the D2010 compiler’ »