Is AND-operator short-circuiting in Pascal?

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Benutzeravatar
Winni
Beiträge: 1575
Registriert: Mo 2. Mär 2009, 16:45
OS, Lazarus, FPC: Laz2.2.2, fpc 3.2.2
CPU-Target: 64Bit
Wohnort: Fast Dänemark

Re: Is AND-operator short-circuiting in Pascal?

Beitrag von Winni »

@ m.fuchs


Wenn Du Dir 30 Jahre zu spät Gedanken um boolean short-circuit machst, dann ist das kein Rant, sondern ein trauriges Bild von Dir.

Und dann hätte ich gerne mal ein halbwegs sauber programmiertes Beispiel von Dir, wie man den short-circuit aufs Kreuz legt....

Erstmal um die Grundlagen kümmern. Wie gesagt.

Winni

MitjaStachowiak
Lazarusforum e. V.
Beiträge: 386
Registriert: Sa 15. Mai 2010, 13:46
CPU-Target: 64 bit
Kontaktdaten:

Re: Is AND-operator short-circuiting in Pascal?

Beitrag von MitjaStachowiak »

Zur Optimierung: Nehmen wir einen Ausdruck, wie:

Code: Alles auswählen

if (a) and (a or b) then ... 
Das kann man logisch auch zu einem (a or b) optimieren. Eigentlich würde ich erwarten, dass der Compiler solche Optimierungen auch durchführt. Aber wenn a jetzt ein Funktionsaufruf ist, der im Hintergrund etwas tut, dann würde a bei true zwei mal aufgerufen ohne Optimierung und mit Optimierung nurnoch ein mal...

Um das zu vermeiden, müsste die Optimierung nur dann passieren, wenn im Ausdruck keine Aufrufe passieren. Naja, oder nur solche Aufrufe optimieren, die einen reinen read-only charakter haben. Oft verwenden wir ja properties mit gettern und settern... Ist FPC jetzt schlau genug, in die Tiefe eines getters einzusteigen und zu entscheiden, ob es egal ist, den zwei mal aufzurufen?

Für eine AND-Verknüpfung halte ich short-circuiting schon für sinnvoll. Aber in Javascript kann man auch so brillianten Code creieren, wie den folgenden:

Code: Alles auswählen

function MyObject () {
}
MyObject.prototype = {
  doSomething : function () {
    alert('Es tut!');
  }
};
function getObject () {
  if (Math.random() > 0.5) return new MyObject();
  else return null;
}
function die (msg) {
  throw new Error(msg);
}
(function () {
  var a = getObject() || die("Can't create object!");
  a.doSomething();
})();
Der ||-Operator kann nicht nur Boolesche Werte vergleichen, sondern nimmt auch ein Object an und dann gilt null als false und alles andere als true. Ein echter, impliziter Typecast findet aber nicht statt, da der Ausdruck im falle "not null" weiterhin das gültige Object für a zurück gibt, statt true :roll:

Dass Pascal es mit solchen Konzepten nicht gerade übertreibt, finde ich nicht so schlecht :wink:

Benutzeravatar
m.fuchs
Lazarusforum e. V.
Beiträge: 2532
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: Is AND-operator short-circuiting in Pascal?

Beitrag von m.fuchs »

Winni hat geschrieben:
Mi 16. Nov 2022, 12:59
Wenn Du Dir 30 Jahre zu spät Gedanken um boolean short-circuit machst, dann ist das kein Rant, sondern ein trauriges Bild von Dir.
Mein DeLorean ist leider gerade in der Werkstatt, sonst würde ich die Diskussion dreißig Jahre früher durchführen.

Aber kleiner Tipp: wenn dich das hier so nervt - lies und schreibe einfach nicht mit. Das hat auch für den Rest den Vorteil dass man deinen rüden Umgangston nicht ertragen muss.
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de

PascalDragon
Beiträge: 670
Registriert: Mi 3. Jun 2020, 07:18
OS, Lazarus, FPC: L 2.0.8, FPC Trunk, OS Win/Linux
CPU-Target: Aarch64 bis Z80 ;)
Wohnort: München

Re: Is AND-operator short-circuiting in Pascal?

