Friday, May 28, 2004

More RC fun...

In the "keeping up with the Jones'" department (Anders Ohlsson and Michael Swindell), I just ran across this Huge B-52 flying scale model. What is really interesting is that it uses real turbine engines! Some folks have just have way too much time (and money) on their hands..

Thursday, May 27, 2004

Delphi Win32: Why packages are better than libraries.

In this rather lengthy entry in Chris Brumme's weblog, Startup, Shutdown & related matters, he outlines many little-known items related to how the Windows OS handles dynamic loading of DLLs. He also mentions a major potential "gotcha" when executing code in "DLLMain()" (or in Delphi parlance, the unit initializations for all units in a Delphi "library"). Most of his discussions are couched in relation to the CLR buildup and teardown within an OS process. There is, however some interesting insight that can be gotten from this article regarding certain caveats when writing regular Win32 applications.

The most interesting section is the discussion regarding the OS Loader Lock. At their core, all Windows DLLs have an entry point referred to among the "C/C++" crowd as "DLLMain()." To us Delphi-heads, we just use the implicit unit initialization. The problems come from the very fact that in a Delphi library, unit initializations are called during the DLL_PROCESS_ATTACH phase of DLLMain(). Since the OS is holding the Loader Lock, there are a several things you can't necessarily do from within the unit initialization. Here's Chris' list of don'ts:


1) You must never call LoadLibrary or otherwise perform a dynamic bind.
2) You must never attempt to acquire a lock, if that lock might be held by a thread that needs the OS loader lock. (Acquiring a heap lock by calling HeapAlloc or HeapFree is probably okay).
3) You should never call into another DLL. The danger is that the other DLL may not have initialized yet, or it may have already uninitialized. (Calling into kernel32.dll is probably okay).
4) You should never start up a thread or terminate a thread, and then rendezvous with that other thread's start or termination.


OK.... so what does this have to do with packages?

As it turns out, Delphi packages avoid these issues because the initialization model is much different. When a Delphi package is dynamically loaded, unit initializations are not implicitly called like a Delphi library. Only a small initialization stub is called that is just enough to wire the package into a global linked list of packages, setup that package's HInstance variable, and initialize the Thread Local Storage block. No unit initialization can be done until LoadLibrary returns and the OS Loader Lock is released. The LoadPackage function in SysUtils.pas does this by calling GetProcAddress on the package's HModule looking for the compiler-generated entry-point called Initialize and then calling it. This entry point calls a stub of code with a table of all the various unit initialization blocks addresses that in-turn runs through the list an calls each one. So when your unit initialization code is called when the unit is in a dynamically loaded package, you are free to do anything, including all those items listed above. Remember to always use LoadPackage to dynamically load your packages as this will ensure that this sequence of events is properly followed. Alternatively, you can load the package yourself using LoadLibrary, but you must call InitializePackage prior to making any calls into the package.

Remember, also, the rules outlined by Chris apply to dynamically loading a Delphi library that is linked with packages. This is because, even though you are implicitly dynamically loading the packages, the unit initializations of even the linked packages are controlled by the library's unit initialization sematics. Describing the complete details of how the unit initialization logic works is beyond the scope of this article.

Wednesday, May 26, 2004

Plucky Duck...

So I've been trying out Pluck for the past couple of days as my news aggregator and so far I'm quite impressed. It displays the actual web page of the blog article by browsing to the originating site within a browser pane. So this means that even if the RSS feed doesn't include the entire article text, it doesn't matter because you are taken straight to the originating web page. All of this is hosted as an Internet Explorer add-on. Of course if you despise IE, then you probably won't like it.

Monday, May 24, 2004

Hallvard is now blgging

Hallvard's Blog

Hallvard has a keen eye for the details. He also is one of the few Delphi customers that succeeds in keeping us on our toes on a regular basis. No chance of getting too complacent with Hallvard looking over our shoulder... Welcome to the blogsphere!

