Laraus V3 RC1 - Frage zu "+=" und "-="

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
MmVisual
Beiträge: 1470
Registriert: Fr 10. Okt 2008, 23:54
OS, Lazarus, FPC: Winuxarm (L 3.0 FPC 3.2)
CPU-Target: 32/64Bit

Re: Laraus V3 RC1 - Frage zu "+=" und "-="

Beitrag von MmVisual »

Ich weiß wie man guten Code schreiben muss, ich programmiere hauptsächlich für Medizintechnik. Um dafür schlussendlich entsprechende Zulassungen der Behörden zu bekommen muss (nicht nur) der Code ordentlich sein.

Und das hat rein gar nichts damit zu tun ob man nur ein ":=" oder auch ein "+=" verwendet.

Viel schlimmer finde ich den Operator "XOr" (^ in C)damit kann man so manch einem einen Haarausfall provozieren.
EleLa - Elektronik Lagerverwaltung - www.elela.de

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6216
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: Laraus V3 RC1 - Frage zu "+=" und "-="

Beitrag von af0815 »

Ich sage mal so, wenn man die 'Abkürzung' nimmt, sollte man auch die Pferdefüsse kennen :-) Ich mag die C-Abkürzungen auch nicht besonders und habe mich an die nie so richtig gewöhnt, außer ich muss mal die Sprache wechseln und was in einem C Dialekt schreiben.

Das bin ich gewöhnt, Deutsch, Englisch und Griechisch sind auch sehr unterschiedlich. Ich kann mich an die griechische Schreibweise in normaler Schreibschrift auch nicht gewöhnen (zB. gia sou statt για σου) . Also entweder richtig oder gar nicht.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

Warf
Beiträge: 1913
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: Laraus V3 RC1 - Frage zu "+=" und "-="

Beitrag von Warf »

MmVisual hat geschrieben:
Do 14. Sep 2023, 21:52
Anderseits:
Bei einem i += 5; sollte der FPC auch so klug sein und den optimierten Assembler Befehl einseztzen und kein Read-Modify-Write.
Als Programmschreiber würde ich zumindest davon ausgehen, dass solche Optimierungen der Compiler kann.
Macht er ab -O2 auch, wollte nur verdeutlichen was der unterschied ist zwischen einer reinen Inline operation wie Inc und etwas wie +, was dank Operator Überladung ja beliebigen Code hinter sich haben kann.

Übrigens was interessant ist, das Folgende:

Code: Alles auswählen

{$ModeSwitch ArrayOperators}
var
  Arr: Array of Integer;
  x: Integer;
begin
  ...
  Arr += [x];
  // bzw
  Arr := Arr + [x];
end;
Zum anhängen eines Arrays scheint keinen temporären Array zu erstellen, und scheint damit besser Optimiert zu sein als:

Code: Alles auswählen

var
  Arr: Array of Integer;
  x: Integer;
begin
  ...
  Insert(x, Arr, Length(Arr));
end;
Was ein sehr interessanter sonderfall zu sein scheint, den ich sehr Begrüße, da ich Insert sehr hässlich finde, sodass einfach + zu benutzen, under der Compiler weis das es einfach nur ein Insert ganz am ende ist, und damit sehr guten Code erzeugen kann, ist einfach genial.

MmVisual
Beiträge: 1470
Registriert: Fr 10. Okt 2008, 23:54
OS, Lazarus, FPC: Winuxarm (L 3.0 FPC 3.2)
CPU-Target: 32/64Bit

Re: Laraus V3 RC1 - Frage zu "+=" und "-="

Beitrag von MmVisual »

Code: Alles auswählen

Arr += [x];
kannte ich bisher noch nicht. Das vereinfach die dynamische Arrays deutlich.

Ich nutze zum dynamische Arrays zu haben lieber die TList. Ich mag lieber mit solchen Objekten arbeiten, auch wegen dem Freigeben vom Speicher ist das mir lieber. Wohlwissend dass es mehr RAM und Rechenzeit benötigt.
EleLa - Elektronik Lagerverwaltung - www.elela.de

Benutzeravatar
kupferstecher
Beiträge: 422
Registriert: Do 17. Nov 2016, 11:52

Re: Laraus V3 RC1 - Frage zu "+=" und "-="

Beitrag von kupferstecher »

Warf hat geschrieben:
Do 14. Sep 2023, 22:29
Zum anhängen eines Arrays scheint keinen temporären Array zu erstellen, und scheint damit besser Optimiert zu sein als:
Was spricht gegen SetLength? Umkopiert werden muss doch immer wenn sich das Array vergrößert und nicht zufällig freier Speicher direkt hinter dem bestehenden frei ist.

Warf
Beiträge: 1913
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: Laraus V3 RC1 - Frage zu "+=" und "-="

Beitrag von Warf »

