Zwei Variablen mit eigenem Operator vertauschen

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • Hallo Marco Feltmann,

    Ironie lässt sich über das Internet manchmal schwierig ausdrücken. Ich gehe davon aus, dass Sie den Code-Ausschnitt eben nicht als selbsterklärend empfinden.
    Sollten Sie keine Erfahrung mit Swift haben, kann ich Ihren Eindruck nachvollziehen. Tuples gibt es zum Beispiel nicht in Objective-C 2.0.

    Swift bietet viele Neuerungen gegenüber Objective-C. Diese Neuerungen können zu ganz neuen Lösungsansätzen führen (siehe mein vorherige Antwort
    ). Für weiterführende Informationen empfehle ich Apple's eigene Dokumention über Swift.
  • p3tom schrieb:

    Ich gehe davon aus, dass Sie den Code-Ausschnitt eben nicht als selbsterklärend empfinden.

    Rischtisch. Alles Andere als selbsterklärend.

    Mir ist bekannt, dass ein Tupel ein Wertepaar bzw. ein paar Werte darstellt.
    Wer mit Punktkoordinaten gearbeitet hat (also jeder, der irgendwann mal irgendwas programmiert hat), kennt beispielsweise einen Vertex als berühmtesten Vertreter der Tupel.

    Mir ist nicht bekannt, dass Swift es wirklich ermöglicht, mal eben dynamisch Tupel zu erstellen, indem man die beiden Werte in Klammern setzt.
    Noch weniger ist mir bekannt, dass es möglich ist, ein Tupel zu erstellen und ihm die Werte eines anderen Tupels zuzuweisen.

    Dass das geht, erklärt der Code ja von selbst (so er sich denn wirklich kompilieren und ausführen lässt).

    Ich habe nur absolut keine Ahnung, welche technologische Umsetzung hinter den Tupeln steckt.
    Wer kümmert sich wie um das Memory Management, und warum?

    Und vor Allem:
    Was verdammt noch mal ist so schwer daran zu verstehen, dass

    Quellcode

    1. operator infix <> {}
    2. @infix @assignment func <> <T> (inout left: T, inout right: T) {
    3. (left, right) = (right, left)
    4. }
    5. /* Mal so getan als wüssten wir nicht, was da oben steht */
    6. let a = 23;
    7. let b = 42;
    8. a <> b;

    absolut unübersichtlich ist, weil ich genau wissen muss, wie <> im aktuellen Scope definiert ist?

    Ich habe nichts gegen die Tupel.
    Ich finde nur

    Quellcode

    1. @assingment func swapValues <T> (inout left: T, inout right: T) {
    2. (left, right) = (right, left)
    3. }
    4. /* Mal so getan als wüssten wir nicht, was da oben steht */
    5. let a = 23;
    6. leb = 42;
    7. swapValues(a, b);

    für absolut jeden sofort ersichtlich.

    Keine Ahnung ob die Funktionsnotation so richtig ist. Bin noch nicht dazu gekommen mal ein Testprojekt mit Swift aufzuziehen – und ehrlich gesagt fehlt mir je mehr Positives ich darüber höre immer mehr der Mut dazu.
    Ich meine, ausnahmslos jeder, der sich von Swift begeistert zeigt, hat einen C++/Java/C# Hintergrund. Jeder mir Bekannte, der einen reinen Smalltalk/Objective-C Hintergrund hat, findet Swift total zum Kotzen.
    «Applejack» "Don't you use your fancy mathematics to muddle the issue!"

    Iä-86! Iä-64! Awavauatsh fthagn!

    kmr schrieb:

    Ach, Du bist auch so ein leichtgläubiger Zeitgenosse, der alles glaubt, was irgendwelche Typen vor sich hin brabbeln. :-P
  • Marco Feltmann schrieb:

    Mir ist nicht bekannt, dass Swift es wirklich ermöglicht, mal eben dynamisch Tupel zu erstellen, indem man die beiden Werte in Klammern setzt.
    Noch weniger ist mir bekannt, dass es möglich ist, ein Tupel zu erstellen und ihm die Werte eines anderen Tupels zuzuweisen.


    Tatsächlich wird da gar nichts dynamisch erstellt, denn die Tupel im Beispiel sind keine Datenstruktur, sondern nur eine Schreibweise.

    Die Zuweisung

    Quellcode

    1. (left, right) = (right, left)

    Ist tatsächlich identisch zu

    Quellcode

    1. left = right
    2. right = left

    wobei beide Zuweisungen aber gleichzeitig ausgeführt werden. Und so dürfte der Compiler das auch intern behandeln.

    Ein Tupel ist also per se erst mal kein Struct oder Objekt, sondern sagt nur: "Diese Werte / Variablen will ich auf einmal in dieser Reihenfolge benutzen".

    Marco Feltmann schrieb:

    Dass das geht, erklärt der Code ja von selbst (so er sich denn wirklich kompilieren und ausführen lässt).


    Der einzige Bug in dem zitierten Code war, daß man natürlich die zu vertauschenden Variablen mit var deklarieren muß, weil bei let der Compiler korrekterweise meckert, wenn man die konstanten Werte vertauschen will.

    Marco Feltmann schrieb:

    Ich habe nur absolut keine Ahnung, welche technologische Umsetzung hinter den Tupeln steckt.
    Wer kümmert sich wie um das Memory Management, und warum?


    Da die Tupel nur eine syntaktische Gruppierung von schon existierende Dingen sind, braucht es keine zusätzlichen dynamischen Konstrukte.

    Intern müßte es so laufen, daß z.B. beim Zurückgeben eines Tupels aus einer Funktion der Aufrufer-Code die empfangenden Variablen (die auch temporäre in einer Expression sein können) ganz normal statisch reserviert und die Funktion dann alle Komponenten des Ergebnis-Tupels in die bereitgehaltenen Aufrufer-Einzelvariablen schreibt.

    Der einzige Unterschied ist dabei, daß es in Swift eben nicht mehr nur genau eine Ergebnis-Variable geben kann (zumindest ohne Pointer-Referenz-Geschichten), sondern mehrere, wenn man will.

    Marco Feltmann schrieb:

    Und vor Allem:
    Was verdammt noch mal ist so schwer daran zu verstehen, dass

    Quellcode

    1. operator infix <> {}
    2. @infix @assignment func <> <T> (inout left: T, inout right: T) {
    3. (left, right) = (right, left)
    4. }
    5. /* Mal so getan als wüssten wir nicht, was da oben steht */
    6. let a = 23;
    7. let b = 42;
    8. a <> b;


    absolut unübersichtlich ist, weil ich genau wissen muss, wie <> im aktuellen Scope definiert ist?


    Daran ist nichts per se unübersichtlich. Eigene oder überladene Operatoren sollte man aber logischerweise genauso mit Umsicht verwenden wie alle anderen syntaktischen oder semantischen Konstrukte. Scope-Visibility muß sowieso schon bei allen anderen Aspekten beachtet werden; Das ist hier nichts wirklich spezielles.

    Auch in C++ ist das kein größeres Problem, da in der Regel einigermaßen vorsichtig damit hantiert wird. Bei sinnvoller Nutzung ist das allerdings ein sehr elegantes Werkzeug, das viel Syntax-Rauschen ersparen kann.

    Marco Feltmann schrieb:

    Keine Ahnung ob die Funktionsnotation so richtig ist. Bin noch nicht dazu gekommen mal ein Testprojekt mit Swift aufzuziehen – und ehrlich gesagt fehlt mir je mehr Positives ich darüber höre immer mehr der Mut dazu.
    Ich meine, ausnahmslos jeder, der sich von Swift begeistert zeigt, hat einen C++/Java/C# Hintergrund. Jeder mir Bekannte, der einen reinen Smalltalk/Objective-C Hintergrund hat, findet Swift total zum Kotzen.


    Ich habe auch schon von erfahrenen Objective-C-Entwicklern positives über Swift gehört. Allerdings von solchen, die sich auch wirklich mal etwas mehr darauf eingelassen haben. Aber wie bei allem und jedem gibt es auch hier natürlich Licht und Schatten, und natürlich sowieso in diesem frühen Stadium noch Beta-Geschichten.
  • RegExpressive schrieb:

    Ist tatsächlich identisch zu

    Quellcode

    1. left = right
    2. right = left

    wobei beide Zuweisungen aber gleichzeitig ausgeführt werden. Und so dürfte der Compiler das auch intern behandeln.

    Was für ein Unsinn! Soll das Computer-Esoterik sein?

    Der Prozessor kopiert beide Werte in Zwischenvariablen und weist sie danach vertauscht zu. Wenn da der Optimizer nicht noch eingreift, ist die Tupellösung somit ungünstiger als die Verwendung einer Hilfsvariablen, wie es der OP vorgeschlagen hat. Aber das ist POITROAE.
    „Meine Komplikation hatte eine Komplikation.“
  • macmoonshine schrieb:

    Was für ein Unsinn! Soll das Computer-Esoterik sein?

    Der Prozessor kopiert beide Werte in Zwischenvariablen und weist sie danach vertauscht zu. Wenn da der Optimizer nicht noch eingreift, ist die Tupellösung somit ungünstiger als die Verwendung einer Hilfsvariablen, wie es der OP vorgeschlagen hat. Aber das ist POITROAE.


    Es ging mir in genau dieser Erklärung um Verständlichkeit des Prinzips, nicht um kompilierbaren Code einer bestimmten Sprache.

    Wenn der Compiler was taugt, wird er an der Aufrufstelle ggf. gar nichts umkopieren, sondern nur die Variablen zur Compilezeit intern umbenennen, weil er den Operator in dieser Form inlinen kann.

    Manche Prozessoren haben tatsächlich auch einen nativen Swap- bzw. Xchg-Befehl, auf den der komplette Operator-Aufruf reduziert werden kann.

    Mehrfache Rückgaben auf dem Umweg über Pointer-Parameter sind notorisch schlecht zu optimieren. Bei der Formulierung als Tupel ist die Optimierung viel besser möglich, mit Inlining sogar extrem gut.

    Wobei wir selbstverständlich sehen müssen, ob diese Möglichkeiten auch voll ausgeschöpft werden, und natürlich ab welcher Compiler-Version.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von RegExpressive ()

  • Weil der Optimizer immer das letzte ist, was man einschleift, wenn man eine neue Sprache einführt. Erst mal geht's darum, daß der Compiler korrekt funktioniert – alles weitere hat niedrigere Priorität.

    Wobei offenbar viele "Benchmarks" sogar ohne Optimierung durchgeführt wurden, und dann kann man jeden Vergleich eh vergessen.
  • RegExpressive schrieb:

    Weil der Optimizer immer das letzte ist, was man einschleift, wenn man eine neue Sprache einführt. Erst mal geht's darum, daß der Compiler korrekt funktioniert – alles weitere hat niedrigere Priorität.

    Wobei offenbar viele "Benchmarks" sogar ohne Optimierung durchgeführt wurden, und dann kann man jeden Vergleich eh vergessen.


    bei vielen vergleichen habe ich auch die zeiten bei unterschiedlichen optimierungsstufen gesehen - und keine sprachen für swift.
  • RegExpressive schrieb:



    Die Zuweisung

    Quellcode

    1. (left, right) = (right, left)

    Ist tatsächlich identisch zu

    Quellcode

    1. left = right
    2. right = left

    wobei beide Zuweisungen aber gleichzeitig ausgeführt werden. Und so dürfte der Compiler das auch intern behandeln.

    ​Der macht das echt gleichzeitig? Das wird dann aber ein lustiger Spaß. Man könnte jetzt noch darüber sinnieren, ob man sich einen Tastendruck mit Sekretärinnen-Swift sparen kann. Ich bin aber zu faul nachzuzählen Ist auch irgendwie blödsinnig, schließlich verhält sich der Spaß wohl ziemlich identisch zu

    Quellcode

    1. left = right;

    was die Sache dann gleich viel prägnanter macht.
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • RegExpressive schrieb:

    macmoonshine schrieb:

    Was für ein Unsinn! Soll das Computer-Esoterik sein?

    Der Prozessor kopiert beide Werte in Zwischenvariablen und weist sie danach vertauscht zu. Wenn da der Optimizer nicht noch eingreift, ist die Tupellösung somit ungünstiger als die Verwendung einer Hilfsvariablen, wie es der OP vorgeschlagen hat. Aber das ist POITROAE.

    Es ging mir in genau dieser Erklärung um Verständlichkeit des Prinzips, nicht um kompilierbaren Code einer bestimmten Sprache.

    Mich erheischt ja zunehmend der Gedanke, dass es bei Shit with inferred types insgesamt nicht um kompilierbaren Code geht.

    RegExpressive schrieb:

    Wenn der Compiler was taugt, wird er an der Aufrufstelle ggf. gar nichts umkopieren, sondern nur die Variablen zur Compilezeit intern umbenennen, weil er den Operator in dieser Form inlinen kann.

    Manche Prozessoren haben tatsächlich auch einen nativen Swap- bzw. Xchg-Befehl, auf den der komplette Operator-Aufruf reduziert werden kann.

    Mehrfache Rückgaben auf dem Umweg über Pointer-Parameter sind notorisch schlecht zu optimieren. Bei der Formulierung als Tupel ist die Optimierung viel besser möglich, mit Inlining sogar extrem gut.

    Wobei wir selbstverständlich sehen müssen, ob diese Möglichkeiten auch voll ausgeschöpft werden, und natürlich ab welcher Compiler-Version.

    Ja, die wirkliche Optimierung bei der Zuweisung. Etwas, was ich schon lange vermisst habe. Endlich get's voran!
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • RegExpressive schrieb:

    Weil der Optimizer immer das letzte ist, was man einschleift, wenn man eine neue Sprache einführt. Erst mal geht's darum, daß der Compiler korrekt funktioniert – alles weitere hat niedrigere Priorität.

    Wobei offenbar viele "Benchmarks" sogar ohne Optimierung durchgeführt wurden, und dann kann man jeden Vergleich eh vergessen.
    Nach nur wenigen Tagen Arrays gleich von Grund auf neu implementieren zu müssen (Wann waren eigentlich das letzte Mal seit MODERN BASIC Arrays überhaupt Sprachbestandteil?), ist ja auch irgendwie wichtiger, wenn man es total verbockt hat.

    Ich glaube, diese Sache da, also diese kleine Unbedeutendheit mit dem irgendwie funktionieren, wird uns noch eine Weile beschäftigen.
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?