Syntaxerweiterung von Pascal

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Timm Thaler
Beiträge: 1224
Registriert: So 20. Mär 2016, 22:14
OS, Lazarus, FPC: Win7-64bit Laz1.9.0 FPC3.1.1 für Win, RPi, AVR embedded
CPU-Target: Raspberry Pi 3

Re: Syntaxerweiterung von Pascal

Beitrag von Timm Thaler »

Mathias hat geschrieben:Ich verwende gerne with, wen man es richtig anwendet, wird der Code somit viel übersichtlicher.


Ich verwende es nicht gern, es macht Code fehleranfälliger:

Code: Alles auswählen

    Width := 200// irgendwo mal definiert
    Height := 50;
   ...
    with Button[i] do begin
      Parent := Self;
      Width := Width;
      Height := Height;
      Left := (i mod 16) * (w + 2);
      Top := (i div 16) * (h + 2);
      Caption := char(i + 32);
      OnClick := @Button1Click;
    end;


Na, welche Width und Height wird jetzt welcher zugeordnet?

braunbär
Beiträge: 369
Registriert: Do 8. Jun 2017, 18:21
OS, Lazarus, FPC: Windows 10 64bit, Lazarus 2.0.10, FPC 3.2.0
CPU-Target: 64Bit
Wohnort: Wien

Re: Syntaxerweiterung von Pascal

Beitrag von braunbär »

Und wie wärs mit

Code: Alles auswählen

 
      Width := 200// irgendwo mal definiert
      Height := 50;
       ...
        with B:=Button[i] do begin
          B.Parent := Self;
          B.Width := Width;
          B.Height := Height;
          B.Left := (i mod 16) * (w + 2);
          B.Top := (i div 16) * (h + 2);
          B.Caption := char(i + 32);
          B.OnClick := @Button1Click;
        end;
 
 


Width und height beziehen sich da nur in Verbindung mit "b." auf die Button Komponente (und natürlich auch nicht auf eine Kopie des Buttons, die man am Ende des with-Blocks zurück zuweisen müsste), ohne das "b." sind es normale Variable. Mit einem Schlag ist die Fehleranfälligkeit weg.

Benutzeravatar
m.fuchs
Lazarusforum e. V.
Beiträge: 2636
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: Syntaxerweiterung von Pascal

Beitrag von m.fuchs »

braunbär hat geschrieben:
M.Fuchs hat geschrieben:Wenn du Variablen haben möchtest, die nur für einige Zeilen gültig sein sollen, dann lagere diese Zeilen in eine eigene Prozedur oder Funktion aus

Ein übertriebenes Aufsplittern des Codes in Zwerg-Unterprogramme trägt nicht zur Verbesserung der Lesbarkeit des Codes bei.

Was ist denn übertrieben? Idealerweise ist eine Prozedur/Funktion nicht länger als sieben Zeilen. Schafft man vielleicht nicht immer. Alles was länger als zwanzig Zeilen ist, ist aber definitiv zu lang. Bis dahin kann man auch problemlos die Variablen im Auge behalten.

braunbär hat geschrieben:Und wie wärs mit

Code: Alles auswählen

 
      Width := 200// irgendwo mal definiert
      Height := 50;
       ...
        with B:=Button[i] do begin
          B.Parent := Self;
          B.Width := Width;
      (* ... *))
 

Kannst du doch jetzt genauso haben ohne with.

Code: Alles auswählen

procedure Bla;
var
  B: TButton;
begin
  B:=Button[i];
  B.Parent := Self;
  B.Width := Width;
end;
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de

mse
Beiträge: 2013
Registriert: Do 16. Okt 2008, 10:22
OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
CPU-Target: x86,x64,ARM

Re: Syntaxerweiterung von Pascal

Beitrag von mse »

m.fuchs hat geschrieben:Kannst du doch jetzt genauso haben ohne with.

Code: Alles auswählen

procedure Bla;
var
  B: TButton;
begin
  B:=Button[i];
  B.Parent := Self;
  B.Width := Width;
end;

Die "with" Entsprechung wäre:

Code: Alles auswählen

procedure Bla;
var
  B: ^TButton;
begin
  B:= @Button[i];
  B^.Parent := Self;
  B^.Width := Width;
end;

Das Schlüsselwort "with" dient auch zur Strukturierung des Programmtextes vor allem im Zusammenhang mit Records.

