Frage zu Generics

Für Fragen von Einsteigern und Programmieranfängern...
Antworten
Benutzeravatar
photor
Beiträge: 209
Registriert: Mo 24. Jan 2011, 21:38
OS, Lazarus, FPC: Arch Linux (L 2.0.10 FPC 3.2.0)
CPU-Target: 64Bit

Frage zu Generics

Beitrag von photor »

Hallo Forum,

ich habe eine Unit, die unter Delphi eingesetzt wird und die ich jetzt auch für Lazarus/fpc nutzen würde. In dieser werden Generics genutzt (und auch in sinnvoller Weise, wie ich denke). Da ich nicht die ganze Unit hier posten möchte, habe ich mal den Code eingedampft:

Code: Alles auswählen

 
unit BLAHUtils;
 
{$mode delphi}{$H+}
 
interface
 
uses
  SysUtils,
  Classes,
  Generics.Defaults,
  Generics.Collections,
  Math;
 
type
 
  TCycle = class
    Amp : Single;
    Mean : Single;
    isHalf : boolean;
    Constructor Create(); overload;
    Constructor Create(const FromValue: Single; const ToValue : Single; const isHalf : boolean); overload;
  end;
 
  TOneCycle = class
    Name : string;
    FileName : string;
    WeightFactor : Double;
 
    LoadCycleList : TList<TCycle>;   // <--- hier bekomme ich den Syntax-Error
 
    constructor Create(ID : integer);
    destructor Destroy(); override;
 
    // ... some more functions defined
 
///// Fehlermeldung:
/////BLAHUtils.pas (....): Error: Identifier not found "TList$1"
/////BLAHUtils.pas (....): Error: Illegal expression
 


Ich habe schon ein "{mode delphi}" eingefügt. Die beiden USES "Generics.Defaults" und "Generics.Collections" werden nicht gefunden; also habe ich sie auskommentiert - aber bslang keinen wirklichen Ersatz gefunden (außer vielleicht "uses fgl" s.u.).

Die Fehlermeldung (im CODE-Bereich angegeben) deutet darauf hin, dass der Compiler nichts mit der generics-Definition "TList<TCycle>" anfangen kann (klar, ich habe ja die beiden Units nicht mehr im USES-Teil).

Das, was ich im Netz gefunden habe, kann ich nur so halb deuten und verwirrt mich gerade mehr als dass es hilft. Deshalb frage ich hier nach.

Was ich verstanden habe, deute ich so, dass ich "uses fgl" (Free Pascal Generics Lib) hinzunehmen muss und dann "TList<...>" durch "TFPGList<...>" ersetzen muss. Ist das so richtig (was dann doch ein wenig Umbau bedeuten würde)? Allerdings war die Seite mit dieser Info auch nicht mehr ganz neu. Allerdings verstehe ich nicht, wieso das nicht einfach mit "TList<...>" gehen sollte; der Syntax ist doch auch zulässig, oder?

Danke für Eure Hilfe,
Photor

Warf
Beiträge: 1491
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: MacOS | Win 10 | Linux
CPU-Target: x86_64
Wohnort: Aachen

Re: Frage zu Generics

Beitrag von Warf »

Schau mal hier: Link

Du willst wahrscheinlich die unit fgl benutzen, und daraus die klasse TFPGList, oder viel wahrscheinlicher TFPGObjectList (da du mit klassen arbeitest).

Beispiel:

Code: Alles auswählen

... 
uses fgl;
...
TCycleList = specialize TFPGList<TCycle>;
...
  LoadCycleList : TCycleList;
...
 

Benutzeravatar
photor
Beiträge: 209
Registriert: Mo 24. Jan 2011, 21:38
OS, Lazarus, FPC: Arch Linux (L 2.0.10 FPC 3.2.0)
CPU-Target: 64Bit

Re: Frage zu Generics

Beitrag von photor »

moin Warf,

das ist ungefähr auch mein bisheriger Stand. Ich hatte nur gedacht (gehofft), dass es neueres gibt und die Unterschiede zwischen Delphi und Lazarus mittlerweile geringer sind (das was ich gefunden hatte, war so aus 2015, 2017).

Schade. Aber Danke

ciao,
Photor

Warf
Beiträge: 1491
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: MacOS | Win 10 | Linux
CPU-Target: x86_64
Wohnort: Aachen

Re: Frage zu Generics

Beitrag von Warf »

photor hat geschrieben:das ist ungefähr auch mein bisheriger Stand. Ich hatte nur gedacht (gehofft), dass es neueres gibt und die Unterschiede zwischen Delphi und Lazarus mittlerweile geringer sind (das was ich gefunden hatte, war so aus 2015, 2017).


Nö, seit dem Delphi die Namespaces eingeführt hat, hat Lazarus das nicht mit übernommen. MMn. machts auch keinen sinn TList mit zwei verschiedenen Klassen zu überladen, einmal in Classes Unit, und einmal als Generischer datentyp. Ich finde TFPGList jetzt nicht den schönsten namen, aber immerhin ists nicht der gleiche wie eine bestehende Klasse (die vor allem auch noch sehr viel benutzung findet).

