Funktion, die "array of X" und "array of Y" akzeptiert

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Antworten
RSE
Beiträge: 462
Registriert: Mi 30. Jul 2008, 13:11
OS, Lazarus, FPC: WinXP SP3 (L 0.9.28.2 FPC 2.2.4)
CPU-Target: 32Bit
Kontaktdaten:

Funktion, die "array of X" und "array of Y" akzeptiert

Beitrag von RSE »

Hallo!

Die folgenden Funktionen implementieren Binäre Suche mit Gradientenabstieg auf jeweils einem Array vom Typ TWay bzw. TNode. Kann man diese Funktion auch so formulieren, dass Freepascal beide Typen akzeptiert, dass man sich die zweite spart (ist ja der gleiche Code)? Mir fällt nur ein das Ganze in einer generischen Klasse zu implementieren, und diese für beide Typen abzuleiten. Aber das erscheint mir irgendwie wie mit Kanonen auf Spatzen... Geht das nicht auch ohne Klasse?

Code: Alles auswählen

function NodeByID(a: array of TNode; ID: LongWord): TNode;
var
  i: Integer;
begin
  result := nil;
  if Length(a) < 1 then
    Exit;
  if Length(a) = 1 then begin
    if a[0].ID = ID then
      result := a[0];
    Exit;
  end;
  i := trunc(((ID-a[0].ID)*(Length(a)-1))/(a[Length(a)-1].ID-a[0].ID));
  if a[i].ID = ID then
    result := a[i]
  else if a[i].ID > ID then
    result := NodeByID(a[i+1..Length(a)-1],ID)
  else
    result := NodeByID(a[0..i-1],ID);
end;
 
function WayByID(a: array of TWay; ID: LongWord): TWay;
var
  i: Integer;
begin
  result := nil;
  if Length(a) < 1 then
    Exit;
  if Length(a) = 1 then begin
    if a[0].ID = ID then
      result := a[0];
    Exit;
  end;
  i := trunc(((ID-a[0].ID)*(Length(a)-1))/(a[Length(a)-1].ID-a[0].ID));
  if a[i].ID = ID then
    result := a[i]
  else if a[i].ID > ID then
    result := WayByID(a[i+1..Length(a)-1],ID)
  else
    result := WayByID(a[0..i-1],ID);
end;
Seit er seinen neuen Computer hat, löst er alle Probleme, die er vorher nicht hatte!

Benutzeravatar
theo
Beiträge: 10869
Registriert: Mo 11. Sep 2006, 19:01

Re: Funktion, die "array of X" und "array of Y" akzeptiert

Beitrag von theo »

Gemeinsame Basisklasse definieren.

z.B.

TBase = Class
....
property ID ....
...

TWay = Class(TBase)
etc.

TNode = Class(TBase)
etc.

function BaseByID(a: array of TBase; ID: LongWord): TBase;

RSE
Beiträge: 462
Registriert: Mi 30. Jul 2008, 13:11
OS, Lazarus, FPC: WinXP SP3 (L 0.9.28.2 FPC 2.2.4)
CPU-Target: 32Bit
Kontaktdaten:

Re: Funktion, die "array of X" und "array of Y" akzeptiert

Beitrag von RSE »

hm, als ich das probiert habe, bin ich nicht auf die idee gekommen auch im Hauptprogramm ein Array of TBase für meine Liste vom Nodes zu definieren... und Array of TBase ist natürlich nicht kompatibel mit Array of TNode. Wenn ich aber auch im Hauptprogramm ein array of TBase benutze, um meine Nodes darin zu speichern, sollte es auch klappen ;-) thx
Seit er seinen neuen Computer hat, löst er alle Probleme, die er vorher nicht hatte!

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: Funktion, die "array of X" und "array of Y" akzeptiert

Beitrag von mschnell »

So was ist fürchterlich modern und heißt dann "generics": http://de.wikipedia.org/wiki/Generics" onclick="window.open(this.href);return false;

Ich weiß nicht ob FTP schon generics kann (das neuste Delphi kann es wohl).

mit FTP kann Du aber in jedem Fall den Macro-Preprozessor aktivieren und den Code für overloaded functions für mehrere Typen aus einer gemeinsamen Quelle automatisch bauen lassen.

-Michael

RSE
Beiträge: 462
Registriert: Mi 30. Jul 2008, 13:11
OS, Lazarus, FPC: WinXP SP3 (L 0.9.28.2 FPC 2.2.4)
CPU-Target: 32Bit
Kontaktdaten:

Re: Funktion, die "array of X" und "array of Y" akzeptiert

Beitrag von RSE »

rse hat geschrieben:Mir fällt nur ein das Ganze in einer generischen Klasse zu implementieren, und diese für beide Typen abzuleiten. Aber das erscheint mir irgendwie wie mit Kanonen auf Spatzen... Geht das nicht auch ohne Klasse?
Soviel zu generics, aber es geht ja (theoretisch) auch ohne, wie von theo beschrieben. Allerdings habe ich jetzt folgendes Problem: Wenn ich folgendes definiere:

Code: Alles auswählen

TBase = class
public
  ID: LongWord
end;
TBaseArray = array of TBase;
...
function FindByID (a: TBaseArray; ID: LongWord): TBase;
begin
  ...
