Programowanie w języku Delphi » Gotowce

Operator wyboru w Delphi

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 komentarze

vpiotr 2012-09-13 19:15

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

Patryk27 2012-09-12 20:27

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...

vpiotr 2012-09-12 19:58

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'));