Benutzeravatar
m.fuchs
Lazarusforum e. V.
Beiträge: 2636
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: Syntaxerweiterung von Pascal

Beitrag von m.fuchs »

Warum willst du da mit Zeigern arbeiten?
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de

mse
Beiträge: 2013
Registriert: Do 16. Okt 2008, 10:22
OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
CPU-Target: x86,x64,ARM

Re: Syntaxerweiterung von Pascal

Beitrag von mse »

Weil "with" mit Zeigern arbeitet. Wobei ein Beispiel mit "record" besser geeignet wäre.

Benutzeravatar
m.fuchs
Lazarusforum e. V.
Beiträge: 2636
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: Syntaxerweiterung von Pascal

Beitrag von m.fuchs »

mse hat geschrieben:Weil "with" mit Zeigern arbeitet.

Nö, with arbeitet nicht mit Zeigern. Der Compiler sorgt einfach dafür, dass die Zugriff auf die ursprüngliche Variable erfolgt. Kann man leicht sehen, wenn man sich den generierten Code anschaut.

mse hat geschrieben:Wobei ein Beispiel mit "record" besser geeignet wäre.

Es wäre nicht besser geeignet, Zeiger wären nur dort sinnvoll. Das ist ja der Grund warum man Klassen benutzt.
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de

mse
Beiträge: 2013
Registriert: Do 16. Okt 2008, 10:22
OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
CPU-Target: x86,x64,ARM

Re: Syntaxerweiterung von Pascal

Beitrag von mse »

m.fuchs hat geschrieben:
mse hat geschrieben:Weil "with" mit Zeigern arbeitet.

Nö, with arbeitet nicht mit Zeigern. Der Compiler sorgt einfach dafür, dass die Zugriff auf die ursprüngliche Variable erfolgt. Kann man leicht sehen, wenn man sich den generierten Code anschaut.

"with" nimmt die Adresse der Daten. Bei einer Objektinstanz ist die Adresse der Daten der Inhalt der Instanzvariable, da hast du recht, sorry.
mse hat geschrieben:Wobei ein Beispiel mit "record" besser geeignet wäre.

Es wäre nicht besser geeignet, Zeiger wären nur dort sinnvoll. Das ist ja der Grund warum man Klassen benutzt.

Mit einem riesigen Overhead. Ja ich weiss, bei den heutigen Computern ist Performance kein Thema mehr. ;-)

Benutzeravatar
m.fuchs
Lazarusforum e. V.
Beiträge: 2636
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: Syntaxerweiterung von Pascal

Beitrag von m.fuchs »

Moderationshinweis: Die Beiträge zum Overhead bei Objektorientierung habe ich in ein neues Thema verschoben: viewtopic.php?f=10&t=10816
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de

braunbär
Beiträge: 369
Registriert: Do 8. Jun 2017, 18:21
OS, Lazarus, FPC: Windows 10 64bit, Lazarus 2.0.10, FPC 3.2.0
CPU-Target: 64Bit
Wohnort: Wien

Re: Syntaxerweiterung von Pascal

Beitrag von braunbär »

m.fuchs hat geschrieben:Was ist denn übertrieben? Idealerweise ist eine Prozedur/Funktion nicht länger als sieben Zeilen. Schafft man vielleicht nicht immer. Alles was länger als zwanzig Zeilen ist, ist aber definitiv zu lang.

Idealerweise ist eine Prozedur so lang, wie sie sein muss, um ihre Aufgabe zu erfüllen. Da maximale Zeilenzahlen pauschal vorzugeben, ist meines Erachtens Unsinn.
Wenn sich sinnvolle, abgeschlossene Teilaufgaben eingrenzen lassen, dann solllte man die in Prozeduren auslagern. Aber vom Aufspalten einer Prozedur in Teilprozeduren, bloß um die Zeilenzahl zu beschränken, halte ich überhaupt nichts. 20 Zeilen übersteigst du schon leicht, wenn du ein case Statement mit einer entsprechenden Zahl von Einträgen hast.

procedure Bla;
var
B: TButton;
begin
B:=Button[i];
B.Parent := Self;
B.Width := Width;
end;

