Pamiętacie mój dawny wpis na blogu, w którym opisałem kilka swoich przemyśleń na temat modernizacji składni Pascala? Traktował on m.in. o fuzji bloków kontrolnych, określeniu skoku iteratora pętli for
oraz o deklaracji zmiennych w dowolnym miejscu ciała podprogramu, na wzór najpopularniejszych języków programowania.
No i ostatnia propozycja, czyli punkt B., właśnie wchodzi w życie – dla stałych i zmiennych, ogólnych i dla pętli. ;)
Introducing Inline Variables in the Delphi Language
The coming 10.3 version of Delphi introduces a very handy feature to the language, local inline variables with local scope and type inference.
The Delphi language in 10.3 has a fairly core change in the way it allows far more flexibility in the declaration of local variables, their scope and lifetime. This is a change that breaks a key tenet of the original Pascal language, but offers a significant number of advantages, reducing unneeded code in several cases.
Jeśli o mnie chodzi, to jest to świetna wiadomość.
Przez chwilę miałem nadzieję na to, że może jednak będę miał możliwość używania nowych konstrukcji – w końcu FPC cały czas jest w pełni kompatybilny ze składnią Delphi. Niestety moja nadzieja gaśnie z każdą chwilą, ze względu na wypowiedzi ważnych graczy w tym wątku…
Wychodzi na to, że deweloperzy zmian nie doceniają, nie chcą implementować inline'owanych deklaracji zmiennych, a co gorsze (dla całego projektu, nie dla mnie), uznają tę nowość za dobry powód do zerwania kompatybilności z Delphi. Wolą zostać przy pradawnej, zardzewiałej składni oraz twierdzić, że jedyne słuszne i najlepsze rozwiązanie to to obecne. Taki beton, o który rozbija się w drobny mak większość sensownych pomysłów modernizacji składni. :/
Sam w dalszym ciągu uważam, że połączenie wewnętrznych deklaracji lokalnych zmiennych w połączeniu z inferencją typów to funkcjonalność, która powinna zostać dodana do składni już dawno temu i której mi ciągle cholernie brakuje.
#fpc #free-pascal #lazarus #delphi
Koniecznie z wykorzystaniem inferencji i koniecznie dla obu typów pętli – for to/downto do
i for in
.
for var Item in Collection do // miodzio
Już nawet tym bym się od biedy zadowolił…
Co jakiś czas ktoś – celowo lub przy okazji – pyta się na forum, czy referencja w Pascalu to wskaźnik, czy nie wskaźnik. Uściślijmy więc.
Tak, referencja instancji klasy to wskaźnik, co prawda traktowany jest w odmienny sposób, jednak to nie zmienia faktu bycia wskaźnikiem. Aby sprawdzić to w praktyce, wystarczy referencję zrzutować na pointer, a ten następnie z powrotem na referencję konkretnej klasy.
Przykład testowej aplikacji poniżej:
uses
Classes;
var
ListObj: TStringList;
ListPtr: Pointer;
begin
ListObj := TStringList.Create();
try
ListObj.Add('free pascal');
ListPtr := Pointer(ListObj); // przerobienie referencji na wskaźnik
ListObj := TStringList(ListPtr); // przerobienie wskaźnika na referencję
Write(ListObj.Text);
finally
ListObj.Free();
end;
end.
Dwa rzutowania i wszystko jasne. Miszung ze wskazaniami nie sprawi, że w linijce z wyświetleniem zawartości listy dostaniemy wyjątek.
Gdzieniegdzie, raczej w starych kodach pisanych np. w Delphi 7, można spotkać konwersję referencji na zwykłą liczbę, w celu jej przesłania w parametrze razem z komunikatem.
Druga sprawa – czasem ktoś wpada na pomysł, aby wykorzystać zwykłą procedurę jako zdarzenie jakiegoś obiektu. I też pojawiają się różne zdania na temat tego, czy da się, czy jednak się nie da. Otóż, bezpośrednio nie da się – zmienna zdarzeniowa nie jest pointerem, więc nie można do niej przypisać adresu zwykłej procedury. A czym jest? Nie jest to jeden wskaźnik, a dwa – jeden przechowuje adres kodu do wykonania, a drugi wskazuje na dodatkowe dane.
Aby móc użyć zwykłej procedury jako zdarzenia, należy przypisać adres tej procedury do pierwszego wskaźnika. A co z drugim, tym na dane? Cóż, można w nim przesłać adres czegokolwiek – wyślijmy więc referencję obiektu, aby dopełnić pierwszą część tego wpisu. ;)
Prosty przykład:
uses
Classes;
procedure OnListChange(ASender: TObject); // zwykła procedura, zgodna z TNotifyEvent
var
List: TStringList absolute ASender;
begin
Write(List.Text);
end;
var
List: TStringList;
Method: TMethod; // TMethod reprezentuje wymaganą strukturę wskaźników
begin
List := TStringList.Create();
try
Method.Code := @OnListChange; // przypisanie adresu zwykłej procedury
Method.Data := List; // przypisanie referencji (ta podana zostanie w parametrze ASender)
List.OnChange := TNotifyEvent(Method); // ustawienie przygotowanego zdarzenia (rzutowanie konieczne)
List.Add('free pascal');
finally
List.Free();
end;
end.
Po wywołaniu metody Add
, wartość jej parametru zostanie dodana do listy, po czym instancja odpali zdarzenie OnChange
, o ile zostało ustawione. My to zrobiliśmy, więc zostanie wykonana procedurka OnListChange
– na ekranie konsoli pojawi się zawartość listy, czyli w tym przypadku napis free pascal
.
#free-pascal #lazarus #delphi
Referencja to referencja. To czy referencja jest samym tylko wskaźnikiem, czy jakimś opakowanym, czy czymś więcej - to szczegół implementacyjny.
Owszem, jednak aby wiedzieć z czym ma się do czynienia i co niestandardowego można z referencjami zrobić, warto zagłębić się w temat i podłubać. W razie kolejnego ciekawskiego, będę mógł podlinkować ten wpis, zamiast znów tłumaczyć to samo. :P
Wczoraj napisałem i opublikowalem w tym sersie artykuł o specyficznej liście dwukierunkowej; Opisuje on sposób implementacji dwukierunkowej listy, korzystającej ze znacznika, czyli wskaźnika pamiętającego ostatnio użyty węzeł listy. Dzięki temu znacznikowi, przeszukiwanie listy jest znacznie szybsze niż jej tradycyjnego odpowiednika;
Artykuł znajduje się pod poniższym adresem:
Jest do druga część cyklu artykułów dotyczących implementacji list wskaźnikowych w języku Free Pascal; Pierwsza część opisywała sposób implementacji listy jednokierunkowej i wyszła spod ręki @babubabu; Artykuł ten znajduje się pod poniższym linkiem:
Mam nadzieję, że artykuł przyda się i ktoś skorzysta z proponowanych implementacji; W każdym razie życzę miłej lektury, a w razie pytań proszę o kontakt, ewentualnie wątki w dziale http://4programmers.net/Forum/Newbie lub http://4programmers.net/Forum/Delphi_Pascal.
#fpc #lazarus #delphi
Przed chwilą popełniłem taką linijkę:
tknToken := ATokens[intToken] as TToken;
i może sprawiać wrażenie pokręconej - wszędzie to słowo Token
; Jednak wszystkie cztery użyte identyfikatory wskazują na zupełnie inne typy:
tknToken
- lokalny obiekt klasy TToken
(użyta notacja węgierska),ATokens
- argument metody jako obiekt klasy TObjectList
,intToken
- lokalny iterator pętli typu Int32
(także użyta notacja węgierska),TToken
- klasa pojedynczego tokenu;To chyba najlepszy przykład jaki kiedykolwiek "odkryłem", który pokazuje jak przydatne jest stosowanie się do standardów nazewnictwa oraz używanie notacji węgierskiej :)
#pascal #fpc #lazarus #delphi
@vpiotr: Nazywaj to jak chcesz - dla mnie jest o wiele bardziej czytelna taka postać, niż jakakolwiek inna ;P
Jednak to nie jest "Smurf Naming", bo notacja węgierska to wyklucza; Poza tym wszystkie identyfikatory dotyczą pojedynczego tokenu lub listy tokenów, więc nie muszę ich nazywać TokenLoop
, TokensList
, TokenLocal
i TTokenClass
- każdy to Token
, a ich unikalność zapewniają konwencje nazewnictwa.
tknToken := ATokens[intToken] as TToken;
@furious programming: w tym wypadku napisałbym token := ATokens[idx] as TToken;
Ukończyłem właśnie prace nad komponentem TFuriousLabel
, czyli przeznaczonym dla środowisk Delphi projektem etykiety, której zawartość można formatować znacznikami HTML; Może także posiadać klikalne linki, co jest niestandardową funkcją etykiet zawartych w VCL;
Zainteresowanych zapraszam do dedykowanego wątku: http://4programmers.net/Forum/Off-Topic/Oceny_i_recenzje/239916-tfuriouslabel_-_etykieta_formatowana_znacznikami_html
#delphi #delphi7 #furious-controls #tfuriouslabel
Wczoraj miałem dość dużo wolnego czasu, więc postanowiłem nieco rozwinąć projekt mojej konsolowej gry SnakeASCII, który rozwijam w ramach rozrywki i odpoczynku od pisania specyfikacji formatu TreeStructInfo;
Udało się wprowadzić wiele sensownych zmian, m.in.:
Teraz przynajmniej można sobie pograć, bo wąż sam chodzi; Plansze można modyfikować, odpowiednio zmieniając zawartość plików (póki co jest jeden - 0.lvl
), znajdujących się w lokalnym katalogu levels
;
Gra będzie ciągle rozwijana, w każdej wolnej chwili, tak że można się spodziewać jeszcze wielu nowych rzeczy; Opis wprowadzonych zmian w stosunku do poprzedniej wersji, zawarty jest w dedykowanym wątku **http://4programmers.net/Forum/Off-Topic/Oceny_i_recenzje/234190-snakeascii_czyli_kultowy_waz_w_specyficznej_tekstowej_formie?p=1046586#id1046586**; Kod gry jest otwarty, udostępniany na licencji GNU Lesser GPL 3, więc można go wykorzystywać jak kto potrzebuje.
Przykładowy zrzut zapauzowanej gry poniżej.
#SnakeASCII #Pascal #FPC #Lazarus #Delphi
@furious programming: wlasnie myslalem ze to w srodku to waz bo ten z prawej jest przeciety a waz nie moze się przecinać i mnie zmyliło. Odpalić nie moge bo nie mam windy od dobrych 7 lat :)
Ogólnie nie jestem zwolennikiem deklaracji zmiennych gdzie się ma ochotę ale zrobienie wyjątku np dla pętli for byłoby świetnym rozwiązaniem
for var i := 1 to 10 do writeln(i);