Beitrag von PascalDragon »

m.fuchs hat geschrieben:
Mi 16. Nov 2022, 11:56
Winni hat geschrieben:
Mi 16. Nov 2022, 10:43
Wer halbwegs sauberen Code schreibt, ist mit boolean short-circuit auf der völlig sicheren Seite.
Nicht zwangsläufig. Tatsächlich bin ich bisher noch nicht darüber gestolpert. Für die Zukunft weiß ich jetzt aber: wenn ich zwei Funktionen ausführen und deren Rückgabewerte per and verknüpfen möchte, dann muss ich Hilfsvariablen benutzen. Kommt sicher selten vor, aber kann auch vorkommen.
Du kannst für den Teil auch einfach den $B umschalten:

Code: Alles auswählen

{$push}{$B-}
if funcA() and funcB() then
  ...
{$pop}
m.fuchs hat geschrieben:
Mi 16. Nov 2022, 11:56
Unter anderem damit der Compiler eventuell auch die Reihenfolge der Aussagen verändern kann. Hmmmm.
Ist Short-Circuiting aktiv, so ändert der Compiler die Reihenfolge nicht. Ist es nicht aktiv, macht der Compiler da in der Tat Optimierungen, wenn es sich anbietet.
m.fuchs hat geschrieben:
Mi 16. Nov 2022, 10:13
Wie dem auch sei: aus meiner Sicht wäre eine Unterscheidung der Optimierung durch unterschiedliche Operatoren wie and und andalso oder so etwas die bessere Wahl.
Die kann man in seinem Code je nach Notwendigkeit einsetzen.
Wir werden wahrscheinlich irgendwann mal Unterstützung für and_then und or_then aus ISO Extended Pascal einbauen. Womöglich aber auch nur in diesem Modus oder mit einem entsprechenden Modusschalter.
FPC Compiler Entwickler

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

Re: Is AND-operator short-circuiting in Pascal?

Beitrag von af0815 »

PascalDragon hat geschrieben:
Do 17. Nov 2022, 07:51
Ist Short-Circuiting aktiv, so ändert der Compiler die Reihenfolge nicht. Ist es nicht aktiv, macht der Compiler da in der Tat Optimierungen, wenn es sich anbietet.
Das wäre eine Information die in die Referenz https://www.freepascal.org/docs-html/cu ... ogsu4.html IMHO hineingehören würde. Weil damit ist es klar und definiert, wie der Compiler sich verhält.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

Benutzeravatar
fliegermichl
Lazarusforum e. V.
Beiträge: 1214
Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Winux (L 2.0.11 FPC 3.2)
CPU-Target: 32/64Bit
Wohnort: Echzell

Re: Is AND-operator short-circuiting in Pascal?

Beitrag von fliegermichl »

Mein erster Kontakt zu $b- war mit Borland Pascal 5. Da stand explizit in der Anleitung für Turbo Vision Programme, daß diese mit B- übersetzt werden müssen.

if (Objekt <> nil) and (Objekt^.Whatever) then ...

wäre sonst in die Hose gegangen.

Benutzeravatar
Winni
Beiträge: 1575
Registriert: Mo 2. Mär 2009, 16:45
OS, Lazarus, FPC: Laz2.2.2, fpc 3.2.2
CPU-Target: 64Bit
Wohnort: Fast Dänemark

Re: Is AND-operator short-circuiting in Pascal?

Beitrag von Winni »

Hi!

{$B-} gab es ab Turbo 4.0 als Boolean short-circuit

In den Versionen 1.0 bis 3.0 wurde mit {$B ...} der Standard Input/Output gewählt: Terminal (TRM) oder Konsole (CON).

Wie praktisch {$B-} ist, sei nur an einem kurzen Beispiel gezeigt:

Code: Alles auswählen