Nur bei einem sehr gut optimierenden Compiler kommt da der gleiche Programmcode heraus. Ich brauche eine zusätzliche Deklaration, das ist zwar nicht viel Aufwand, aber unnötig, und der Geltungsbereich der Variable B ist nicht so schön eingeschränkt wie bei Verwendung eines with. Alles nicht wirklich schlimm, aber ganz sicher kein Vorteil gegenüber einer with-Konstruktion. Wenn das "with-objekt" ein record ist, wird der Code ausgesprochen hässlich, und wenn das with-Objekt gar ein namenloser Recordtyp (var x: record ... end) ist, dann geht deine Variante überhaupt nicht.

Benutzeravatar
m.fuchs
Lazarusforum e. V.
Beiträge: 2636
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: Syntaxerweiterung von Pascal

Beitrag von m.fuchs »

braunbär hat geschrieben:Idealerweise ist eine Prozedur so lang, wie sie sein muss, um ihre Aufgabe zu erfüllen.

Genau. Und zwar um eine Aufgabe zu erfüllen. Prozeduren die länger als zwanzig Zeilen sind, sind im Allgemeinen ein Hinweis darauf dass die Prozedur mehr als eine Aufgabe erfüllt.

braunbär hat geschrieben:Da maximale Zeilenzahlen pauschal vorzugeben, ist meines Erachtens Unsinn.

Tja, dieser pauschale Unsinn wird durchaus in der Praxis so durchgeführt. Wenn bei uns ein Mitarbeiter Quellcode eincheckt der längere Prozeduren enthält, dann markiert der CI-Server das Projekt als instabil. Und dann wird auch verkleinert.

braunbär hat geschrieben:Wenn sich sinnvolle, abgeschlossene Teilaufgaben eingrenzen lassen, dann solllte man die in Prozeduren auslagern. Aber vom Aufspalten einer Prozedur in Teilprozeduren, bloß um die Zeilenzahl zu beschränken, halte ich überhaupt nichts.

Häufig ist beides das Gleiche, siehe oben.

braunbär hat geschrieben:20 Zeilen übersteigst du schon leicht, wenn du ein case Statement mit einer entsprechenden Zahl von Einträgen hast.

Das kann passieren, ist aber ein seltener Fall. Und dann schaut man sich das Problem näher an. Nicht selten findet man eine bessere Lösung.

braunbär hat geschrieben:
procedure Bla;
var
B: TButton;
begin
B:=Button[i];
B.Parent := Self;
B.Width := Width;
end;

Nur bei einem sehr gut optimierenden Compiler kommt da der gleiche Programmcode heraus. Ich brauche eine zusätzliche Deklaration, das ist zwar nicht viel Aufwand, aber unnötig, und der Geltungsbereich der Variable B ist nicht so schön eingeschränkt wie bei Verwendung eines with. Alles nicht wirklich schlimm, aber ganz sicher kein Vorteil gegenüber einer with-Konstruktion. Wenn das "with-objekt" ein record ist, wird der Code ausgesprochen hässlich, und wenn das with-Objekt gar ein namenloser Recordtyp (var x: record ... end) ist, dann geht deine Variante überhaupt nicht.
[/quote]
Ja, in diesem Fällen passt das nicht. Aber wie gesagt: kurze Prozedure => weniger Probleme bei der Lesbarkeit.
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de

braunbär
Beiträge: 369
Registriert: Do 8. Jun 2017, 18:21
OS, Lazarus, FPC: Windows 10 64bit, Lazarus 2.0.10, FPC 3.2.0
CPU-Target: 64Bit
Wohnort: Wien

Re: Syntaxerweiterung von Pascal

Beitrag von braunbär »

m.fuchs hat geschrieben:Genau. Und zwar um eine Aufgabe zu erfüllen. Prozeduren die länger als zwanzig Zeilen sind, sind im Allgemeinen ein Hinweis darauf dass die Prozedur mehr als eine Aufgabe erfüllt.

Manchmal ja, oft genug ist das aber nicht der Fall.

m.fuchs hat geschrieben:Tja, dieser pauschale Unsinn wird durchaus in der Praxis so durchgeführt. Wenn bei uns ein Mitarbeiter Quellcode eincheckt der längere Prozeduren enthält, dann markiert der CI-Server das Projekt als instabil. Und dann wird auch verkleinert.

Dann hab ich wohl ein verdammtes Glück, dass ich nicht in eurer Firma arbeite...

m.fuchs hat geschrieben:Häufig ist beides das Gleiche, siehe oben.

Ja. Und häufig nicht.