end;
Dann bricht der Compiler in der ersten Zeile des Programms (diese ist Orange) mit der Meldung "project1.lpr(1,1) Fatal: Compilation aborted" ab (kein anderer Hinwis auf den Grund!). Zuvor bemerkt er aber in der Funktion schon einen prinzipiell möglichen Overflow und schlägt mir vor, vor der Subtraktion auf Int64 zu typecasten (in meinem Code aber tatsächlich nicht nötig, da alle IDs positiv sind). Ist FPC 2.2.2 an dieser Stelle etwa buggy? Hilft ein Update auf 2.2.4? Wenn ich die Funktion auskommentiere, dann bleibt er nur stecken, weil er die Funktion beim Aufruf nicht kennt...
Seit er seinen neuen Computer hat, löst er alle Probleme, die er vorher nicht hatte!

RSE
Beiträge: 462
Registriert: Mi 30. Jul 2008, 13:11
OS, Lazarus, FPC: WinXP SP3 (L 0.9.28.2 FPC 2.2.4)
CPU-Target: 32Bit
Kontaktdaten:

Re: Funktion, die "array of X" und "array of Y" akzeptiert

Beitrag von RSE »

Hm, es lag am rekursiven Aufruf in den letzten Zeilen (siehe erster Post)... allerdings ist diese Form des Aufrufs laut http://www.freepascal.org/docs-html/ref ... 400011.4.5" onclick="window.open(this.href);return false; seit FPC 2.2 erlaubt...
Seit er seinen neuen Computer hat, löst er alle Probleme, die er vorher nicht hatte!

_X_
Beiträge: 250
Registriert: Di 16. Dez 2008, 20:13
OS, Lazarus, FPC: aptosid (aptosid.com); Lazarus SVN gtk2+qt4; FPC 2.4.0
CPU-Target: 32/64Bit

Re: Funktion, die "array of X" und "array of Y" akzeptiert

Beitrag von _X_ »

Kann man da nicht "array of type" verwenden?

Ich habe leider gerade keine Zeit zum Testen.

mfg _X_

RSE
Beiträge: 462
Registriert: Mi 30. Jul 2008, 13:11
OS, Lazarus, FPC: WinXP SP3 (L 0.9.28.2 FPC 2.2.4)
CPU-Target: 32Bit
Kontaktdaten:

Re: Funktion, die "array of X" und "array of Y" akzeptiert

Beitrag von RSE »

Um es noch mal hervorzuheben: es ist die Übergabeweise des Teilarrays, die den Fehler verursacht, aber wie gesagt eigentlich seit FPC 2.2 erlaubt ist:
result := FindByID(a[i+1..Length(a)-1],ID)

@ _X_ : Was meinst du mit "array of type"? Als Typangabe akzeptiert es der Compiler jedenfalls nicht.
Seit er seinen neuen Computer hat, löst er alle Probleme, die er vorher nicht hatte!

RSE
Beiträge: 462
Registriert: Mi 30. Jul 2008, 13:11
OS, Lazarus, FPC: WinXP SP3 (L 0.9.28.2 FPC 2.2.4)
CPU-Target: 32Bit
Kontaktdaten:

Re: Funktion, die "array of X" und "array of Y" akzeptiert

Beitrag von RSE »

Ich hab es jetzt mit Copy ausgedrückt und schon klappt es (in Kombination mit den anderen Tipps) :-D
Seit er seinen neuen Computer hat, löst er alle Probleme, die er vorher nicht hatte!

_X_
Beiträge: 250
Registriert: Di 16. Dez 2008, 20:13
OS, Lazarus, FPC: aptosid (aptosid.com); Lazarus SVN gtk2+qt4; FPC 2.4.0
CPU-Target: 32/64Bit

Re: Funktion, die "array of X" und "array of Y" akzeptiert

Beitrag von _X_ »

RSE hat geschrieben:@ _X_ : Was meinst du mit "array of type"? Als Typangabe akzeptiert es der Compiler jedenfalls nicht.
Sry, ich habe da mal was gelesen.
Wenn ich es finde, poste ich den Link.

mfg _X_

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: Funktion, die "array of X" und "array of Y" akzeptiert

Beitrag von mschnell »

RSE hat geschrieben:Was meinst du mit "array of type"? Als Typangabe akzeptiert es der Compiler jedenfalls nicht.
Das geht tatsächlich (ob das hier was bringt, weiß ich nicht). Mein Sohn hat es jedenfalls letztens benutzt. Ich frag ihn morgen.

-Michael

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: Funktion, die "array of X" und "array of Y" akzeptiert

Beitrag von mschnell »

Er hat "Array of Class" benutzt, nictt "Array of Type".

Es tut aber dich eigentlich nicht weh, TNode und TWay als Class anstatt als Record zu definieren.

(Ich würde im Übrigen auch lieber TList oder noch besser TObjectList statt dynamischer arrays nehmen. Da sind die (Quicksort-) Sortier- und (binäre) Such-Algorithmen kostenlos dabei.

-Michael

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: Funktion, die "array of X" und "array of Y" akzeptiert

Beitrag von mschnell »

RSE hat geschrieben:Soviel zu generics, aber es geht ja (theoretisch) auch ohne, wie von theo beschrieben.
Geht "Generics" wirklich nur für Klassen ? Man kann sich doch auch "generic" Definitionen für einfache Funktionen vorstellen. Ich habe aber keine Ahnung was in FPC implementiert ist und wie.
Deshalb auch der Vorschlag mit einem Preprozessor-Makro. Damit geht es auf jeden Fall.

Etwa so (ungetestet, gcc-Preprozessor-Notoation):

Code: Alles auswählen

#define createprocedure(ptype)
procedure x(a: ptype); overload;
  var i: Integer;
  ...
  i := a.i;
  ...
end;
 
...
 
createprocedure(TNode)
createprocedure(TWay)
 
...
 
var 
  an: TNode;
  aw: WTway;
...
  x(an);
  x(aw);
...
-Michael

Antworten