procedure StripLeadingBlanks (var s : string);
begin
While (length(s) > 0) and (s[1] = #32) do delete (s,1,1);
end;
Im Modus {$B+} müsste man das in 2 Bedingungen schachteln, weil es sonst bei s[1] krachen könnte.

Winni

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

Re: Is AND-operator short-circuiting in Pascal?

Beitrag von kupferstecher »

m.fuchs hat geschrieben:
Mi 16. Nov 2022, 11:56
Ach halt, es liegt gar nicht an Pascal. N. Wirth hatte Short-Circuit nicht vorgesehen. Unter anderem damit der Compiler eventuell auch die Reihenfolge der Aussagen verändern kann.
Die Reihenfolge zu optimieren denke ich bringt in der Praxis wenig Performancegewinn. Außer der Compiler könnte dann gleichzeitig die Auswertung vorzeitig abbrechen, aber beide Optimierungen schließen sich ja gegenseitig aus.

Ich finde es nett, dass der Compiler bei einer Zeile wie
If (key=vk_o) and (ssCtrl in Shift) then ...
unaufgefordert Short-Circuiting betreibt, auch wenn die paar Takte in diesem Beispiel kaum der Rede wert sind.

Mit andthen könnte ich auch leben, ist halt wieder das Problem der Rückwärts(in)kompatibilität. Mit and_then weniger, das macht das ganze Schriftbild kaputt :wink:

In Pascal ist das Short-Circuiting m.E. weniger dramatisch, weil man gemäß der Pascal-Philosophie sowieso nicht größere Funktionalitäten in if-Bedingungen verstecken sollte.

MitjaStachowiak
Lazarusforum e. V.
Beiträge: 386
Registriert: Sa 15. Mai 2010, 13:46
CPU-Target: 64 bit
Kontaktdaten:

Re: Is AND-operator short-circuiting in Pascal?

Beitrag von MitjaStachowiak »

Wir werden wahrscheinlich irgendwann mal Unterstützung für and_then und or_then aus ISO Extended Pascal einbauen.
Da aktuell ja das normale and standardgemäß genau das tut, fände ich m.fuchs Vorschlag besser, das so zu lassen und den no-short-circuiting-Fall mit andAlso sowie orAlso anzubieten, statt mit {$push}{$B-}[...]{$pop}.

So Sachen, wie

Code: Alles auswählen

if (obj <> nil) and (obj.ready) then ...
if (length(arr) > 0) and (arr[0] = x) then ...
sind schon so geläufig, dass man das Verhalten des regulären and nicht mehr ändern kann.

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

Re: Is AND-operator short-circuiting in Pascal?

Beitrag von af0815 »

MitjaStachowiak hat geschrieben:
Do 17. Nov 2022, 13:42
So Sachen, wie

Code: Alles auswählen

if (obj <> nil) and (obj.ready) then ...
if (length(arr) > 0) and (arr[0] = x) then ...
sind schon so geläufig, dass man das Verhalten des regulären and nicht mehr ändern kann.
Und wozu brauche ich dann B+ ? Denn dort dürfen Parameter umsortiert/optimiert werden. B- ist ja ein Sonderfall einer effizienten Optimierung :-)

Ich sehe keinen Sinn in andAlso bzw. orAlso. Bisher sind die mir wirklich nicht abgegangen.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

MitjaStachowiak
Lazarusforum e. V.
Beiträge: 386
Registriert: Sa 15. Mai 2010, 13:46
CPU-Target: 64 bit
Kontaktdaten:

Re: Is AND-operator short-circuiting in Pascal?

Beitrag von MitjaStachowiak »

Der Punkt ist: Die Operatoren and und or haben mit {B+} und {B-} verschiedene, semantische Bedeutungen. Das ist nicht gut. Vor allem, weil man dieses Flag ja beliebig weit weg vom eigentlichen Ausdruck platzieren kann, sodass Pascal-Code plötzlich nicht mehr eindeutig ist.

Wenn jemand eine Unit, die jemand anderes angefangen hat, weiter entwickeln soll und da ggf. so ein Flag irgendwo gesetzt wird, dann führen Code-Schnipsel, die man gewohnheitsgemäß und überall sonst sicher verwenden kann, plötzlich zu instabilem Verhalten.

So eine <> nil-Prüfung baut man ja oft irgendwo als Sicherheit ein, obwohl dieser Fall normaler Weise nicht eintritt. Da das so banal und Standard ist, wird vielleicht auch kein Test-Case dafür angelegt. Und dann hat man instabile Software, obwohl man vielleicht nach allen Regeln der Kunst solide entwickelt hat...