kupferstecher hat geschrieben:
Fr 15. Sep 2023, 13:09
Was spricht gegen SetLength? Umkopiert werden muss doch immer wenn sich das Array vergrößert und nicht zufällig freier Speicher direkt hinter dem bestehenden frei ist.
Lesbarkeit, z.B. sagen wir mal du liest strings ein:

Code: Alles auswählen

while not Reader.Finished do
  Lines += [Reader.ReadLine];
ist sehr klar und einfach zu verstehen was es macht. SetLength hingegen

Code: Alles auswählen

while not Reader.Finished do
begin
  SetLength(Lines, Length(lines) + 1);
  Lines[High(Lines)] := Reader.ReadLine;
end;
Hier ist einfach viel mehr drin was schief gehen kann, z.B. kannst du das Length + 1 vergessen, du kannst High und Length verwechseln, und es ist einfach viel mehr Information die man verarbeiten muss um das zu verstehen.

Man möchte beim Programmieren eigentlich möglichst nur beschreiben "Was" man machen möchte, und möglichst darauf verzichten immer genau anzugeben "wie" etwas gemacht werden soll. Das ist der Grund warum man Hochsprachen mit While oder For Loops nimmt, statt ASM mit labels und goto.
Genauso hier, ich möchte einfach was an den Array dran hängen, warum sollte ich dazu mit SetLength Code schreiben wollen wie der Array im speicehr re-alloziiert wird? Ich sag ja auch "Ich geh einkaufen" und nicht "Ich nehm mir den Schlüssel, ziehe Schuhe an, verlasse das Haus durch die Vordertür, ..."

Benutzeravatar
m.fuchs
Lazarusforum e. V.
Beiträge: 2641
Registriert: Fr 22. Sep 2006, 19:32
OS, Lazarus, FPC: Winux (Lazarus 2.0.10, FPC 3.2.0)
CPU-Target: x86, x64, arm
Wohnort: Berlin
Kontaktdaten:

Re: Laraus V3 RC1 - Frage zu "+=" und "-="

Beitrag von m.fuchs »

Aber wenn wir schon bei einer objektorientierten Hochsprache sind, warum dann noch einzeln in Arrays einlesen und nicht die bestehenden - und verständlichen - Listen verwenden?
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de

MmVisual
Beiträge: 1470
Registriert: Fr 10. Okt 2008, 23:54
OS, Lazarus, FPC: Winuxarm (L 3.0 FPC 3.2)
CPU-Target: 32/64Bit

Re: Laraus V3 RC1 - Frage zu "+=" und "-="

Beitrag von MmVisual »

Weil man mit Pascal auch kleine Microcontroller programmieren kann, damit ist der Programmierstiel ein anderer, da muss man wirklich auf die CPU Takte und den RAM Verbrauch schauen und optimieren.
EleLa - Elektronik Lagerverwaltung - www.elela.de

Mathias
Beiträge: 6209
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Laraus V3 RC1 - Frage zu "+=" und "-="

Beitrag von Mathias »

m.fuchs hat geschrieben:
Fr 15. Sep 2023, 14:42
Aber wenn wir schon bei einer objektorientierten Hochsprache sind, warum dann noch einzeln in Arrays einlesen und nicht die bestehenden - und verständlichen - Listen verwenden?
Hast du mal TList genauer angeguckt, wen man dort immer tiefer rein geht, ist man auf einmal auch bei einer dynamischen Array anbelangt.

Code: Alles auswählen

Arr += [x];
kannte ich bisher noch nicht. Das vereinfach die dynamische Arrays deutlich.
Sind das nicht alles Sachen, die momentan erst in der Trunc von FPC unterstützt werden ?
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

TSchnuckenbock
Beiträge: 72
Registriert: Do 20. Jul 2017, 23:47
OS, Lazarus, FPC: Win7 und Win10
CPU-Target: xxBit
Wohnort: Südheide (Schnuckenland)

Re: Laraus V3 RC1 - Frage zu "+=" und "-="

Beitrag von TSchnuckenbock »

m.fuchs hat geschrieben:
Do 14. Sep 2023, 21:19
MmVisual hat geschrieben:
Do 14. Sep 2023, 19:44
Ein

Code: Alles auswählen

I += 1;
I := l + 1;
Bei der ersten Zeile sieht man sofort dass es ein Increment sein soll. Bei der zweiten Zeile muss man schon genau hinschauen dass es 2 unterschiedliche Variablen sind.
Wer solche Variablennamen benutzt, hat Probleme aber auch ein bisschen verdient. :wink:
Die Aussage war letzte Nacht mein Highlight, als ich es laß. :lol:

Wie war das nochmal mit selbstbeschreibenden Variablennamen? Da war doch was....