m.fuchs hat geschrieben:Das kann passieren, ist aber ein seltener Fall. Und dann schaut man sich das Problem näher an. Nicht selten findet man eine bessere Lösung.

Selten oder nicht, ist nicht das Thema. Und ein case-Statement ist kein "Problem", für das man eine "bessere Lösung" suchen müsste. Wie umfangreich eine Prozedur ist, hängt von der Aufgabe (nicht den Aufgaben) ab, die sie erfüllt. Und wenn die einzige "Verbesserung" eine Aufspaltung zum Zweck der Reduktion der Zeilen der Prozedur ist, dann ist das meines Erachtens keine Verbesserung.

m.fuchs hat geschrieben:kurze Prozedure => weniger Probleme bei der Lesbarkeit.

Das stimmt so pauschal nicht. Weil das, was tatsächlich passiert, muss man sich dann aus vielen Teilprocedures erst wieder mühsam zusammen klauben. Oft ist die Auslagerung von Code in (kleinere) Unterprogramme sinnvoll, oft aber auch nicht. Die Compiler, die ich bisher kennen gelernt habe , sind für den Zugriff auf lokale und auf globale Variable optimiert, während der Zugriff auf lokale Variable übergeordneter Prozeduren mit einem relativ großen Overhead verbunden ist. Schon aus dem Grund bin ich mit der Verwendung von in andere Prozeduren eingebetteten Prozeduren eher zurückhaltend.

Ich habe jetzt noch kein Argument gelesen, das gegen die von mir vorgeschlagenen Erweiterungen der Pascal Syntax sprechen würde. Dass es auch jetzt schon workarounds gibt, mit denen MANCHMAL mehr oder weniger umständlich das gleiche erreicht werden kann, kann man doch nicht ernsthaft als Gegenargument bezeichnen.

Es gibt in Pascal ein with statement. Das hat sich der Herr Wirth ja nicht einfallen lassen, weil er blöd ist. Die Art, wie das Konzept derzeit in Pascal umgesetzt ist, führt zu Problemen, deretwegen man das with Statement so, wie es ist, besser nicht verwenden sollte. Aber statt es bei dem Zustand zu belassen und den Leuten zu sagen: "das Feature gibt es, aber verwendet es bitte nicht", wäre es doch besser, durch eine geringfügige Änderung der Syntax die Verwendung dieses Sprachfeatures auf sichere Art zu ermöglichen. Defaultmäßig sollten dann nur mehr das sichere with erlaubt sein, per Compilerschalter (der auch durch mode delphi defaultmäßig aktiviert werden müsste) die unsichere Version erlaubt werden.
Zuletzt geändert von braunbär am Mo 19. Jun 2017, 15:40, insgesamt 1-mal geändert.

mse
Beiträge: 2013
Registriert: Do 16. Okt 2008, 10:22
OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
CPU-Target: x86,x64,ARM

Re: Syntaxerweiterung von Pascal

Beitrag von mse »

Wie gesagt, das wird in Free Pascal seit über zehn Jahren diskutiert. Mache dir keine Hoffnungen, ein sicheres "with" Statement ist nicht aufsehenerregend genug um implementiert zu werden. Da machen Generics und der Nachbau weiterer Delphi Neuerungen mehr Spass.

Benutzeravatar
m.fuchs
Lazarusforum e. V.
Beiträge: 2636
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: Syntaxerweiterung von Pascal

Beitrag von m.fuchs »

Ich gehe jetzt mal nur auf einen Teil deiner Nachricht ein, dass ich dich überzeugen kann scheint mir eher unrealistisch zu sein.
braunbär hat geschrieben:
m.fuchs hat geschrieben:kurze Prozedure => weniger Probleme bei der Lesbarkeit.

Das stimmt so pauschal nicht. Weil das, was tatsächlich passiert, muss man sich dann aus vielen Teilprocedures erst wieder mühsam zusammen klauben.

Was in den vielen Teilprozeduren steht, ist meistens gar nicht relevant. Der Sinn besteht ja darin Sachen auszulagern, damit ich sie mir nicht mehr ansehen muss. Außer wenn ich wirklich etwas an einem ganz bestimmten Teilaspekt ändern muss. Ich lagere sogar immer mal wieder einzelne Zeilen aus, weil das deutlich lesbarer ist:

Code: Alles auswählen