Daher am besten eine non-short-circuiting-Version dieser Operatoren anbieten und das B-Flag deprecaden. Wenn man schon dabei ist:
Wie wäre es bei Methoden, Funktionen oder Properties mit einer Art unaltering-Direktive?

Ich bin nach etwas Nachdenken zu dem Schluss gekommen, dass FPC bei mehrfachen Peroperty-Zugriffen in einem Ausdruck nicht erkennen kann, ob man die durch Optimierungen zusammenfassen kann. Es kann ja z.B. sein, das ein Property eine Art Caching durchführt, sodass im Getter schon ein Schreibzugriff passiert. Nur dass es hier trotzdem egal ist, wie oft das property abgefragt wird. Der Compiler könnte den Zugriff also in einem Register puffern...

Benutzeravatar
fliegermichl
Lazarusforum e. V.
Beiträge: 1214
Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Winux (L 2.0.11 FPC 3.2)
CPU-Target: 32/64Bit
Wohnort: Echzell

Re: Is AND-operator short-circuiting in Pascal?

Beitrag von fliegermichl »

af0815 hat geschrieben:
Do 17. Nov 2022, 14:35
...
Und wozu brauche ich dann B+ ? Denn dort dürfen Parameter umsortiert/optimiert werden. B- ist ja ein Sonderfall einer effizienten Optimierung :-)

Ich sehe keinen Sinn in andAlso bzw. orAlso. Bisher sind die mir wirklich nicht abgegangen.
In dem Vergleich nach and könnte eine Funktion aufgerufen werden, die globale Variablen ändert. Bei B+ wird die sicher aufgerufen bei B- nur dann, wenn der Ausdruck vor dem and true ergibt.

Benutzeravatar
Winni
Beiträge: 1575
Registriert: Mo 2. Mär 2009, 16:45
OS, Lazarus, FPC: Laz2.2.2, fpc 3.2.2
CPU-Target: 64Bit
Wohnort: Fast Dänemark

Re: Is AND-operator short-circuiting in Pascal?

Beitrag von Winni »

fliegermichl hat geschrieben:
Do 17. Nov 2022, 14:58

In dem Vergleich nach and könnte eine Funktion aufgerufen werden, die globale Variablen ändert. Bei B+ wird die sicher aufgerufen bei B- nur dann, wenn der Ausdruck vor dem and true ergibt.
Hi!

Das hat dann aber nichts mehr mit sauberer Programmierung zu tun, wenn die Funktionen wilde Seiteneffekte haben.

Mir ist in der Tat kein Fall bekannt, bei dem man {$B+} sinnvoll einetzen könnte.

Winni

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

Re: Is AND-operator short-circuiting in Pascal?

Beitrag von af0815 »

fliegermichl hat geschrieben:
Do 17. Nov 2022, 14:58
af0815 hat geschrieben:
Do 17. Nov 2022, 14:35
...
Und wozu brauche ich dann B+ ? Denn dort dürfen Parameter umsortiert/optimiert werden. B- ist ja ein Sonderfall einer effizienten Optimierung :-)

Ich sehe keinen Sinn in andAlso bzw. orAlso. Bisher sind die mir wirklich nicht abgegangen.
In dem Vergleich nach and könnte eine Funktion aufgerufen werden, die globale Variablen ändert. Bei B+ wird die sicher aufgerufen bei B- nur dann, wenn der Ausdruck vor dem and true ergibt.
Ok, das leuchtet ein. Ein super Fall für defensive Programmierung. Sorry aber mein Verständnis ist dafür sehr begrenzt, zumindest bis ich in Pension gehe.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

MitjaStachowiak
Lazarusforum e. V.
Beiträge: 386
Registriert: Sa 15. Mai 2010, 13:46
CPU-Target: 64 bit
Kontaktdaten:

Re: Is AND-operator short-circuiting in Pascal?

Beitrag von MitjaStachowiak »

Ich hatte in einem Javascriptprogramm mal irgendwann den Fall, ein and ohne short-circuiting zu brauchen. Aber ja, es ist schon selten. Deswegen darf das sich auch gerne hinter einem langen Schlüsselwort verstecken...

Antworten