Usprawnienia języka Delphi w nowych środowiskach Embarcadero

0

Witajcie, pytanie do znawców nowych rozwiązań w nowych środowiskach języka Delphi. Ogólnie w tym wątku przedstawiono nowości kolejnych środowisk
i z tego co widzę, nadal Delphi nie zostało usprawnione w wielu aspektach.

Czy jest możliwe inne przypisanie wartości typu Boolean do takiego przykładu jak poniżej? Jak wiadomo, standardowym przypisaniem wartości typu Boolean (jak ktoś zaczynał programować to tak pisał kod) jest:

if CheckBox.Checked = True then Label.Font.Color := clRed
else
if CheckBox.Checked = False then Label.Font.Color := clGreen;

który można skrócić do formy:

if CheckBox.Checked then Label.Font.Color := clRed
else Label.Font.Color := clGreen;

Można też zastosować takie rozwiązanie:

const
 Kolor: array [Boolean] of TColor = (clGreen, clRed);
begin
 Label.Font.Color := Kolor[CheckBox.Checked];
end;

lub takie:

with Label.Font do
 case CheckBox.Checked of
    True: Color := clRed;
   False: Color := clGreen;
 end;

Z punktu widzenia czytelności, najlepszym rozwiązaniem jest przykład nr 2.

Jednak czy istnieją inne rozwiązania w nowych środowiskach Delphi, tak jak wstawianie zmiennych po begin? (zupełna abstrakcja w pomysłach poniżej):

 //1
 Label.Font.Color := TColor(CheckBox.Checked(clRed, clGreen));

 //2
 Label.Font.Color := if CheckBox.Checked then TColor(clRed, clGreen);

 //3
 Label.Font.Color := TColor = (CheckBox.Checked = [clRed, clGreen]); 
1
Opi napisał(a):

Witajcie, pytanie do znawców nowych rozwiązań w nowych środowiskach języka Delphi. Zależy mi na przedstawieniu wszystkich możliwych nowości języka Delphi. Od czasu Delphi 2005, kiedy pojawiła się pętla for-in, czy możliwość definiowania zmiennych po słowie begin w Delphi 10.3 Rio (?), doszło mnóstwo innych usprawnień do których ciężko dotrzeć.

Czy ja wiem, czy ciężko...
Tu masz nowości dla poszczególnych wersji:
https://docwiki.embarcadero.com/RADStudio/Alexandria/en/What_Was_New_in_Past_Releases

A Ciebie interesuje to co jest opisane w sekcji RTL/Compiler.
Czytasz, sprawdzasz i opisujesz ;-)

Ale ja bym nie skupiał się tylko na nowych słowach kluczowych języka, bo to ciut mało.

Np. o tym mógłbyś zapomnieć, a to daje ciekawe możliwości:
https://docwiki.embarcadero.com/RADStudio/Sydney/en/Custom_Managed_Records

2
Opi napisał(a):

Jednak czy istnieją inne rozwiązania w nowych środowiskach Delphi, tak jak wstawianie zmiennych po begin?

jeśli pytasz o zmienne po begin, to chyba masz na myśli taki przykład:
https://blog.marcocantu.com/blog/2018-october-inline-variables-delphi.html

tak, jak najbardziej działa taki zapis od wersji 10.3, nazywa się to inline variables

mały przykład z artykułu:

procedure Test;
begin
  var I, J: Integer;
  I := 22;
  j := I + 20;
  ShowMessage (J.ToString);
end;
2

Czy jest możliwe inne przypisanie wartości typu Boolean do takiego przykładu jak poniżej?

Może o coś takiego chodziło?

Label.Font.Color := StringToColor(IfThen(CheckBox.Checked, 'clRed', 'clGreen'));

Ale nie jest to nic nowego w odniesieniu do nowych wersji Delphi.

1
Opi napisał(a):

Jednak czy istnieją inne rozwiązania w nowych środowiskach Delphi, tak jak wstawianie zmiennych po begin? (zupełna abstrakcja w pomysłach poniżej):

 //1
 Label.Font.Color := TColor(CheckBox.Checked(clRed, clGreen));

 //2
 Label.Font.Color := if CheckBox.Checked then TColor(clRed, clGreen);

 //3
 Label.Font.Color := TColor = (CheckBox.Checked = [clRed, clGreen]); 

Z tego co kojarzę to w Delphi nie, ale jako ciekawostkę podam, że w Oxygene już tak — if then else może być wykorzystany wewnątrz wyrażenia i działa to tak samo jak ternary operator w językach C-podobnych. Można by go użyć w ten sposób (wedle twoich przykładów):

Label.Font.Color := if CheckBox.Checked then clRed else clGreen;

