Sunday, December 12, 2010

Ternary operator ? in Delphi

Delphi does not have an ternary operator, but with templates we can do something similar:


TBool<T> = class
public
  class function IFF(aCondition: boolean; aTrue, aFalse: T): T; inline;
end;
{ TBool<T> }
class function TBool<T>.IFF(aCondition: boolean; aTrue, aFalse: T): T;
begin
  if aCondition then
    Exit(aTrue)
  else
    Exit(aFalse);
end;
I use it in ChessKISS (just for fun) in this way:
//Null moves
mate := False;
if (FUseNullMove and FAllowNullMove) and (CurrentCheck = checkNo) and (CurrentStage <> sPawnEnding) then
begin
  R := TBool<integer>.IFF(aDepth > 6, 3, 2);

  Switch;
  FAllowNullMove := False;  //do not use recursive null moves
  CurrentScore := -AlphaBeta(-aBeta, -aBeta + 1, aDepth - R);
  FAllowNullMove := True;
  Switch;

  if CurrentScore >= aBeta then
  begin
    FCache.Add(FBoard.GetBoardHash(FSide), NO_MOVE, aDepth, CurrentScore, htBeta);
    Exit(aBeta);  //Cutoff!
  end else
    if (CurrentScore <= -PieceValues[ptKing]) and (FMateExtension) then
      mate := True;
end;
The main problem with that is that both expressions are evaluated before the call is make, which it should not be a problem I we know that, but avoid expensive calls like:
TBool<boolean>IFF(i > 3, ExpensiveTrue(), ExpensiveFalse())
Since it will call both functions, both functions will be evaluated. This another example that can even be worse:
TBool<integer>IFF(list <> nil, list.Count, 'null')
If the list is null then Houston we have a problem since it will anyway evaluate List.Count.

No comments:

Post a Comment