Und das mit specialize und dem kram kannst du durch $MODE Delphi umgehen, ist halt einer der Syntaktischen Unterschiede zwischen FPC und Delphi. Wenn dus möglichst identisch haben willst, erstell ne eigene Unit "Generics.Collections" und füg da ein:

Code: Alles auswählen

unit Generics.Collections;
{$Mode objfpc}{$H+}
 
uses fgl;
 
interface
 
type generic TList<T> = class(specialize TFPGList<T>);   
 
end.


Und du hast deine Delphi kompatibilität

Benutzeravatar
photor
Beiträge: 209
Registriert: Mo 24. Jan 2011, 21:38
OS, Lazarus, FPC: Arch Linux (L 2.0.10 FPC 3.2.0)
CPU-Target: 64Bit

Re: Frage zu Generics

Beitrag von photor »

Danke Warf,

Ich werde mal damit rum spielen. Ich hätte es halt schöner gefunden, wenn die Unterschiede zu Delphi geringer wären (ich muss halt beides nutzen). Mein Einblick in die Innereien beider ist zu gering, als dass ich sagen könnte, was sinnvoller oder schöner ist.

Da ich bislang noch kaum mal mit Generics in Berührung gekommen bin, war ich von der Lesbarkeit der Delphi-Unit überrascht. Mal sehen, wie das mit Lazarus aussieht.

Nachtrag: ich hatte auch deshalb gefragt, weil ich bei meiner Recherche auf https://github.com/maciej-izak/generics.collections gestoßen bin.

Ciao,
Photor

Benutzeravatar
photor
Beiträge: 209
Registriert: Mo 24. Jan 2011, 21:38
OS, Lazarus, FPC: Arch Linux (L 2.0.10 FPC 3.2.0)
CPU-Target: 64Bit

Re: Frage zu Generics

Beitrag von photor »

Moin,

ich probiere das gerade und arbeite mich durch die Unit. Dabei bin ich jetzt auf folgendes getroffen:

Code: Alles auswählen

 
    DELarray : TArray<TArray<DEL>>;
 

wobei DEL selbst eine relative einfache Klasse ist:

Code: Alles auswählen

 
  TDEL = class
    W : Double;
    Count : Double;
    DEL : Double;
    constructor create();
  end;
 

Mein Versuch, das zu ersetzen

Code: Alles auswählen

 
 {$ifdef FPC}
    DELarray : specialize TFPGArray<TFPGArray<DEL>>;
{$endif}
 

funktioniert nicht. Hat jemand eine Idee, wie man solche verschachtelten Definitionen auflösen kann? (ich habe das jetzt noch nicht tiefer analysiert, und weiß noch nicht, wie sinnvoll eine solche Definition ist). Oder fehlt das TArray<T>-Konstrukt gar ganz (wenn die Unit unter /usr/lib/fpc/src/rtl/objpas/fgl.pp liegt, dann finde ich was in der Art tatsächlich nicht)?

Ciao,
Photor

Socke
Lazarusforum e. V.
Beiträge: 2799
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: Frage zu Generics

Beitrag von Socke »

photor hat geschrieben:Mein Versuch, das zu ersetzen

Code: Alles auswählen

 
 {$ifdef FPC}
    DELarray : specialize TFPGArray<TFPGArray<DEL>>;
{$endif}
 

funktioniert nicht. Hat jemand eine Idee, wie man solche verschachtelten Definitionen auflösen kann? (ich habe das jetzt noch nicht tiefer analysiert, und weiß noch nicht, wie sinnvoll eine solche Definition ist). Oder fehlt das TArray<T>-Konstrukt gar ganz (wenn die Unit unter /usr/lib/fpc/src/rtl/objpas/fgl.pp liegt, dann finde ich was in der Art tatsächlich nicht)?


Von der Syntax her musst du auch den inneren Generic spezialisieren:

Code: Alles auswählen

DELarray : specialize TFPGArray< specialize TFPGArray<DEL> >;
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

Benutzeravatar
photor
Beiträge: 209
Registriert: Mo 24. Jan 2011, 21:38
OS, Lazarus, FPC: Arch Linux (L 2.0.10 FPC 3.2.0)
CPU-Target: 64Bit

Re: Frage zu Generics

Beitrag von photor »

Moin,

ich frage mich nur langsam, wie übersichtlich das noch ist bzw. wie unübersichtlich es werden kann und ob man es besser um-arrangiert. Damit würde ich dann natürlich die originale Unit ändern. Ob ich das will ... ?

Ich ackere mich mal weiter durch.

Ciao,
Photor

Nachfrage: gibt es TFPGArray überhaupt? Ich kann die Definitin dazu nicht finden - bis jetzt?

Socke
Lazarusforum e. V.
Beiträge: 2799
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: Frage zu Generics

Beitrag von Socke »

photor hat geschrieben:Nachfrage: gibt es TFPGArray überhaupt? Ich kann die Definitin dazu nicht finden - bis jetzt?

Es gibt den generic TArray. Da es in Free Pascal keinen generischen Array Helper gibt, hat es bis auf die Delphi-Kompatibilität kaum einen Mehrwert, TArray zu verwenden (siehe Diskussion hier im Forum).
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

Antworten