Donnerstag, 5. Dezember 2013

Delphi and the (still a little bit missing) ternary operator

One of the things I missed in Delphi is the ternary operator, that I learned to love and use in other programming languages. It helps saving lines of code and in most cases is more readable than the longer annotation. Look for example at the following example in C/C++/Java syntax:
if SomeBooleanVal {
  a = b;
} else {
  a = c;
}
SomeFunction(a);

There are several lines of code which could be just one easy readable line width the same meaning:
SomeFunction(SomeBooleanVal ? b : c);

Since Delphi 7 (or 6?) there is an IfThen function in StrUtils and Math lib supporting similar functionality for string, Integer, Int64 and Double data types.

So look at the following example for detailed code:
if SomeBooleanVal
  a := b
else
  a := c;
SomeFunction(a);

And now at the much shorter code:
SomeFunction(IfThen(SomeBooleanVal, b, c);

While it helps keeping the code simpler, it sill has its limitations. The function is only defined for four data types and you would have to write another function for every data type you need which is not one of the four. The other limitation is simply the fact that it is a function and not a compiler feature like in other languages so there is no laziness possible. If you submit something more complex as b and c parameters like d *10 - e / 5, both values are evaluated first and the result of them sent to the function which would return the correct result depending on the boolean value. In C only the needed of both values would be evaluated and assigned to the target variable.
Of course with today's machines it's not the most ugly loss of efficiency, it still shows some limitations of a language design.

Edit:
+Eric Grange pointed another simple case which IfThen can't handle:
a := IfThen(c<>0, b/c)

Because evaluation happens before check you will get division by zero if c is zero.

Mittwoch, 4. Dezember 2013

Delphi and missing Windows API functions

When I had to write a Windows service using Delphi 2010, which is possible thanks to WinSvc.pas, which is based on winsvc.h from Windows SDK, I found several functions just missing from the pascal unit. One of the functions I missed was ChangeServiceConfig2, which I could use to set extended service properties without fiddling with registry and setting some string and DWORD values.
I decided to go deep into the old SDKs to see what version the unit represents and was very surprised that it still had more or less the stand of Win9x line, though I'm not sure of WinME because I couldn't find it's SDK or advapi32.dll. While at least the function EnumServicesStatusEx was already in NT4.0 (but not in Win98FE), many new functions came with Win2k SDK (including ChangeServiceConfig2 which I intended to use) which was released in 2000. With Delphi support for WinXP (released in 2001) which is supported since Delphi 7 (released in 2002) they still didn't implement the new and missing WinAPI bindings and this seems to be still the situation as of today.

I decided to properly implement all the missing functions and structures of winsvc.h from Win2k SDK and so far have added extensions from WinXP SDK. (Here it's just the same as Win2k + two new constants) and currently I'm in the process of adding the extensions which came with Windows Vista, but this is WIP yet.

Because the might be several other API binding missing I decided to create a small project for this, so all the binding extensions can live in one central place. You will find the WIP source and the "stable" releases of the units here: https://github.com/rarog/winapi-for-delphi.