Wenn ich mich recht erinnere, dann bekamen wir damals vor gut 30 Jahren beim Studium schon von dem einen Programmierkurs-Professor den Tip, auf lesbaren und leicht verständlichen Code zu achten. Die Begründung: Die Rechner werden immer schneller werden und es wird immer mehr Speicherplatz kostengünstig zur Verfügung stehen.
Die Zeiten, optimierten Code bzgl. Rechenzeit und Speicherplatz zu schreiben, wären immer mehr vorbei.

Ich schlag mich seit Jahrzehnten mit uraltem Code rum, der noch auf Speed optimiert war. Vor 20 Jahren merkte ich auch noch, daß das notwendig war. Heute könnte man auf so ein Gefrickel locker verzichten.

Vor ein paar Jahren hatte ich just-for-fun mal ausprobiert, eine umfangreiche Rechengeschichte auf die Grafikkarte zu schubsen und es da rechnen zu lassen. Holla-die-Waldfee, da ging die Post ab. Also wer Speed rausholen will, dem sei die Grafikkarte dafür empfohlen.

Auch Auslagerung in einen separaten Thread kann manchmal eine sinnvolle Sache sein, um mehr Speed rauszuholen.

Warf
Beiträge: 1913
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: Laraus V3 RC1 - Frage zu "+=" und "-="

Beitrag von Warf »

m.fuchs hat geschrieben:
Fr 15. Sep 2023, 14:42
Aber wenn wir schon bei einer objektorientierten Hochsprache sind, warum dann noch einzeln in Arrays einlesen und nicht die bestehenden - und verständlichen - Listen verwenden?
Ganz einfach, Listen müssen gefreed werden, und können damit nicht in Records geschrieben werden (da records bei jedem assignment kopiert werden ist nicht klar wie viele Refernezen es auf eine Liste gibt).

Ich baue meine Projekte immer von simpel nach komplex. So fang ich z.B. immer an statt komplexer Datenstrukturen erstmal soweit wie möglich es mit Arrays und Records zu bauen. Fällt mir dann auf das es z.B. zu langsam, oder unflexibel ist, dann wechsel ich auf komplexere Datenstrukturen wie Listen, Hashmaps, Sets, etc.

Beispiel, ich will einfach nur den gesammten Text der Konsole Zeilenweise lesen:

Code: Alles auswählen

function ReadAllLines: TStringArray;
var
  ln: String;
begin
  Result := [];
  while not EOF(Input) do
  begin
    ReadLn(ln);
    Result += [ln];
  end;
end;
Das gleiche mit TStringList:

Code: Alles auswählen

function ReadAllLines: TStringList;
var
  ln: String;
begin
  Result := TStringList.Create;
  try
    while not EOF(Input) do
    begin
      ReadLn(ln);
      Result.Add(ln);
    end;
  except
  begin
    Result.Free;
    Raise;
  end;
  end;
end;
Der code ist viel komplizierter geworden, weil TStringList eine Klasse ist, die manuelles memory management braucht, also im Falle einer Exception (und damit das Result der Funktion undefined ist) muss ich den Speicher also freigeben.

Alternativ kann man es so machen:

Code: Alles auswählen

procedure ReadAllLines(AStrings: TStrings);
var
  ln: String;
begin
  while not EOF(Input) do
  begin
    ReadLn(ln);
    AStrings.Add(ln);
  end;
end;
Was zwar schön sauber in der Definition ist, dafür ist die callsite jetzte:

Code: Alles auswählen

sl := TStringList.Create;
try
  ReadAllLines(sl);
  // ...
finally
  sl.Free;
end;
// Im Gegensatz zu
arr := ReadAllLines;
// ...
Mit dem Array ist der code schlicht und ergreifend sauberer, sowohl an der callsite als auch bei der Definition.

Der einzige nachteil ist, Listen implementieren Geometrisches Wachstum, Arrays nicht, was dazu führt das die Array Variante deutlich weniger Performant für großen durchfluss sein kann. Andere Vorteile von Listen sind natürlich bestehende Funktionalität wie Sortieren, Suchen, etc., die man beim Array selbst bauen muss.
Daher wie gesagt, ich benutze Arrays solange es simpel und schnell genug ist, und benutz das komplexere dann wenn es wirklich nötig ist

Warf
Beiträge: 1913
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: Laraus V3 RC1 - Frage zu "+=" und "-="

Beitrag von Warf »

Mathias hat geschrieben:
Fr 15. Sep 2023, 15:33
Sind das nicht alles Sachen, die momentan erst in der Trunc von FPC unterstützt werden ?
Der Modeswitch ArrayOperators ist glaube ich schon seit 3.2 stable verfügbar. Ich weis noch wie sehr ich mich darüber gefreut habe das es das jetzt geht als ich darüber in den New Feature Artike im Wiki gelesen hab: https://wiki.freepascal.org/FPC_New_Features_3.2.0