Mis-attribution...

Guardian Unlimited | Online | Inside track

I think Mary got a little mixed up. From the article:


Thorpe's disclaimer includes the line: "If you actually think that my opinions are a reflection of Borland, then I have a bridge I can sell you."


Now scroll down to the bottom of this page and read my disclaimer. Then follow this link to Danny's blog and scroll down to the bottom of that page and read the disclaimer.

You decide...

Friday, May 21, 2004

Gates on blogging

OK.. I just couldn't let this one go... I tried.. really I did. Seems Bill is talking up blogging to top CEOs. This will either be great for many companies (especially technology driven companies)... or not. According to Gates:


"Another new phenomenon that connects into this is one that started outside of the business space, more in the corporate or technical enthusiast space, a thing called blogging. And a standard around that that notifies you that something has changed called RSS."

and

"Another big phenomenon is building communities around Web sites, around products. And virtually every company ought to have on their Web site the ability for their customers, their suppliers, various people, to interact and their employees to see the dialogue taking place there and jump in and talk to them and help them"


On the surface it is great that a well respected (or reviled) industry luminary, is pushing the idea of corporate blogging. Borland is certainly dipping its toe into the blogging waters and MS is going gangbusters into blogging. The good thing about widespread corporate blogging is that it can certainly help dispel all those various rumors and conspiracy theories about some corporate hidden agenda. Guess what, in general, all for-profit corporations have that one "hidden" agenda... make money, increase shareholder value, rise above the competition, etc... By a company condoning widespread blogging by its employees, it can become more transparent and visible to the customers. In other words put on a happy face.

Now what about the "or not" mentioned in my opening sentence? This is where my cynical side comes in. Especially in light of the recent announcements of JBoss sandbagging the public forums with corporate shills. The potential for abuse is certainly there. Just like any new tool or technology, there are those that would like to approach it from a much darker angle. Email opened up a new form communication that has now so permeated our society, that even your great-grandmother has an email address. Now every time you go to read your email, you cringe at the sight of countless offers for improving your sexual prowess, that $0 down 0% home mortgage, or that self-described hotty, Bambi wants to meet you. Email is now a marginalized commodity. A necessary "evil." While I don't necessarily see there being this huge rise is "blog spam," it has already started with RSS feeds. What if a company were to "commission" groups of individuals to start blogging without the appearance that they are company employees, or they use pseudonyms? What if several employees started doing it on their own and the company simply looked the other way while those employees spread FUD about a competitor and made libelous statements?

For now, blogging is in the "innocence" phase of its development. Just like email and the internet itself was "young and innocent" at one time.

Thursday, May 20, 2004

Charlotte's web...

I was trolling through the newsgroups while rebuilding Delphi, and happened across a post that was wondering what happened to "Charlotte?" I suppose one could also ask, "what happened to the Delphi /Java byte-code compiler?" I can't necessarily say that they're dead, but just dormant. They were also just technology demonstrations which were the result of some internal research. Many times we will present these little peeks into what's happening in the labs in order to gauge response and overall interest. We don't have a crystal ball... more like a Magic Eight Ball, so there are bound to be some things that just don't make the cut, were too early, too late, or simply too dumb (I'm not implying that either of these two items were dumb!)... Sometimes the technology that we developed while researching these items actually do have an impact on our current product offerings. Many times in ways that you may not directly recognize.

For instance, the "Charlotte" research has produced some parser-generator tools that are used extensively in C#Builder and Delphi8 for producing the Abstract Syntax Trees (AST's) used to build the CodeDOM necessary for the WinForms and ASP.NET designers. So... you say? Well what is unique about these grammars is that they are designed from the start to be very robust in terms of dealing with code that is currently under development. Those parsers must be able to make reasonable sense of code that will not actually compile. It has to do this by inferring certain things about the code by inserting special error nodes into the AST. This whole error recovery system is all part of the actual language grammar definition itself rather than glued onto the side as an after-thought. So in that sense, a little bit of "Charlotte" has been shipping with C#Builder and Delphi8 for a while.

