Ever since introduction of the IfThenfunctions introduced in Delphi Delphi 2007 in both the Math and StrUtils units (see WayBack radstudio2007 HUpdate4 EN delphivclwin32.pdf ¹), I have been telling people that these do not perform lazy evaluation of the then and else parts which the if/then/elsestatement provides.
The newly introduced if/then/elseternary conditional operator in Delphi 13 ² (of which I am not a fan, not even of the generic workaround³) – despite the unlucky number – luckily also provides lazy evaluation of the then and else parts.
Statements and operations can be subject of optimisation by means of lazy evaluation; method arguments for function calls are always evaluated in full before calling.
Use of a ternary conditional operator results in seemingly shorter code (for Delphi not so much because the existing keywords have been re-used), but the brevity can lead to far less readable code.
The brevity usually does not lead to more optimal code generation, as most (with the exception of Delphi) language compilers can optimise from
procedure TForm48.btnTernaryClick(Sender: TObject);
begin
var s := 'My String';
var sNew :=
if CheckBox1.Checked then
Reverse2(s)
else
UpperCase2(s);
ShowMessage(sNew);
end;
procedure TForm48.btnIFThenClick(Sender: TObject);
beginvar s := 'My String';
var sNew :=
IfThen(CheckBox1.Checked, Reverse2(s), UpperCase2(s));
ShowMessage(sNew);
end;
function TForm48.Reverse2 (const s: string): string;
begin
Result := ReverseString(s);
end;
function TForm48.Uppercase2(const s: string): string;
begin
Result := UpperCase(s);
end;
Yay, naming conventions!
/s
It would be even clearer if there had been UI elements that would signal when Reverse2 and Uppercase2 had been called.
² the ternary operator has been asked for since ages – see the QC report below, but now that it’s there library developers likely will hesitate to adopt it as it breaks compatibility with less recent Delphi versions, see
Both the Stack Overflow and QC entry propose the ternary conditional operator with the ?: syntax. Delphi 13 implemented it with the if/then/else syntax (basically making the if into an operator that return a value)
³ the stack Over flow entry has this remark by Vivian to which I very much agreed and still agree, despite the current syntax reusing the if/then/else keywords.
Vivian:
Personally I would rather not see a conditional operator (i.e. ?:) introduced in Delphi as I prefer the readability of Delphi/Pascal over C and it derivative languages. I would prefer to see more innovative Delphi type solutions to something like this than to implement more C-isms.
Me:
mini-rant: I have seen very unreadable code with even very small usage of the ? ternary operator in C-like languages. The main cause is that it is yet another symbol being used, and most people using it forget to add parentheses or indentation for readability. The speed improvements that it can bring are hardly reached: most usage is just a replacement of a single if/then/else, whereas real improvement only can be gained in complex expressions that few people can maintain.
In the same entry, Wouter gives an answer that works in all Delphi versions supporting generics. Not fast, but it supports lazy evaluation:
Ok. WTF code of the day :)
How to get something that mostly acts like a ternary/conditional function.
program Project107;
{$APPTYPE CONSOLE}uses SysUtils;
type
TLazyIfThen<T:record>=recordclassfunctionIfThen(aCondition:Boolean;aIfTrue, aIfFalse:TFunc<T>):T; static;
end;
classfunctionTLazyIfThen<T>.IfThen(aCondition:Boolean;aIfTrue, aIfFalse:TFunc<T>):T;
beginif aCondition then
Result := aIfTrue
else
Result := aIfFalse
end;
begin
WriteLn(
TLazyIfThen<Integer>.IfThen(
True,
function:Integer begin result := 0end,
function:Integer begin result := 1end
)
);
ReadLn;
end.
Yeah, it’s more or less useless, but it shows that it can be done.
Leave a comment