Benutzeravatar
kupferstecher
Beiträge: 422
Registriert: Do 17. Nov 2016, 11:52

Re: Laraus V3 RC1 - Frage zu "+=" und "-="

Beitrag von kupferstecher »

Warf hat geschrieben:
Fr 15. Sep 2023, 13:52
Lesbarkeit, z.B. sagen wir mal du liest strings ein:

Code: Alles auswählen

while not Reader.Finished do
  Lines += [Reader.ReadLine];
ist sehr klar und einfach zu verstehen was es macht. SetLength hingegen

Code: Alles auswählen

while not Reader.Finished do
begin
  SetLength(Lines, Length(lines) + 1);
  Lines[High(Lines)] := Reader.ReadLine;
end;
Hier ist einfach viel mehr drin was schief gehen kann, z.B. kannst du das Length + 1 vergessen, du kannst High und Length verwechseln, und es ist einfach viel mehr Information die man verarbeiten muss um das zu verstehen.
Das Problem an der vereinfachten Variante ist, dass es eine spezielle Syntax ist, die es nur für genau den Fall der Arrayerweiterung gibt. Und da muss man sich dann fragen, lohnt sich das, die Sprache weiter zu zerklittern, für diese kleine Vereinfachung. Also ich hab mein Urteil darüber noch nicht gefällt, das Feature kannte ich bisher ja garnicht. Allerdings habe ich auch selten den Fall an ein dynamisches Array ein einzelnes Element anzuhängen, weil ich mir der dabei vorkommenden vollen Array-Kopie bewusst bin und und dann gleich eine TList nehme. Aber ja, bei kleinen Arrays warum nicht. Die ArrayOperators haben auch noch andere Tricks* drauf?

Nachtrag:
*Hab den Link mit den Featuren jetzt gelesen.

Mathias
Beiträge: 6209
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Laraus V3 RC1 - Frage zu "+=" und "-="

Beitrag von Mathias »

Allerdings habe ich auch selten den Fall an ein dynamisches Array ein einzelnes Element anzuhängen, weil ich mir der dabei vorkommenden vollen Array-Kopie bewusst bin und und dann gleich eine TList nehme. Aber ja, bei kleinen Arrays warum nicht. Die ArrayOperators haben auch noch andere Tricks* drauf?
Ich brauche dies noch relativ häufig.
Mit den neuen Operationen wird einem das Leben einfacher gemacht.

Sowas bietet echten Komfort.
Besonders das hinten anhängen.

Code: Alles auswählen

{$ModeSwitch ArrayOperators}
var
  ar:array of byte= (1,2,3);
begin
  ar := ar + [111];
  ar := [222] + ar;  
  ar := ar + ar;
Beim rendern einer Szene ist die recht praktisch.
Aber später in einer Loop gibt es schnellere Methoden.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Warf
Beiträge: 1913
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: Laraus V3 RC1 - Frage zu "+=" und "-="

Beitrag von Warf »

kupferstecher hat geschrieben:
Sa 16. Sep 2023, 11:34
Das Problem an der vereinfachten Variante ist, dass es eine spezielle Syntax ist, die es nur für genau den Fall der Arrayerweiterung gibt. Und da muss man sich dann fragen, lohnt sich das, die Sprache weiter zu zerklittern, für diese kleine Vereinfachung.
Tatsächlich ist es das nicht, es ist die existierende Operator Syntax, auch ohne den ModeSwitch kann man das einfach manuell überladen:

Code: Alles auswählen

type
  TIntArray = array of Integer;

operator +(const lhs, rhs: TIntArray): TIntArray;
begin
  Result := lhs;
  SetLength(Result, Length(lhs)+Length(rhs));
  Move(rhs[0], Result[Length(lhs)], length(rhs)*SizeOf(Integer));
end;

var
  arr: TIntArray;
begin
  arr := [1,2,3,4];
  arr += [5];
end.  
Das "Problem" ist das man für jeden Array typen es manuell überladen muss. Also der ModeSwitch bringt absolut keine neue syntax rein, er registriert einfach nur ein paar standardüberladungen für die Operatoren die man sonst auch manuell machen könnte (und hat dabei noch ein paar performance optimierungen drin wie vorher beschrieben)

Warum das vielleicht wie eine Spezialsyntax aussieht ist weil es eigentlich eine Kombination von 2 standard sytaxen ist, das eine ist die inline Array konstruktion [ + ELEMENTS + ] wobei Elements eine Kommaseperierte Elementliste ist, und das andere ist die standard operator Syntax.
Das das eigentlich nur standard syntax ist kann man relativ einfach sehen wenn man es aufdröselt:

Code: Alles auswählen

var
  arr, tmp: TIntArray;
begin
  arr := [1,2,3,4]:
  elem := [5];
  arr := arr + elem;
end;

Antworten