Tue, 31 Oct 2006
Delphi Naming Non-Conventions
It often happens in programming that you need to name two things that are
similar but different. This can be a difficult task, but one would expect
that if you were designing a language or its standard library you'd put
extra effort into your naming. Sadly, it sometimes seems that the people
designing Delphi didn't put in that effort. For a simple example,
consider division by zero. If you try to divide by zero, Delphi generates
an exception at runtime, but if you were doing an integer divide the
EDivByZero, whereas floating-point division generates
For a more extreme example, let's look at String comparisons. Delphi has functions for native Delphi strings and C-style null-terminated strings, functions for case-sensitive and case-insensitive comparison, functions that understand multibyte character coding systems and use Windows locale info and functions that don't, and some null-terminated functions that also take a character count (analogous to strncmp).
|Function||String Type||Multibyte-aware||Case-Sensitive||Specify Length|
Granted, the null-terminated functions are pretty consistent with their Ls
and Is, but I can never remember which of
is which (not to mention remembering which names are for null-terminated
strings and which are for Delphi strings). And the rule of thumb is to
always use the
Ansi functions, because they honor locale orderings.
Presumably the non-
Ansi functions are around because they're faster
(they do a straight numeric compare on the ordinal value of each
character), but the naming implies that they should be the default.
Another hairy mess of naming I run into moderately often is the task of
TDateTime into a string. Should I use
TimeToStr, which each take one parameter (the
TDateTime variable) and
use several global variables to determine their formatting? Should I use
FormatDateTime, which takes two parameters: the
TDateTime variable and
a format string? Should I use
DateTimeToStr, which works just like
FormatDateTime, but takes a third parameter, a string variable passed by
reference, into which the result is placed? (
FormatDateTime are Delphi functions while
DateTimeToStr is a
Format to be Delphi's analog to
sprintf, and use it
exclusively, but Delphi provides
Format is a function that returns a formatted Delphi string.
is a procedure that gets its result variable passed in by reference.
FormatBuf is the direct analog to
snprintf: you must pass in the
result variable and the format string as
PChars, as well as the lengths
of those two strings; the result is placed into the passed variable and
the function returns the length of that string.
StrUpper upcases an entire
AnsiStrUpper does the same, but
understands multibyte encodings and honors the Windows locale.
AnsiUpperCase are the same, but for Delphi strings.
UpCase upcases a single character.
Low gives the lowest value of a range type or the lowest index of an
Lo gives the low-order byte of an integer. Likewise,
gives the highest value of a range type or the highest index of an array
Hi gives the high-order byte of an integer. (More properly,
returns the second-lowest-order byte of an integer; it assumes all
integers are 16-bit.)
Trunc takes a floating point number and truncates it to an integer.
Truncate deletes all data in a file past the current seek point. I use
Trunc just rarely enough that I almost always use
Truncate when I mean
I suppose all languages have similar issues (I'm reminded of Common Lisp
schar, and (I
row-major-aref), but in most other cases, I don't often find
myself trying to decide which of several similarly-named functions is the
right one and which is wrong. Delphi's setup just feels more muddied to