Jednak jest to tylko cukier składniowy, dlatego że kompilator i tak wygeneruje tutaj skok warunkowy, co da taką samą wydajność jak w przypadku klasycznego ifa. Natomiast case of będzie wolniejszy nawet od zwykłej instrukcji warunkowej (w Delphi i innych językach).


Jeśli dasz radę zastąpić instrukcję warunkową prostymi obliczeniami, to możesz pójść w tę stronę — to technika zwana branchless programming. Tyle że nie widzę takiej możliwości w przypadku tych kolorów, dlatego że clRed to 0x0000FF, a clGreen to 0x008000 — nie za bardzo jest jak to przeliczyć na podstawie wartości logicznej.

Gdyby clGreen posiadał normalnie zapalone bity kanału (czyli miał wartość 0x00FF00), to wtedy bez problemu by się dało wykluczyć warunek i taki kod działałby znacznie szybciej od ifa:

Label.Font.Color := $FF shl (UInt8(CheckBox.Checked) shl 3); // 0x0000FF lub 0x00FF00

Tyle tylko, że takie rzeczy robi się wtedy, kiedy ma to sens, czyli kiedy ręcznie optymalizujemy kod, wycinamy skoki warunkowe i w ten sposób podnosimy stopniowo wydajność. W twoim przypadku nie ma to zastosowania, bo tobie zależy na skróceniu kodu, a nie na wydajności. Coś takiego można by zrobić parametryzowanymi makrami, ale Delphi ma ubogi preprocesor, więc tak czy siak kicha. :D

0
Clarc napisał(a):

Może o coś takiego chodziło?

Label.Font.Color := StringToColor(IfThen(CheckBox.Checked, 'clRed', 'clGreen'));

Ale nie jest to nic nowego w odniesieniu do nowych wersji Delphi.

W zasadzie to właśnie o taki przykład mi chodziło w odniesieniu do nowych rozwiązań języka (których de facto nie ma nadal w Delphi 11.3), ale to jak wspomniałeś nie jest nowym rozwiązaniem acz działającym. Nie znałem go, dzięki za przykład.

furious programming napisał(a):

Jeśli dasz radę zastąpić instrukcję warunkową prostymi obliczeniami, to możesz pójść w tę stronę — to technika zwana branchless programming. Tyle że nie widzę takiej możliwości w przypadku tych kolorów, dlatego że clRed to 0x0000FF, a clGreen to 0x008000 — nie za bardzo jest jak to przeliczyć na podstawie wartości logicznej.

Gdyby clGreen posiadał normalnie zapalone bity kanału (czyli miał wartość 0x00FF00), to wtedy bez problemu by się dało wykluczyć warunek i taki kod działałby znacznie szybciej od ifa:

Label.Font.Color := $FF shl (UInt8(CheckBox.Checked) shl 3); // 0x0000FF lub 0x00FF00

Też myślałem nad takim przeliczeniem i jest to ciekawe rozwiązanie. Z tymże nie chodziło tutaj o zabawę z TColor i akurat te kolory wybrałem przypadkowo do posta. Chodziło o sam zamysł rozwiązania, które można wykorzystać o ile nie ma rozwiązania w samym języku - a jak widać po Embarcadero, raczej nie zanosi się na wprowadzenie nowości w samym języku (o standardowych komponentach nie wspomnę).

2

Jako, że TColor to Integer to można skorzystać z przykładu @Clarc bez konwersji:

Label.Font.Color := IfThen(CheckBox.Checked, clRed, clGreen);

musisz tylko dodać Math (System.Math) do sekcji uses

0
Paweł Dmitruk napisał(a):

Jako, że TColor to Integer to można skorzystać z przykładu @Clarc bez konwersji:

Label.Font.Color := IfThen(CheckBox.Checked, clRed, clGreen);

musisz tylko dodać Math (System.Math) do sekcji uses

Nie istnieje przeciążona funkcja IfThen mogąca obsłużyć takie argumenty, co nie zmienia faktu, że można zrobić funkcję swoją:

function IfThen(AValue: Boolean; const ATrue: Integer; const AFalse: Integer): TColor;
begin
 if AValue then Result := ATrue
 else Result := AFalse;
end;

Jednak i tutaj w ostatecznym rozrachunku pojawia się problem z tematu, czyli brak rozwiązania w samym języku (funkcja posiada klasyczne "if then else").

0

@Opi nie wiem na jakiej wersji Delphi sprawdzasz, ale na 10.4 (Community) działa.

funkcja posiada klasyczne "if then else"

IfThen "systemowe" to też klasyczne if then else tylko w module dostarczanym przez producenta.

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.