I was thinking of an enhancement to nslookup (an utility to look up various Internet information) last night and when thinking about string parsing, I thought about a case switch on strings.

The case syntax in Delphi is as such:

case selectorExpression of
   caseList1: statement1;
    ...
   caselistn: statementn;
 else
   statements;
 end

When I  analyzed the case syntax, it consists of a single expression, followed by one or more ordinal types matching the type of the expression, followed by a (block) statement, and optionally an else section. Since there isn't a case switch for strings in Delphi, I wrote something similar to extend the language, by leveraging record methods. So, I came to the conclusion that it is an array of ordinal types and statement blocks.

I declared the above as a TCaseItem, like so:

      TCaseItem = record
        AItem: T;
        AProc: TProc;
     end;

The initial declaration for a generic case switch looks like this:

class procedure TCondition<T>.caseOf(const AItemToMatch: T; const AItems: TArray<TCaseItem>);

But when I started to try and use it, it was more convenient to write it as:

     TCondition<string>.CaseOf(AStringVar, [
     'a', procedure begin end,
     'b', procedure begin end]);

In order to support the above syntax as well as the "else" clause of a case statement, the eventual declaration became:

class procedure TCondition<T>.caseOf(const AItemToMatch: T; const AItems: array of const);
Looking at my specific usage of the TCondition<string>.CaseOf method,
     TCondition<string>.CaseOf(AStringVar, [
     'case1', procedure begin
     end,
     'case2', procedure begin
     end,
     'case3'', procedure begin
     end]);

it seemed that I had stumbled across a bug in the Delphi compiler where I have to cast anonymous methods as an IInterface before the compiler agrees to compile the code, or not execute the code while evaluating it as a parameter to the variant open array.

Of course, my specific implementation allows an else block as well, and usage is like so:

     TCondition<string>.CaseOf(AStringVar, [
     'case1', procedure begin 
     end,
     'case2', procedure begin 
     end,
     'case3'', procedure begin 
     end,
     procedure begin
      // else section
     end]);

Then it turned out people had worked on this nearly 5 years ago. For example, Lar Fosdal's generic case for strings. However, I'd like to think mine is neater. :)