Operator wyboru w Delphi

Patryk27

Jak wszyscy wiedzą, w Pascalu nie istnieje C++'owski operator wyboru (conditional operator):
warunek?wartość_true:wartość_false i co najwyżej można użyć ifthen oraz tym podobnych funkcji.
Postanowiłem więc trochę pokombinować i napisałem taki kod (dla FPC>=2.6; w nowszych Delphi także powinien działać):

{$MODE DELPHI}

Type TLazy<T> = Record
                 Type TFunc = Function: T;
                 Class Function Lazy(aCondition: Boolean; aTrue, aFalse: T): T; static;
                 Class Function LazyFunc(aCondition: Boolean; aTrue, aFalse: TFunc): T; static;
                End;

Class Function TLazy<T>.Lazy(aCondition: Boolean; aTrue, aFalse: T): T;
Begin
 if (aCondition) Then
  Result := aTrue Else
  Result := aFalse;
End;

Class Function TLazy<T>.LazyFunc(aCondition: Boolean; aTrue, aFalse: TFunc): T;
Begin
 if (aCondition) Then
  Result := aTrue() Else
  Result := aFalse();
End;

Function Val1: Integer;
Begin
 Writeln('Val1');
 Result := 10;
End;

Function Val2: Integer;
Begin
 Writeln('Val2');
 Result := 20;
End;

Begin
 Writeln(TLazy<Integer>.LazyFunc(False, Val1, Val2));
 ReadLn;
End.

Kod zwróci:

Val2
20

Istnieją dwa typy jego wywołań:

TLazy<nazwa typu>.Lazy(warunek, wartość dla true, wartość dla false)

oraz

TLazy<nazwa typu>.LazyFunc(warunek, funkcja dla true, funkcja dla false)

Różnica jest taka, iż w przypadku użycia pierwszej opcji (Lazy), obliczona zostanie wartość funkcji (czyli nota bene funkcja zostanie wywołana wtedy, gdy nie będzie ona potencjalnie potrzebna), podczas gdy używając drugiej (LazyFunc), wywoływana jest tylko jedna, wymagana funkcja.

Korzystając z Delphi, można ten kod uzupełnić o anonymouse functions, ale ja (tj.autor tego kodu) akurat nie jestem w posiadaniu takiego.
Jak ktoś chce, może śmiało edytować ten kod.


Kod wrzucam, ponieważ może komuś się przydać.

3 komentarzy

Tak, niestety dla leniwego wywołania trzeba pokombinować.

O ile pamiętam, po podstawieniu funkcji za parametr (korzystając z Twojego kodu), zostanie ona wywołana tak czy siak.
Dało się to co prawda uniknąć wskaźnikami, no ale...

Tyle zachodu żeby zrobić VBasicowego IIF-a...

A wystarczy:

function IIF(const ACondition: boolean;
const ATrueValue, AFalseValue: Variant): Variant;
begin
if ACondition then
Result := ATrueValue
else
Result := AFalseValue;
end;

A potem:
WriteSimpleElement('Enabled', IIF(Self.Enabled, 'True', 'False'));