What about the Java byte-code compiler? Well, it turns out that we may be using some of the concepts introduced by that little bit of tech for providing a solution to multi-unit namespaces. So, while we've demoed future tech (and may continue to do so), many times tech doesn't die or turn into a stand-alone product, but is "parted-out" to existing products so that it can gain the widest possible audience.

Wednesday, May 19, 2004

dbRTL public beta posted

There is now a public beta available for immediate download that fixes the "persistent field size mismatch exception" issue introduced by the Delphi 7.1 patch. You can get get more information here.

Cool hardware...

I've been eyeing this little bit of hardware for a while and so I finally went and got it. I have a lot of videos that I'd recorded on my home PC but I hat sitting at the computer to watch them. I'd rather go to the living room with the 53" big-screen. What I'd been doing was to burn them to a VideoCD or, more recently, to DVD. That works, but sometimes it is just a show I scheduled to be recorded and only watch it once and then delete it. I'd rather not burn a DVD just to be able to watch the show. So I bought this really cool little set-top device called the MediaMVP. It is essentially a little embedded Linux device with a PowerPC "set-top" chip with an MPEG decoder, some flash memory, some RAM and ethernet controller. It directly connects to the network and talks to a special server service running on your PC. It then streams audio, video, pictures and internet radio directly to your TV. Now I don't really watch too much TV at all, but there are a few things I do like to watch. Sure, I could spend several hundred bucks on a Tivo or ReplayTV, but I already have a TV tuner/video capture card in my PC with the requisite record scheduling software. This little device only cost $99. With the latest beta firmware, I can also play Divx encoded videos (that requires a Divx decoder on the server and a little more network bandwidth).

There's also a whole sub-culture beginning to form around this little gem. Here's a few links to various reviews and hardware tinkerers:
MediaMVP and VDR
Hauppauge MediaMVP Software
WinTV PVR & MediaMVP Board
Hauppauge MediaMVP review by PC Magazine
Review on Build Your Own PVR

Monday, May 17, 2004

One namespace to rule them all...

