About namespace, scopes and collisions

I was recently reading Raymond Chen’s blog The curse of the redefinition of the symbol HLOG. Although not exactly the same issue, it reminded me of a situation a coworker requested help on a long time ago.

The root of the issue was pretty simple, my colleague had the error E2037 Declaration of ‘SomeProc’ differs from previous declaration.

Now,  most of the time, this is a pretty trivial error to correct. But I was initially baffled by the problem. Here’s what the declaration looked like :

type
  TSomeClass = class
[...]
    Procedure SomeProc(ABitmap : TBitmap);
[...]
procedure TSomeClass.SomeProc(ABitmap : TBitmap);
begin
end;

Now, I don’t know about you, but the declarations look the same to me. It took me a few minutes to realize the source of the problem. Here’s what the fix looked like :

type
  TSomeClass = class
[...]
    Procedure SomeProc(ABitmap : TBitmap);
[...]
procedure TSomeClass.SomeProc(ABitmap : Graphics.TBitmap);
begin
end;

Now, why was it required to use the full scope name in the function implementation? It so happens that, in the unit where the class was declared, the interface section had a use on Graphics.pas and the implementation had a use on Windows.pas. For this reason, TBitmap in the interface section was being interpreted as Graphics.TBitmap while TBitmap in the implementation section was interpreted as Windows.TBitmap.

Implicit scoping saves a lot of typing, especially now that Delphi uses doted namespace. I wouldn’t want to be required to type
Generics.Collections.TList<System.Classes.TAction> everytime I want to declare a list of TAction. That being said, like I mentioned recently, implicit behaviors can really reserve you surprises when you are not aware of them.

One of the caveat of high level programming

After I decided to study computer science, but before I actually started classes, I was scared. I was scared computer science (programming mostly) would be way too hard for me.

Part of that scare came from my total lack of knowledge on the subject. All I knew about EXE files was what I learned opening those in a hex editor.  I started thinking programming was about writing “stuff” in hexadecimal, and if aligned properly inside a file, magic happened! Thankfully, it is not the case. If only I had known what a compiler was back then…

Compiler are powerful tools that allows to transform instructions in plain text into machine code. The use of compilers has many advantages. They can hide the details of the hardware. A new CPU comes around with new, better performing instructions for a specific task? As soon as an update to the compiler is available you can simply update the compiler and rebuild your project without altering a single line of code and you can take advantage of the new instructions. There’s more than 1 sequence of instructions that can do what you ask on the hardware level?  Well, the compiler knows which one (or should know) performs it best.

But compilers can create quite a few “problems”. One of the problems that arise from compiler technologies is that pretty often, programmers are not 100% aware of what the machine does “behind the scene” given some lines of codes.  The Delphi language is especially rich in “implicit” stuff going around. Notably, string/array management.

When I started to work with the Exception class, one of the thing I wondered was, what was the point of its constructor CreateFmt. I was asking myself “What’s the difference between those 2 lines:”

  raise Exception.Create(Format(SSomeConstant, [1]));
  raise Exception.CreateFmt(SSomeConstant, [1]);

It took me many years before I stumbled upon information that allowed me to extrapolate the reason for the existence of CreateFmt. Granted, the difference between the 2 isn’t meaningful for most(99%) intent and purpose.

The reason why the 2 exists is partly because of the compiler doing a lot more than we know about. Lets take an example

procedure CheckValue(AValue : Integer);
begin
  if AValue > 10 then
    raise Exception.create(Format(SValueTooHigh, [AValue]));
end;

what you are really doing is

procedure CheckValue(AValue : Integer);
var ImplicitStringVariable : string;
begin
  ImplicitStringVariable := '';
  try
    if AValue > 10 then
    begin
      ImplicitStringVariable := Format(SValueTooHigh, [AValue])
      raise Exception.create(ImplicitStringVariable);
    end;
  finally
    DecRefCount(ImplicitStringVariable);
  end;
end;

while using Exception.CreateFmt really do only

procedure CheckValue(AValue : Integer);
begin
  if AValue > 10 then
    raise Exception.createFmt(SValueTooHigh, [AValue]);
end;

Of the few tests I’ve made, Using Exception.CreateFmt instead of Exception.Create(format) made the function about 8 times faster when no exceptions where raised. In situation where performance matters, it’s quite a difference. (ok, in situation where performance matters, exceptions wouldn’t be used 😉 )

Moral of the story, the higher level the language, the more things happening implicitly in the background. And those things doesn’t always make sense.  This video express it better than I could ever do.