if (Domain.ExpireDate < Now) and (Domain.Active) and (not Domain.Customer.Locked) and (Domain.Customer.DunningLevel < 2) then

vs.

Code: Alles auswählen

if ShouldBeRenewed(Domain)


Die erste Zeile ist nicht verständlich, die zweite schon. Ich muss bei der zweiten Variante nicht einmal die Funktion ShouldBeRenewed aufsuchen um zu wissen was sie tut. Die Details der Implementierung sind nämlich völlig uninteressant. Es sei denn, ich will die Kriterien für einen anstehenden Renew ändern. Aber wirklich nur dann. Und deswegen widerspreche ich dir: es ist eben häufig der Fall, dass eine kurze Prozedur/Funktion auch lesbarer ist.

braunbär hat geschrieben:Die Compiler, die ich bisher kennen gelernt habe , sind für den Zugriff auf lokale und auf globale Variable optimiert, während der Zugriff auf lokale Variable übergeordneter Prozeduren mit einem relativ großen Overhead verbunden ist. Schon aus dem Grund bin ich mit der Verwendung von in andere Prozeduren eingebetteten Prozeduren eher zurückhaltend.

Niemand will auf lokale Variablen in übergeordneten Prozeduren zugreifen. Wie gesagt: heutzutage wird objektorientiert entwickelt. Da reicht man maximal die Referenz eines Objektes irgendwo rein oder häufiger benutzt man gleich Objektmethoden.

braunbär hat geschrieben:Ich habe jetzt noch kein Argument gelesen, das gegen die von mir vorgeschlagenen Erweiterungen der Pascal Syntax sprechen würde. Dass es auch jetzt schon workarounds gibt, mit denen MANCHMAL mehr oder weniger umständlich das gleiche erreicht werden kann, kann man doch nicht ernsthaft als Gegenargument bezeichnen.

Ich habe noch immer nicht verstanden was der Vorteil sein soll, das reicht mir erst mal als Gegenargument. Wenn eine Verbesserung des with-Block nötig ist, würde ich einfach folgendes vorschlagen:

Code: Alles auswählen

 
with Button1 do begin
  .Width := 100;
  .Height := 25;
  .Caption := 'Test';
end;

Sprich, Zugriff auf die Methoden und Properties der Variable im with nur mit vorangestelltem Punkt. Dann gibt es keine Verwechselung mit Variablen gleichen Namens und man muss auch keine unnötige lokalen Variablen nutzen.

Für deinen zweiten Vorschlag Zuweisungen in Teilexpressions habe ich nicht einmal eine Alternativlösung. Das ist einfach nur unleserlich und bringt überhaupt keine Vorteile.


braunbär hat geschrieben:Es gibt in Pascal ein with statement. Das hat sich der Herr Wirth ja nicht einfallen lassen, weil er blöd ist. Die Art, wie das Konzept derzeit in Pascal umgesetzt ist, führt zu Problemen, deretwegen man das with Statement so, wie es ist, besser nicht verwenden sollte. Aber statt es bei dem Zustand zu belassen und den Leuten zu sagen: "das Feature gibt es, aber verwendet es bitte nicht", wäre es doch besser, durch eine geringfügige Änderung der Syntax die Verwendung dieses Sprachfeatures auf sichere Art zu ermöglichen.

Es gibt übrigens auch Goto in Pascal. Nimmt ja auch kein geistig gesunder Mensch mehr heutzutage. Manche Dinge verändern sich eben.
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de

marcov
Beiträge: 1100
Registriert: Di 5. Aug 2008, 09:37
OS, Lazarus, FPC: Windows ,Linux,FreeBSD,Dos (L trunk FPC trunk)
CPU-Target: 32/64,PPC(+64), ARM
Wohnort: Eindhoven (Niederlande)

Re: Syntaxerweiterung von Pascal

Beitrag von marcov »

m.fuchs hat geschrieben:Ich gehe jetzt mal nur auf einen Teil deiner Nachricht ein, dass ich dich überzeugen kann scheint mir eher unrealistisch zu sein.
Es gibt übrigens auch Goto in Pascal. Nimmt ja auch kein geistig gesunder Mensch mehr heutzutage. Manche Dinge verändern sich eben.


Ich bin es darüber noch immer mit mein Professor einig; man darf goto nutzen, man muss nur ein 1 A4 Seite Aufsatz über warum es unbedingt nötig ist schreiben.

Antworten