Right before Danny left on his trip to Amsterdam, London and the grandparents, I presented a potential solution to the multi-unit namespace issues. Danny was quite excited about the idea. I've been discussing it with others internally and so far haven't been able to shoot too many holes in it (at least none that we can't easily deal with). Since Danny is due to be back in the office tomorrow, I'm anxious to hear if he's been able to poke any more holes in the idea. I'm sure you'll be able to read about it from either one or both of us within the next couple of weeks.

Friday, May 14, 2004

2rss.com ad free..

Apparently Anders Ohlsson struck a deal with the owners of 2rss.com so that all the Borland bloggers now have ad-free atom->rss feeds. Good job Anders.

Thursday, May 13, 2004

2RSS.com & adverts..

Anders Ohlsson just posted this regarding the fact that 2rss.com is now injecting ads into my rss feed. This blog entry on their site explains why they started doing this. Unlike Anders, however, I cannot actually fault them for this since, as they explained, they have to justify providing a free service. Also, the $14.95 annual fee seems like a reasonable charge in order to use the service ad-free. On the other hand, it would have been nice if they had injected an entry into the feed that merely points out that they would start injecting ads and that you can sign up for the service to support their efforts.

So far the ads seem innocuous and unobtrusive... On the other hand, this may be a catalyst to finally get a blogging solution up and going on the Borland Developer Network site.

Wednesday, May 12, 2004

Delphi 7.1 and persistent fields

The following is a post to the borland.public.delphi.non-technical newsgroup from Mark Edington, a senior engineer on the Delphi development team:


Sorry about the delay in commenting here. My newsreader was giving me fits
trying to post yesterday and I've been running around like a headless
chicken dealing with this issue.

Clearly many folks (and I'll put myself at the top of the list),
underestimated the ramifications of the change that was made to to enforce
the size matching. I was a little hesitent at the time I made the change,
but I really had no idea how common it it is for folks to have this
situation in their applications.

As it stands, the fix is not helping anyone because it has adversely
affected so many applications (and clearly that was not the intention of the
change), so the arguments about whether or not the DB code should enforce
the size matching are somewhat moot. We don't want to be introducing
changes in a patch (or even a point release) that have this effect. Period.

The original TClientDataset defect that prompted the change (QC#3874) can
and will be fixed in a different way.

We are are urgently working on a remedy for this situation and I will be
posting more information regarding that as soon as it is available.

For folks who installed the patch and are affected by this it is my
recomendation that you simply revert the related files from the original
Delphi 7 CD. There are only a handful of fixes in those files anyway. I'll
outline what to copy from the CD below.

By way of defense for the change, I would point out that the size checking
code introduced is actually a slightly more relaxed version of the checking
that was done in Delphi 4 and prior releases. So it's not something
completely new. On the other hand, it is certainly valid for the size of a
persistent field to be larger than the size of the underlying field in the
case where the data is read-only and at the very least that provision should
have been coded in as well. In any case, it is my opinion that the "fix"
should be completely removed and the code restored to the way it was in
Delphi 7.0.

Finally, I would like to offer my most sincere apology to you and the other
folks who were impacted by this issue.

Mark


I couldn't have stated it better myself. I was involved with a rather lengthy meeting regarding this very issue and can certainly attest to the fact that we are working as quickly as possible to get a resolution delivered as soon as possible. Please bear with us while we try and shift gears...

What is a "Breaking interface change?"

There seems to be a level of confusion regarding what constitutes a source code change that would result in symbol version mismatch errors. The rules are actually rather simple, but somewhat obscure and steeped in various levels of voodoo.

The "unit" structure of Delphi (or Borland Pascal) determines what other units can "use" from a particular unit. By placing declarations in the interface section of a unit, the user is publicizing the existence of a particular type, constant, variable, or function for external use. This declaration forms a sort of "contract" between the user of that symbol and the implementation of that symbol. For instance, a class declaration describes general structure of a particular class in addition to the actual physical layout of an instance of that class. When another unit (or program) references that class symbol and then it is compiled, certain bits of information are persisted to the binary .dcu/.dcuil file that describes in very fine detail the actual physical layout of an instance of that class, the class vmt (virtual method table), the RTTI, etc.. For instance, given a class TFoo with a virtual method Bar, a copy of the vmt is placed into the .dcu file with certain offsets. For a descendant of this TFoo, any virtuals it may introduce, will now be appended to the end of ancestor's vmt and the offsets to those entries are recorded. The same thing happens for fields as they have the offsets into the class instance recorded as well.

Now, say you decided to change the declaration of TFoo and wanted to add a new virtual method Baz. When the unit is recompiled, this method would now be inserted into the vmt and all the offsets are recalculated. This represents a classic "breaking" change. In most cases the user is totally unaware that this happened because the compiler is smart enough to recognize that the symbol's version (an internal compiler generated signature that allows the compiler to quickly determine that a symbol has changed), has changed it knows that all other units that refer to that symbol must now be recompiled.

Problems now arise from the fact that if you had a .dcu file that didn't include the original source, there is no way for the compiler to resolve the changes with the users of that symbol. All the compiler has is the final binary representation of that source with all the various offsets and fixups resolved in an intermediate format. This is what causes the symbol version mismatch errors folks may have seen.

All the above also applies to Delphi packages and their corresponding .dcp files as well. .dcp files are simply a concatenation of all the containing .dcu files sans any code blocks since that data is persisted into the .bpl file.

So what can you change that won't break .dcu compatibility? The rules are as follows:

You cannot:


  • change the ancestor type of an existing class

  • add/remove a field to/from a class or record

  • add/remove a new method, virtual, dynamic or otherwise to a class

  • add/remove a property decl to a class, including a property redecl

  • remove a constant, variable, type, or function from the interface

  • change the value of a constant

  • change the calling convention of a method or function

  • change the visibility of a field, method or property

  • change a method to/from virtual or dynamic



You can:

  • add a new global constant

  • add a new class type

  • add a new global variable

  • add a new global procedure or function



This list should cover most situations but there may be some cases that don't quite fit the above list, or at least appear to not fit. For instance, if you had unit A; unit B; and unit C;. Now if the "uses" order were C uses B uses C and a breaking change were made to C, that change may cause a corresponding breaking change in B, and so on. If you didn't have the source to B, there'd be no way to resolve that breaking change.

This is exactly the situation that Borland strives to prevent when we publish a patch. We cannot afford to cause this kind of grief for all the third-parties and ultimately their customers that so diligently support Delphi. Were we to be careless when providing fixes and constantly make breaking changes, the pain and frustration level would rise far above the pain we tried to relieve. Kinda like, "So we cured the patient of that deadly disease, however the problem is that he didn't survive the treatment!"

Now before you skeptics and "flame wolves" pounce and start off with things like, "Hey C++ code doesn't ever have this problem!" Au Contraire! C++ has this same problem in spades. The problem is that you get far less compiler help. Say you had a C++ DLL that exported some classes, or even a .LIB that contained some classes. If you simply replaced the DLL, and thought.. "I only added a private field to my base class," you have just set yourself up for a long debugging session of wondering why some of the fields in your base class are now being overwritten. The same holds true if you had a LIB B for which there were no source (headers don't count here folks), and it linked to a common LIB A. Then LIB A changed the declaration of a class which was used or descended from in LIB B. LIB B will contain instructions, and field offsets based solely on the old version of LIB A. The problem is with this scenario is that the compiler/linker won't tell you that there even is a problem. As long as you didn't change any the method declarations in LIB A, it will link just fine (because the mangled names haven't changed). That is purely insane!

For that other crowd out there that would like to point out that C# isn't afflicted with these problems, I'll have to say for the most part you're right. Since classes in .NET (CLR) are purely late-bound by virtue of the JIT compiler, the runtime execution engine can figure out what the class layout actually is. So you can certainly add virtuals, statics, and fields to an existing class without necessarily breaking existing code... but what if I needed to add a parameter to a method, or I wanted to remove a param? What if that old property or method is obsolete, so I removed it? Same issue folks. Murphy (of Murphy's law) would step in and promptly find that one user that called that changed/removed method and cause their app to break. The interesting thing is that even if that method were referenced in some code, the CLR, and thus the user, would not find out about the problem until the JIT'er actually had to compile the calling method. Microsoft knows all of this and has taken steps to assist the user in solving these issues. The first solution is the late-binding nature of the CLR, the other solutions involve strong names and side-by-side execution, which are out of the scope of this post.

Oh and finally, yes there have been a couple of cases where we did introduce a breaking change in a patch. These situations are met with very internal resistance while the costs and benefits are carefully weighed. These are generally cases where the change was deemed to affect a relatively small number of users, and the likelihood of there being a third-party component that depends on the unit being changed is small. A breaking change to TButton would certainly not likely even be considered. However a change to DDEMan, would certainly be entertained... if only to see who would even notice.

New Title, New Look

I've just updated the title and overall look of this blog. Since Blogger.com has vastly updated their site and features, I figured it was time to do the same. The title change merely reflects the fact that this blog is more about Delphi related things than being a pure vanity thing. Although I do tend to mix in a few personal tidbits now and again.

Friday, May 7, 2004

Files, Units and namespaces.. oh my!

Arbitrary and structural... these are words I would use describe the relationship between how C# contends with files and how Delphi (nay, Turbo/Borland Pascal) contends with them. As I thought more about this it became more clear about how this subtle difference in how Delphi and C# view a physical source file caused some of the misunderstandings, assumptions, and outright disappointments regarding Delphi's handling of namespaces. I may be completely out in left field here... or I may just be stating the obvious... and that may be the issue... duh! that's obvious!

In C#, the notion of a physical source file is almost purely arbitrary and abstract. To the compiler, there are no file boundaries. They carry no structural information to the compiler. You have to tell the compiler about every source file you intend to build into the assembly. That list of files also must be referentially consistent, or every type reference must be resolvable either by the list of source files or by external explicit assembly references. You see, that's a key difference between Delphi and C#'s view of files, structure. In Delphi, a physical file is a language construct in and of itself. It is the boundaries of the actual file that define the "namespace." This is why Delphi can keep .dcu/.dcuil files in order to decrease compile and link times. It can easily tell if a .dcu/.dcuil (which are essentially a raw dump of the compiler's internal symbol tables) is out of date by checking both file dates and symbol versions. It is also this same file-based structure that gives serves to seemingly limit the programmer's ability to define exactly how a set of components or classes appear when they are exported from an assembly.

What about Java? Java is actually closer to the Delphi way than the C# way when dealing with files. To Java, the physical file is also a language construct. You can't have more than one class in a .java or ultimately a .class file, except inner classes, of course. To Java, the folder hierarchy is also a language construct. It serves as the definition of a namespace. Java then goes and throws in another twist... the imports clause can contain the '*' character to tell the compiler that you want to reference all classes from a given namespace (or folder hierarchy) without explicitly specifying every class you intend to reference. This allows you to add classes into a specific namespace and have those new classes appear without updating the dependent source files' imports clauses.

So, what does this all lead up to? Nothing really. You don't even have to think this is particularly insightful. This was just a random thought... You can also see that this is going to be a very tough nut to crack. Delphi's notion of files=units=structure is fundamental to the overall character of the Delphi language. Maybe we should begin to look at other languages' playbooks for ways of dealing with namespaces.

One Bacon Double Research, Hold the Labels

One Bacon Double Research, Hold the Labels

Danny has posted this great piece on why we blog. It's worth a read... Don't worry, I'm sure there are plenty of other "Hornet's nest" out their for either one or both of us to go kicking...

Thursday, May 6, 2004

Delphi 7.1 is now available

Whew! I was beginning to worry that I had lied when I posted that the Delphi 7 update would be available this week... Well, it is now available. Here's the BDN article with the appropriate links.

Vanishing articles

I just happen to click the link to that wonderful bit of journalism from my previous entry and it appears that the article has disappeared. I can't locate it anymore on the Computer Weekly site. Maybe they caught some grief for some of the inaccuracies and decided to pull the article. Hmm...

Wednesday, May 5, 2004

Red Hat strives for corporate legitimacy

Red Hat strives for corporate legitimacy


"It's time for a change. Microsoft's competitors have tried to win by adding functionality - for example, Borland, Lotus and Corel. They're all gone. Now, with a major hardware refresh cycle under way, this is a great opportunity," Szulik said. [emphasis mine]

I had to glance at my paycheck and business card again... yep, Borland. Whew, that's a relief! I thought Szulik knew something I didn't. Hey dude, you're a little out of touch...

Thanks, Nick for the reference. I don't know if I should laugh, cry or be absolutely livid..

Danny's been "Scobleized"

http://radio.weblogs.com/0001011/2004/05/05.html#a7390

This could get interesting....

Put on a happy face...

Danny and I were having a discussion yesterday regarding the benefits that a company can gain by allowing its average-joe employees to maintain a blog hosted from their site or simply allowed to comment on what they do for they're "day job." I made the comment that blogs have the intangible effect of putting a collective "face" and "personality" on to an otherwise amorphous, cold and faceless corporation. It helps cement in the customer's minds that there are real people with real lives behind the products and services produced by the company. They have likes and dislikes, opinions, faults and emotions. Take, for instance, the fact that Microsoft has well over 400 active bloggers. Do you find that appears to make them more approachable and candid as a company? Does blogging help or hurt their public image? Do you find it satisfying that when you post a comment to a blog and the blog owner responds, even if it is a simple "thanks for your comments" response?

Tuesday, May 4, 2004

Sometimes Different == Broken.. maybe

Sometimes Different == Broken

I suppose I could rationalize this. I should mention that Delphi doesn't automatically box values, which is a potentially expensive operation; both in performance, and the potential backward compatibility problems. You can enable automatic boxing by using the (*$AUTOBOX ON*) compiler directive. Now your first question is going to be, "why not autobox by default?" The issue is backward compatibility. Consider some existing source code that has the following overloaded functions:


function Func(Value: Variant): Boolean; overload;
function Func(Obj: TObject): Boolean; overload;


Func(1); in previous versions of Delphi would call the Variant version of Func. Now if this code is compiled with Delphi 8 for .NET and autoboxing were to be on by default, the TObject version of Func would be called! The semantics of the code has changed. Since autoboxing is off by default, the user is now spared countless hours of frustration in wondering why the compiler is calling the "wrong" version of Func.

Now for the the auto casting to IComparable. This one is admittedly a little less defensible. I'll have to consult with Danny on the potential solutions. This will certainly depend on internal compiler architecture and other performance considerations.

C# has the benefit of not having any large base of existing source code; the semantics of the language could be defined in any way seen fit. Delphi having to maintain a high level of backward compatibility is both its strength and is a minor weakness.

Sun Policy on Public Discourse

Sun Policy on Public Discourse

This was just forwarded to me from John Kaster. It seems that Sun is picking up the blogging banner and has an official set of guidelines for bloggers. Eventually, we [Borland] will have a similar set of rules. After all the brouhaha about disclosing too much information, this set of guidelines seems reasonable, don't you. One thing to note about these guidelines is that they never say to err on the side of silence. They merely encourage the individual to seek approval for something that they are unsure of. Of course the one from whom approval is received may themselves be overly cautious, but at least there are checks and balances.

For now, these guidelines look very reasonable.

Monday, May 3, 2004

Enumerating array using for vs. foreach

Enumerating array using for vs. foreach

Here's an interesting tidbit over on Brad Abram's blog about the difference between for and foreach when iterating over an array. Apparently the C# compiler just code-gens an equivalent for statement when using foreach on an array. Something we'll need to keep in mind when/if foreach makes it into a "future" release of Delphi for .NET.

Monty Python..

The other day my children were being sneeky and absconded with my copy of "Monty Pythol and the Holy Grail" and proceeded to view it. Were it not for only a few objectionable scenes, this would not have bothered me and I would have probably allowed them to see it. The only way I knew that they had seen it was when they began quoting some of the funniest portions of the movie. When my son was being scolded for a completely unrelated matter and he started spouting "Help! Help! I'm being repressed!" I couldn't keep a straight face. What is fascinating is that they found funny all the same crazy scenes that most adults (at least those that appreciate Monty Python humor) find funny. I suppose my sense of humor has certainly started to rub off on them, as it is a little off-kilter. I remember watching the movie when I was about their age (which is 13, 12, 11, 11), and a lot of it simply went over my head. Sure, I got a lot of the sight-gags, but the subtlties were lost on me. I'm quite impressed at their insight and overall sense of humor.

Oh, and yes, they've been banned from watching it again until I feel they are old enough... or I can transfer the video to my computer and edit out those few scenes and transfer it back to a DVD.

That which we dare not name

I'm a little behind on blog reading... so much so right now that I just now noticed that Danny has, ahem, posted this little ditty regarding some internal "chastising" as of late... Oh, and pay no attention to the Delphi 9 behind the curtain....

Delphi 7 patch imminent

Looks like the promised patch to Delphi 7 is about to hit the streets. Several others have mentioned it as well. This week looks promising for it being live on the registered user's site.