 Einen wunderschönen guten Morgen oder auch guten Abend, je nachdem, ob ihr noch wach seid. Dass tatsächlich noch Leute sich nach der durchzechten Nacht hierher getraut haben, das spricht für sich, freut mich auf jeden Fall. Wir haben heute nochmal ein Talk über Fusion, Fusion oder Fusion? Fusion, alles klar. Kurze Frage, aus dem Publikum, wie viele Programmiersprachen kennt ihr eine? Was, ihr kennt alle keine? Okay, hitt mal die Hand. Wer kennt eine? Mindestens eine, ja. Okay, das sind alle, hätte ich ja auch erwartet. Gut, zwei, drei, vier, fünf. Okay, ja. Ja, sechs. Ja, okay, beeindruckend, also ich kann nicht so viele. Aber genau, wenn ihr jetzt statt vier den nächsten fünf lernen wollt, dann seid ihr hier richtig. Denn es geht heute um eine relativ neue Programmiersprache, Fusion, die, wie ich gehört habe, Security by Design vor allem in den Vordergrund stellt. Und der Friedi ist heute hier, hat viele Jahre an dem Thema gearbeitet, ist selbst mit Gründer dieser Sprache und wird euch dazu jetzt einiges erzählen. Los geht's. Okay, vielen Dank. Mir fällt jetzt die Aufgabe zu. Die Ehre finde ich eigentlich den Abschlussvortrag auf diesen großartigen Event zu halten. Und ich möchte die Chance nutzen, erstmal dem ganzen Team hier zu danken, die die TPN auf die Beine gestellt haben, Entropia, CCC, den ganzen tollen, allen Helfern, dem Orga Team. Ich denke, das war großartig. Ich glaube, die haben auch in einer kurzen Zeit das hier alles auf die Beine gestellt und sicher viele größere Hindernisse so gelöst, dass wir es gar nicht gemerkt haben. Ich möchte den allen herzlich danken. Ich denke, du sollst den allen herzlich danken. So, mein Talk ist schon online. Ich habe hier gerade die Fusion Website, Flang.dev und da hole ich auch die Slides her. So, maybe one sentence in English, in case there is anybody here who is not confident in German. I will hold the talk in German, but the slides will be in English so you should be able to follow it anyway. If you have any questions, please feel free to ask them in English or any language you like. We will try to find some solution then. But the rest of the talk I will give in German then. Also, ich mache weiter. Auf Deutsch stellt bitte Fragen. Wenn ihr irgendwelche habt, macht euch irgendwie bemerkbar. Ja, ich werde über Fusion reden, das Sprache, an der ich jetzt seit drei Jahren intensiv arbeite, mit dem Ziel eben eine neue General Purpose-Programmiersprache zu schaffen, speziell für sicherheitskritische Systeme, aber nicht beschränkt auf das. Und das möchte ich hier jetzt kurz vorstellen. Ein bisschen was zu mir, zu meinem Hintergrund, ich habe vorhin fast erschrocken, ich habe 33 Jahre Erfahrung mit Programmiersprachen, Compiler-Implementierung, zurück in den 90ern auf Amiga-Computern, wo ich einen Oberrunden-Compiler gemacht habe, einen Eiffel-Compiler, lange Zeit mit Java-Compilern und verschiedenen gearbeitet. Und jetzt eben an Fusion und seit letztem Jahr für eine kleine Firma Tokiba an Fusion, dann sage ich noch mehr dazu. Die Motivation für Fusion war, dass wir sehen, dass etablierte Programmiersprachen mehr und mehr überladen werden mit zusätzlichen Konzepten. Also Sprachen wie Java haben Sachen wie Klassen, Methoden, Interfaces, Constructors. Jetzt kommen Sachen dazu, Trades und andere Sprachen, Records, Structs, Packages, Values und so weiter. Und mit Fusion ist die Grundidee, dass wir diese Explosion an Konzepten entgegenwirken wollen und stattdessen ein einziges Konzept, nämlich das einer Fusion-Feature, das mächtig genug ist, die anderen Sachen nachzubauen, zur Verfügung zu stellen. Und stattdessen, stattdessen, dass wir sehr, sehr viele unterschiedliche Konzepte in der Sprache haben, möchten wir Aufgaben dem Compiler übergeben. Wir sehen, dass heutzutage so ein Compiler und Werkzeuge paufeln. Ja, mächtig genug, um häufig bessere Entscheidungen zu machen als der Entwickler. Wieso soll dann nicht der Compiler diese Entscheidungen auch übernehmen, anstatt dem Entwickler vorzuschreiben, dass er sagen muss, will ich jetzt eine Klasse oder ein Record oder eine Methode haben. Und wir sehen, dass mehr und mehr Systeme, die uns umgeben, sicherheitskritisch sind. Ich nachts sage da mehr darüber, was das genau bedeutet. Und wir müssen sicherstellen, dass diese Systeme eben korrekt funktionieren. Eine kurze Zusammenfassung der Fusion-Sprache, wie ich gesagt habe, das Hauptkonzept in Fusion, ist das der Fusion-Feature. Fusion selbst ist statisch typisiert, eine funktionale Sprache, hat aber auch Vererbung und Redefinition, d.h. auch objektorientierte Eigenschaften. Werte in Fusion sind typischerweise Value Types, es gibt aber auch dynamische Referenztypen, Sachen wie dynamisches Binden und so was hat. Felder in Fusion sind immutable und Fusion setzt sogenannte Effects, sage ich nachher mehr dazu, ein, um nicht funktionale Aspekte zu modellieren wie I.O. oder auch die Veränderung des Motieren von Feldern. Und ganz wichtig, Entscheidungen, Implementierungsdetails sollen möglichst vom Entwickler weggenommen werden und den Tools übertragen werden. Fusion hat ein cooles Logo und ich habe ein Apar-Aufkleber hier, die ich jetzt durchgeben möchte. Wenn ihr Interesse habt, nehmt euch eins, sonst gibt es weiter. Falls sie nicht reichen, ich habe hier noch mehr. Falls welche übrig sind, das sind am Schluss, bitte nicht auf dem Boden fallen lassen, sondern gebt sie wieder hierher. Wo findet ihr Fusion? Fusion ist unter dpl.v3 und GitHub verfügbar. Und ihr habt vorhin schon kurz gesehen, es gibt eine Website, flang.dev, wo alle Informationen zu Fusion zentral gesammelt werden. Da gibt es ein Sprach-Tutorial, es gibt sehr detaillierte Informationen zum Fusion-Design, den Entscheidungen in der Sprachentwicklung. Es gibt Beispiele, alles Mögliche da. Es gibt hier in Karlsruhe eine kleine Firma, die Tokiba Software GmbH, die die Fusion Sprache unterstützt. Und wir sind im Augenblick für Entwickler bei Tokiba, suchen immer noch Verstärkung für unser Team, suchen aber auch nach Finanzierungsmöglichkeiten im Form von Forschungsprojekten beispielsweise oder Investoren. So, jetzt fange ich an mit Sicherheit, was heißt das eigentlich? Im Deutschen, das Wort Sicherheit ist auch noch sehr schwammig, im Englischen wird es übersetzt entweder als Safety oder Security. So möchte ich ein bisschen erst mal erklären, was denn die Bedeutung hier ist. Safety, laut Wikipedia, ist das State of being safe, the condition of being protected from harm or other danger. Safety heißt, dass man sicher geschützt ist für irgendwelchen bösen Einflusschen zu lösen. Während Security is the protection from or resilience against potential harm caused by others. So hier ist bei Security es ganz wichtig, da gibt es irgendein Adversary, irgendein Angreifer, der möchte eine möglicherweise Böses and we want to restrain the freedom of others. Das heißt, wir möchten den Einschränken in seiner Handlungsfreiheit uns nichts Böses zu tun. Also safety ist symbolisiert sehr schön mit einer Sicherheitsnadel, die so designed, dass man sie richtig verwendet, die Wahrscheinlichkeit, dass man sich damit selber wehtut, eben verringert ist. Security kann durch einen Sicherheitsschloss gut symbolisiert werden. Wir wollen die anderen draußen halten. Wir sind alle Entwicklerprogrammierer hier in Code. Da habe ich ein kleines Beispiel für Safety and Security, C-Code jetzt. Print F ist eine C-Funktion, die nicht safe ist, weil abhängig von dem Parameter Spring kann Print F abstürzen, wenn der Spring nur les oder Prozent S oder ähnliche Sachen enthält. Ein Beispiel für Security ist, wenn ich jetzt in meinem Programm einem Angreifer, einem externen, die Möglichkeit gebe, eben diesen Spring zu beeinflussen, den irgendwo über ein Webinterface oder was auch immer einlesen und das dann im Print F übergeben wird diese Sicherheitslücke in Print F auf einmal zu eine Möglichkeit das System anzugreifen. Und wenn der Angreifer fit genug ist, kann er das sogar ausnutzen, um Route Access auf dem System zu erhalten. Um Security zu erreichen in einem System ist Safety eine gute Vorbedingung, aber keine nötige Vorbedingung. Also man kann sichere Systeme in unsicheren Sprachen schreiben, aber es ist einfacher, wenn die Sprache schon mal Safety zur Verfügung stellt, eben solche Security vulnerabilities zu vermeiden. Safety Critical Systems, vier ein paar Beispiele, wo sie uns umgeben, wo wir sie sehen. Natürlich Steuerung in Flugzeugen, medizinischen Geräten, hier ist ein Beispiel, ein Operationsmikroskop für Augen- oder Gehirnoperationen, Verkehrssystemzügen, Luft- und Rahmenfahrttechnik, natürlich kritische Infrastruktur, elektrische Netze, Verkehrssteuerung, Automatisierung, sehr viele Bereiche, wo wir Systeme haben, die zuverlässig funktionieren müssen, die Safety als kritisch sind. Wieder die Definition, was sind Safety Critical Systems und Wikipedia? Das sind Systeme, deren Failure oder Melfunction zum Tod oder schweren Verletzungen von Menschen führen kann, zu großen Schaden oder Verlust von Materialausstattung führen kann, oder die größere Umweltschäden verursachen können. Sicherheitskritische Systeme brauchen häufig eine Zertifizierung, dafür gibt es verschiedene Standards, abhängig von dem Anwendungsbereich, wo diese Systeme eingesetzt werden. Diese Zertifizierung Standards, typischerweise schreiben mehrere Sachen vor. Eines davon ist Anforderung an den Softwareentwicklungsprozess, was man, wie man die Software eigentlich entwickelt, und Anforderungen an das Ergebnis der Softwareentwicklung, an die Artifakte, die dabei rauskommen, und vor allem an die Traceability, d.h. die Rückverfolgbarkeit in den Artifakten. D.h. zum Beispiel, dass man ein klares Mapping hat von Requirements zum Code, der diese Requirements implementiert, und vom Code zur Validierung, wie ich dann verifiziere, dass der Code auch die Requirements implementiert, und zu den Ergebnissen dieser Validierung. Und dann heißt das, dass wir ein eindeutiges Mapping haben zwischen diesen verschiedenen Artifakten, d.h. zum Beispiel, dass sich für jede Anweisung im Code klar sagen kann, weshalb ist die drinnen, wo ist denn das Requirement, das zu dieser Anweisung führt, aber auch sagen kann, wo wird verifiziert, dass diese Anweisung korrekt ist, also wo ist der Testfall beispielsweise, der diese Anweisung ausführt, und was ist das Testergebnis von dem Test Run. Dann für die Zertifizierung wird die rigorose Verifikation und Validierung vorausgesetzt, d.h. wir müssen beispielsweise den Code komplett abdecken, alle Anweisungen durch unsere Test Suite. Und die Idee jetzt bei Fusion ist, dass statische Analyse helfen kann, diese Artifakte, Tests, die Analyse herzustellen und damit den Aufwand für die Zertifizierung zu vereinfachen. So, ein bisschen was zur Fusion-Programmiersprache selbst. Ich kann in diesem kurzen Talk kein komplettes Tutorial über die Fusion-Sprache geben. Ich verweise auf die Flangnodef-Webseite, wenn ihr, ich hoffe, Interesse daran gewonnen habt, könnt ihr das durchgehen und Schritt für Schritt die verschiedene Aspekte der Sprache kennenlernen. Nur, was ich hier kurz sagen möchte, ist Fusion vereinheitlich. Verschiedene Konzepte in dem Fusion Feature, insbesondere ist ein Fusion Feature, was in der Sprache, wie Java, ein Package ist oder eine Klasse, ein Interface-Trade, betrote Record Struct usw. Hier ein ganz kleines Beispiel, an Hello World in Fusion. Hier implementiert als ein Feature, Hello World, das Code enthält, das eben Hello World ausgibt. Genauer ist es sogar ein Konstruktur, das erkennt man in dem Ease. Das heißt, wenn das aufgerufen wird, wird eine Instanz von Hello World angelegt und der Code ausgeführt. Features können ineinander geschachtelt werden. Wir haben jetzt hier das Hello World erweitert, um eine innere Feature, eine Routine, HW, die den Code Hello World enthält. Und im Body von Hello World rufen wir jetzt HW auf und dadurch führen wir diesen Code aus. Ups, jetzt bin ich schon ein weitergegangen, man macht nichts. Wir können Features mit Argumenten versehen. In dem Fall bekommt das HW einen Name als Argument übergeben, das dann ausgegeben wird und am Aufruf von dem HW wird eben ein Parameter auch übergeben. Als nächstes können das Schachteln, wie lieb ich, fortführen. Habe ich jetzt das HW umgewandelt in einem Konstruktur mit einer inneren Feature Run, die das Gleiche macht wie das ursprüngliche HW. Der Parameter ist aber beim umschließenden HW, das heißt jetzt kann ich eine Instanz von HW bilden, mit dem Namen World und kann da einfach oder auch mehrfach Run drauf aufrufen und dadurch eben Hello World ausgeben. Oder ich kann auch verschiedene Instanzen anlegen mit unterschiedlichen Namenparametern. Zusammenfassend Fusion Code, wenn man Fusion Code schreibt, ist man eigentlich die ganze Zeit damit beschäftigt entweder Features zu deklarieren oder Features aufzurufen, das sind die zwei wichtigsten Aspekte der Programmiersprache. Fusion benutzt ganz stark White Space und Inventation, um den Code zu strukturieren. Also insbesondere Einrückung für das Nesting, für die Blockstruktur im Code und Spaces als Separator zwischen Funktionen und Parametern in aufrufen. Es ist aber auch möglich, alternativ auch möglich, mit geschweiften Klammern und runden Klammern das Gleiche zu erreichen. Ich hätte sogar gerne, dass wir irgendwann anbieten, ein Werkzeug, das das in beide Richtungen konvertiert, haben wir im Augenblick noch nicht, aber im Grunde sind beide Notationen gleichwertig. Und ich habe zu viel Zeit in meinem Leben in Streitereien, was jetzt besser ist, welche Formatierung, welche Einrückungstiefe und so weiter. Das Beste ist verloren, das möchte ich nicht mehr. Also ich würde das gerne, so weit wie möglich, tools überlassen. Was hat Fusion nicht? Es gibt eine ganze Reihe an Features, die es in anderen Sprachen gibt, die wir in Fusion definitiv nicht haben wollen. Dazu gehört Dynamisches Laden, Dynamicaloading, Makros, Reflection, Pointer Arithmetic sogar noch weiter. In Fusion ist es noch nicht mal möglich, Referenzen, Pointers miteinander zu vergleichen. Was in Sprachen wie Java relativ einfach möglich ist, was aber viele Einschränkungen für die Analyse und den Compiler mit sich bringt. Wir wollen keine unkontrollierte Multiability, keine Exceptions. Und die Gründe dafür sind, wir müssen, wenn wir Kot schreiben, genau wissen, was macht denn dieser Kot? Wir müssen in der Lage sein, statische Analyse, mächtige statische Analyse laufen zu lassen. Wir brauchen Safety Features der Sprache. Aber auch wir wollen eine gute Performance am Schluss durch den Compiler. Das heißt, wir wollen ihm Möglichkeiten geben, Optimierungen zu machen. Ein vielleicht für viele neues Aspekt in der Fusion Programmiersprache ist das sogenannte Design by Contract. Design by Contract heißt, dass Features in Fusion ihr Verhalten spezifizieren. Das heißt, eine Feature kann eine Pre- und eine Post-Condition haben und die Pre-Condition spezifiziert, was der Aufrufe dieses Features erfüllen muss, damit er dieses Feature aufrufen kann, während die Post-Condition sagt, was für Garantien das Feature nach dem Aufruf garantiert. Design by Contract ist ein relativ altes Konzept. Das wurde von Bertram Meyer in 1986 vorgestellt, damals in der Programmiersprache Eiffel, ich weiß nicht, ob die irgendjemand hier kennt. Das ist eine coole Sprache. Ich habe ein kleines Beispiel hier, wie man Design by Contract einsetzt, in dem Fall für eine Square Route Implementierung, die eben in der Vorbedingung definiert, dass das Argument, das hier reingegeben wird, auf jeden Fall ein positiver Wert sein muss. Und bei Square Route einfach für einen negativen Wert, nicht wissen, wie man das implementieren soll. Und als Post-Condition eben auch klar definiert, dass das Ergebnis, was hier zurückgeliefert wird, die größtemögliche Zahl ist, deren Quadrat eben kleiner gleich das Argument ist. Und vielleicht noch ein Einsatz dadurch, kann eben die Werkzeuge durch Runtime Checks oder statische Analyse feststellen, dass Aufrufer eben die Vorbedingungen erfüllen und dass die Implementierung selber die Nachbedingungen auch erfüllt. So, wenn wir jetzt aber diese Bedingungen dynamisch überprüfen als Laufzeit Checks verursachtes Runtime Overhead und der könnte sogar prohibitiv teuer sein, aber für die Sicherheits des Systems könnte das auch nötig sein. Also wenn wir beispielsweise Kot haben, der auf dem Speichelbereich einen bestimmten Index zugreift, möchten wir sicherstellen, dass der Index auch wirklich definitiv in diesem Bereich ist und nicht irgendwie out of bounds ist. Das heißt, wir haben da auch Sicherheitsanforderungen, die durch Vorbedingungen erfüllt werden. Und die Lösung jetzt aus diesem Dilemma, wir brauchen es für Safety in manchen Stellen, aber es kann auch zu hoher Overhead bedeuten, is Infusion gibt es sogenannte Qualified Contracts. Beispiel hier, gerade mit dem Square root Beispiel, ist, wir können sagen, dass die Vorbedingungen in diesem Fall immer dann geprüft werden sollen, wenn Debugging eingeschaltet ist. Während die Nachbedingungen, wir trauen dem Kot, wir haben den schon häufig benutzt, die führen wir nur aus, wenn Debugging mindestens auf Level 5 eingeschaltet ist. Das heißt, wenn wir normal Level 1 Debugging haben, prüfen wir die Nachbedingungen nicht und dadurch wird die Ausführung sehr viel effizienter. Für diese Qualifizierung der der vor Nachbedingungen, gibt es jetzt verschiedene Level, das strikteste ist Safety, Bedingungen, die für die Sicherheit eben das Systems, wie jetzt der Speicherzugriff, nötig sind. Dann verschiedene Debugging Level, es gibt ein Level Pedantik für Sachen, die eigentlich nicht wirklich notwendig sind, aber vielleicht aus pedantischen Gründen doch. Und als letztes Level Analyses, das sind Bedingungen, die ich jetzt mal auch in dem Beispiel zeige, die zur Laufzeit praktisch gar nicht untersucht werden können, die aber für eine statische Analyse zur Verfügung stellen. Also hier haben wir zum Beispiel mit Quantoren über alle 32-bit Integers Aussagen über das Ergebnis von dieser Maxfunktion, die eben das maximale Element einer Sequenz von Integers liefern soll. So, was für Auswirkungen hat das auf die Zertifizierung für sichertskritische Systeme? Wir sehen, dass die Contracts geben einen relativ direkten Weg vom Code, die formalen Requirements, oder in den Code die formalen Requirements hinzuzufügen und diese auch zur Laufzeit, als Laufzeitschecks beispielsweise zu überprüfen, aber auch als Grundlage zu nehmen, um Tests zu definieren oder zu generieren oder formale Werkzeuge über den Code laufen zu lassen, die im Idealfall verifizieren, dass die Implementierung den Vor- und Nachbedingungen entspricht und diese korrekt implementiert. Es wird nicht in allen Fällen funktionieren, aber in manchen. So, jetzt das nächste. Seiteneffekte im Zusammenhang von Safety und Security. Hier ein paar Beispiele von relativ aktuellen Security Issues. Wir hatten Lock for Shell nicht vor so langer Zeit und das lag letztendlich an einem Seiteneffekt in Lock for Day, in der eine Logging-Operation im Code aus dem Internet nachladen konnte und ausführen konnte, was ein sehr überraschender Seiteneffekt ist, finde ich, nur was in der Lock-File schreiben möchte. Spring Shell ist eine andere Sicherheitslücke, sehr aktuell. Hier ein Beispiel, wo diese Sicherheitslücke dazu geführt hat, dass wir in einem Zugriffskontrollsystem eben die Sicherheit verlieren können. Das heißt wirklich, dazu führen kann das Angreifer Zugriff zu Gebäuden bekommen, wo sie eigentlich nicht reindürfen. Oder gerade letzte Woche, das Rust Decimal Crate, wo Code als Crate zur Verfügung gestellt wurde, der nur einen ähnlichen Namen hat zu einem sehr populären Paket, aber was ganz was anderes macht. Das heißt, hier haben wir wieder den Fall, wo Code Effekte hat, die überraschend sind, die der Anwender eigentlich nicht erwartet. Das heißt, das gemeinsame Problem von dieser Art von Sicherheitslücken ist, dass Anwendungen Code enthalten, der Sachen macht, die dieser Code eigentlich gar nicht soll, der Seiteneffekte hat, die überraschend sind. Das heißt, man setzt was ein und es passiert, aber das ist ganz viel, viel Schlimmeres, als was wir erwartet haben. Um dem entgegenzuwirken, ist in der Functional Community auch schon lange propagiert, dass man Seiteneffekt freien Code verwendet, das heißt nur pure Functions, die noch nicht mal irgendwelche Zustandsänderungen am System machen. Und äußere Seiteneffekte wie IO-Operationen werden dann modelliert, entweder als Monade oder als Effektsysteme. Das bringen noch weitere Vorteile wie Thread Safety und einfache Parallelisierung in der Implementierung. In Fusion werden jetzt Effekte eingesetzt, um Seiteneffekte zu modellieren. Fusion Features kommen ohne Mutation von Zustand, ohne Mutation von Daten aus, sind also Seiteneffekt freie, können aber Effekte voraussetzen in der Umgebung, die Sachen wie Zustandsänderungen, IO, Thread Kommunikation oder Exceptions zur Verfügung stellen und das das modellieren. Das heißt, alle nicht funktionalen Aspekte im Code müssen in der Form von Effekten spezifiziert und realisiert werden. Statische Analyse kann dann hergenommen werden, um diese Effekte zu verifizieren. Das heißt, für einen bestimmten Code zu bestimmen, was sind die Effekte, die dieser Code haben kann? Insbesondere für Bibliothekscode muss der Bibliothekscode auflisten, welche Effekte außer den rein funktionalen dieser Code verursachen kann. Und wenn die Statischen Analyse eben bestimmt, dass noch andere Effekte vorkommen können, dann ist das ein Compile Time Error. Das heißt, wenn man Code reinlädt, der eben spezifiziert, der macht nur Logging, der Compiler die Statischen Analyse testet, aber feststellt, aber feststellt, der kann aber auch beliebigen Code aus dem Internet runterladen und ausführen, sollte das ein Compile Time Error sein. Ich habe ein kleines Beispiel hier auf der Webseite, wie das an einem ganz kleinen Beispiel gezeigt funktioniert mit diesen Effekten. Das Beispiel, was ich habe, ist ein kleiner Würfel Die mit einer Funktion TOS, die den Würfel eben wirft und 10-mal das Ergebnis ausgibt. Die erste Implementierung ist völlig blöd. Ich habe einfach jedes Mal die Augenzahl 5. Wenn ich das ausführe, sehe ich, es kommt jedes Mal eine 5 raus und wenn ich das analysiere, was sind denn die Effekte, die das auslöst, sehe ich, es gibt nur einen einzigen Effekt, Io Out, das heißt, es gibt etwas auf Standard Out aus. Ich könnte jetzt auch den Code ändern und nach Standard R was ausgeben. Wenn ich den ausführe, sieht das Ergebnis erstmal ganz genauso aus. Wenn ich aber die Effekte analysiere, sehe ich jetzt, der Effekt ist, es gibt eine Ausgabe nach Io R. Ich gehe weiter, mache das Beispiel ein bisschen besser. Ich möchte jetzt natürlich, dass der Würfel auch unterschiedliche Werte zurückliefert und implementiere mir einen ganz, ganz einfachen Zufallszahlengenerator mit einem fest vorgegebenen Seat. Das heißt, ich kriege jedes Mal die gleiche Zufallszahlenfolge und wenn ich das jetzt ausführe, sehe ich unterschiedliche Werte, die rauskommen. Wenn ich es aber mehrfach ausführe, sehe ich, dass jedes Mal genau die gleiche Sequenz an Ergebnissen rauskommt. Wenn ich das jetzt analysiere auf die Effekte, die das hat, sehe ich, es hat Io Out wie vorher, aber es hat auch den Mutate Effekt und der kommt daher, dass hier dem Seat bei jedem Aufruf von Toss eben ein neuer Wert zurückgegeben wird. Das heißt, das Toss ist keine Pure Funktion mehr, sondern eine Funktion mit einem Seiteneffekt, die ein mutierbares Field Seat eben hier verändert und das sehen wir dann sofort in dem Code, im Ergebnis von der Analyse. Das nächste Beispiel benutze ich jetzt einen Nanotimer, um ein bisschen zufälligere Werte zu erstellen und wenn ich das mehrfach ausführe, sehe ich hier auch jedes Mal komplett unterschiedliche Werte und wenn ich das nach Effekten analysiere, sehe ich jetzt, es gibt keine Motability mehr, aber es gibt eine Abhängigkeit von dem Time Nano Effekt. Das heißt, es greift auf die Systemuhr zu, um eben unterschiedliche Werte zu liefern. Das letzte Beispiel, das kann man hoffentlich unten noch gut sehen, benutze ich für das Standard Bibliothek, die eine Random Feature zur Verfügung stellt und hole mir da einen 32-Bit Anseind Integer, um meinen Toss zu implementieren und nicht das ausfähre, sehe ich natürlich jedes Mal jetzt unterschiedliche Werte, was aber viel überraschen wird, wenn ich die Effekte analysiere, sehe ich, da gibt es unglaublich viel, also zumindest mehr als man typischerweise vielleicht erwarten würde und zwar insbesondere ist Random selber ein Effekt, wenn ich jetzt aber in dem Programm nicht explizit angebe, welche Implementierung von einem Random Generator ich möchte, fällt er zurück auf einen Nanotime basierten, das heißt, ich habe den Effekt Nanotime Nano, von dem das auch abhängt, aber die Standard Implementierung gibt auch eine Möglichkeit, über eine Environment Variable einen vorgegebenen Seed anzugeben, dass sich Reproducibility in Testläufen und so was herstellen kann. Das heißt, das hängt auch von dem Effekt Envy.Vars ab und wenn ein Seed über die Environment Variable angegeben wird, ist das ein Integerwert, der muss geparsed werden, das Parsen kann fehlschlagen, dann kann das System Panic ausführen, was auch ein Effekt ist, kann ein Error produzieren und vorher sich beenden. Das heißt, wir sehen hier auch sehr klar, was hier alles passiert und das zeige ich jetzt nicht in dem Beispiel, aber ich habe jetzt auch die Möglichkeit, das alles von außen her zu beeinflussen. Das heißt, ich könnte diesen Code ausführen in der Umgebung, in der ich beispielsweise den EnvironmentVars-Effekt durch eine eigene Implementierung ersetze und dazu beispielsweise sicherstelle, dass es auf keinen Fall von außen her eine Environment Variable dahinein fließt oder ich könnte den Panic-Effekt durch was anderes ersetzen, dass ich nicht die Anwendung beende, sondern das irgendwie anders behandle. Je nachdem, wie ich das rap. Okay, weiter zurück zu den Folien. Ja, das ist im Grunde nochmal zusammengefasst, die Standardimplementierung von Random, die eben ihren Seed entweder von der Environment Variable oder von Time Nano holt. Ja, ich habe schon viel gesagt, dass statische Analyse eine sehr wichtige Rolle bei Fusion spielt und dazu ist es natürlich wichtig zu verstehen, wie die Fusion Toolchain aussieht, wo die verschiedenen Ebenen sind, wo statische Analyse greift und dass die Anwendung oder Teile davon analysiert. Deswegen möchte ich hier grob präsentieren, das Design der Toolchain, was ich vielleicht noch nicht deutlich gesagt habe, das ist alles Work in Progress, das sind viele Sachen, die hier im Design vorgestellt sind, existieren noch gar nicht, sondern das ist die Idee, so soll es mal sein. Manche Sachen sind schon da, aber erwartet bitte nicht, dass das alles schon steht. Fusion, die Toolchain als Eingabe bekommt natürlich Fusion-Quelltexte.fz, Files, die durch den Frontend bearbeitet werden und das Frontend generiert daraus Fusion-Modul-Dateien, die sind ein bisschen vergleichbar mit Java-Class-Files oder Java-Modulen. Und diese Modul-Dateien werden dann von der middle-end in eine Fusion-Application, das heißt, in eine einzige Datei zusammengefügt, ein Hauptmodul der Anwendung zusammen mit den ganzen Bibliothekmodulen, die diese Anwendung benötigt. Und die Application ist dann die Eingabe für Optimierung und Analysen, die die ganze Anwendung benötigen für ihre Arbeiten. Und das Ergebnis von diesen Optimierung und diesen Analysen ist dann eine Fusion Intermediate Representation Datei, die als Eingabe dann genommen wird für verschiedene Backends. Im Augenblick haben wir zwei Backends, einen in Java implementierten Interpreter und einen Backend der C-Code erzeugt, den man dann in Maschinencode übersetzen kann. Aber das soll nicht dabei bleiben, es soll noch deutlich mehr Backends dazukommen. Wo passiert jetzt diese statische Analyse? Diese statischen Analyse, verschiedene Teile davon sind im Frontend, im middle-end und im Optimizer Analyse. Grundlage für die statische Analyse ist, dass die intermediate representation, das heißt, womit die Anwendung repräsentiert wird in den ganzen Zwischendateien, basiert auf einer sehr einfachen Zwischendarstellung, eine einfachen intermediate representation. Und die intermediate representation enthält im Grunde zwei Dinge, Features und Typen. Von Features gibt es in der intermediate representation fünf verschiedene Arten. Das sind entweder Routinen oder Felder oder Sachen wie Intrinsics, was in Java eine native Methode wäre. Abstracts oder Choices, ist ein Summtype für Leute mit einem funktionellen Hintergrund. Und Features enthalten selber eben ihren Namen, möglicherweise Code, Typen, das Ergebnis ist der Argumente und Features, die innerhalb von diesem Feature definiert werden. Wir können die alle nästen. Dann gibt es Typen, das sind entweder Typen, die direkt durch ein Feature definiert sind oder Typparameter, also generische Parameter. Der Code selber, es gibt im Augenblick nur zehn unterschiedliche Anweisungen, die der Zwischencode für Features die Code enthalten ausmacht. Und da sind Sachen wie Call und Match, Const und so weiter drin. Es gibt im Zwischencode keine Loops, keine Go-Tos. Es wird alles über Recursion oder über Matches dargestellt. Das macht es deutlich noch mal einfacher, das zu analysieren. Jetzt konkret, was passiert im Frontend-Analyse? Da passiert das, was typischerweise zu Compiler-Fehlern führt im Quelltext, das Type-Checking, die Analyse, dass keine Werte verwendet werden, bevor sie initialisiert werden und einfache Threads-Safety. Im Middle-End haben wir jetzt eine ganze Anwendung, die wir analysieren und da können wir Sachen machen wie Dead Code Removal, das heißt Code, der von der Anwendung gar nicht aufgerufen werden kann, wird entfernt. Code kann spezialisiert werden, das heißt beispielsweise eine Funktion mit Typparametern, mit Generics wird spezialisiert für den konkreten Typ, der eben in dem Code eingesetzt wird. Oder Sachen wie die Bestimmung von Daten, die nur fett lokal verwendet werden und nicht global nötig sind. Als Ergebnis davon haben wir die komplette Applikation und die kann jetzt weiter optimiert und analysiert werden. Da können Sachen passieren wie Compile Time Evaluierung, weitere Code-Spezialisierung, alle Sachen, die den Call Graph betreffen, Informationen, die man daraus ziehen kann. Ganz wichtig, die Livespan-Analysis, das heißt die Entscheidung, welche Allokationen auf dem Stack und welche auf dem Heap passieren sollen. Es sind vielleicht viele verwirrt, weil ich am Anfang gesagt habe, Fusion Features können als Klassen oder als Methode angesehen werden. Letztendlich ist der Unterschied zwischen der Klasse und der Methode. Eine Klasse wird auf dem Heap alluziert. Eine Methode kriegt ihre lokalen Variabeln auf dem Stack alluziert. Und das ist eine Entscheidung, wo kommt das eigentlich hin? Die macht hier dann der Compiler am Schluss, wenn er sieht, wie wird denn das wirklich verwendet. Braucht man das auf dem Heap oder können wir das auf dem Stack packen? Und ja, ein Programmweite Datenflussanalyse ist hier jetzt auch möglich. Das heißt, dass man sehen kann, bestimmte sensitive Daten, wie ein Passwort, das irgendwo eingegeben wird. Wo kann das dann in der Anwendung überall landen und verwendet werden? Außerhalb von der Toolchain, die ich jetzt präsentiert habe, gibt es noch eine Reihe an Unterstützungstools. Eins ist FC Java. Das nimmt ein Java-Modulpfeil und erzeugt daraus Fusion Rappers. So dass wir direkt Java-Code von Fusion aufrufen können, solange wir einen Backend verwenden, dass Java einbinden kann. Unser Java-Interpreter kann das natürlich. Das C-Backend kann es im Augenblick noch nicht, soll es aber über JNI oder ähnliche Mechanismen auch bald können. Und dann können wir in Fusion Sachen schreiben, wie Java lang System Outprint line. Hallo, Java. Oh, hier sind. Und damit eben eine Interoperabilität mit anderen Sprachen herstellen. Was entsprechendes für C haben wir leider im Augenblick noch nicht, ist aber auch geplant. Wir haben eine Language-Server-Implementierung, um eben Entwicklung mit IDIs oder auch mit Editoren wie WM oder IMAX zu unterstützen für Autocompletion, Hilfe mit Signaturen, Dokumentationen von Features und so weiter. Es gibt eine Fusion Doctool. Das Ergebnis von der Standardbibliotheken ist auf unserer Webseite, wo man die Dokumentation eben online dann brausen kann. Ja, ich komme jetzt schon zum Ende. Die nächsten Schritte bei uns für die Entwicklung in Fusion ist, ich habe gesagt, wir haben die verschiedenen Intermediate-Files. Im Augenblick gibt es nur die Modul-Files, die wirklich rausgeschrieben werden. Andere Sachen wie NIFEP und Puer-Files existieren im Augenblick nur. Im Schweiche werden nicht als Dateien rausgeschrieben. Das wird alles eben direkt von den verschiedenen Tools weiter gereicht. Wir arbeiten an einer einfachen Datenflussanalyse. Das C-Backend hat noch keinen Garbage-Collector im Augenblick und es fehlt auch noch ein Interface, um eben C-Bibliotheken anzusprechen. Und es gibt unglaublich viel, was in der Standardbibliotheken noch fehlt. Das ist nur sehr minimal. Damit komme ich schon zum Ende. Wir sehen, Fusion ist ein riesiges Projekt, das ist noch unglaublich viel Arbeit, das da reingehen muss. Aber ich denke, das ist eine spannende Sprache für den speziellen Anwendungsfall von safety-critical-systemen mit dem Fokus auf Simplicity, auf die Einfachheit der Sprache und der Analysierbarkeit des Codes. Es benutzt Design by Contract und Effects, um eben zum einen zu spezifizieren, was der Code macht und zum anderen zu kontrollieren, was für nicht funktionale Effekte Code haben kann. Und ja, es ist vorbereitet für statische Analyse. Es gibt wahrscheinlich noch sehr viel mehr mögliche Analysen, die man auf diesem Code letztendlich dann fahren möchte irgendwann. Wir müssen das kleine Team unbedingt wachsen lassen, so wie wir suchen nach Leuten, die Interesse haben, hier mit einzusteigen, mit beizutragen, entweder direkt an der Fusion-Implementierung, aber auch brauchen wir Feedback von Entwicklern. Was gefällt euch an der Sprache? Was sollte man anders machen? Was könnte man besser machen? Wir sind sehr dankbar für alles, was von außen reinkommt. Und wir suchen auch nach, das habe ich ja vorhin auch schon erwähnt, letztendlich Geldquellen, um langfristig die Entwicklung von Fusion sicherzustellen. So, gib bitte Feedback. Get involved. Wir sind offen. Ressourcen sind hier nochmal kurz gezeigt. Flango.dev, die mein Hauptseite, das Github repository, meine Firmen-E-Mail-Adresse ist hier auch noch. Ja, irgendwelche Fragen. Jo, vielen Dank schon mal für die. Das war doch auch sehr interessant. Auch für mich, der mich nicht so richtig mit Programmieren auskennt, aber gut. Da hinten sehe ich viele Fragen. Ich komme mal. Ich hätte kurz die Frage, wie machst du das mit Effekten bei C-Funktionen, die du aufrufst oder bei Java-Funktionen, die du aufrufst? Das stelle ich mir sehr schwierig vor. Nee, das ist leider sehr einfach. Für eine Java-Funktion, die aufgeführt wird, gibt es dann einen Effekt, der nennt sich Java. Das heißt, wenn man was ausführt, was diesen Effektheit hat, heißt es, es gibt einen Call in die Java-Welt und die kann alles machen, was die Java-Welt machen kann. Das heißt, wir verlieren an der Stelle sehr viel an Möglichkeiten zu sagen, was passiert hier eigentlich, weil wenn wir einmal in die Java-Welt reinrufen, kann in der WM so ziemlich alles passieren. Da kann ja zum Beispiel eine alte Version von Logforschell benutzt werden, um was zu loggen. Ja, auch eine Frage, zu mir wegzustehen. Ich nehm Andu-Verwendungsh-Effekt-Händlers. Reichstudi von außen rein? Oder was machst du da genau? Also die werden von außen rein gehalten, das ist gereicht. Das heißt, ich erzeuge eine Instanz von einen Effekt. Es gibt für die meisten Effekte die Möglichkeit, verschiedene Händler zur Verfügung zu stellen, die diesen Effekt dann implementieren. Das heißt, ich installiere einen Händler und führe dann mit diesem Händler bestimmten Code aus. Wenn das nicht, und das war in meinen Beispielen so, wenn ich nicht explizit einen Effekthändler installiere, dann gibt es für viele Effekte Default-Implementierungen. Das heißt, die Analyse findet, hier wird dieser Effekt verwendet. Der hat eine Default-Implementierung, das heißt, wenn das ausgeführt wird, wird die Default-Implementierung verwendet. Beispielsweise IoOut ist ein Effekt. Ich kann eine Implementierung zur Verfügung stellen, die die Ausgaben alle in der Datei umleitet und meinen Code dann ausführen damit. Das hat dann keine Ausgaben mehr, sondern leitet alles in der Datei um. Oder ich kann den einfach so ausführen, dann kriege ich den Default-Effekt, der das nach Standard-Out ausgibt. Ich hoffe, das war klar. Hier sehe ich was. Wie schaut das aus mit den ganzen Zusatzbibliotheken, die man da extra einbindet? Wie funktioniert da das Management und die Verwaltung? Er kommt jetzt darauf an, was du meinst mit Zusatzbibliotheken. Im Augenblick gibt es Infusion selber nur eine einzige Bibliothek, das ist die Standardbibliothek. Und es gibt ein paar Module, die mit dem FC Java Tool erzeugt wurden, um eben auf Funktionen in der Java VM zuzugreifen. Das heißt, wir haben für alle von Ihnen dann einen Fusion-Module-File. Und im Augenblick geben wir bei dem Fusion-Commando, also dem Compiler für Fusion, an, was sind die Module, die verwendet werden, ähnlich wie man in Java den Classpass angeben würde, was sind die dafalls, und die werden dann eingebunden. Ob es gibt noch im Augenblick noch keine Sprache, um das irgendwie zu formalisieren oder zu sagen, ich habe jetzt die Abhängigkeit von diesen oder jeden anderen Modulen. Sicher was, was wir langfristig irgendwann brauchen. Bei den Zufallsgeneratoren ist mir aufgefallen, dass die Werte wohl recht groß werden. Und ganz viele Sicherheitslücken basieren ja auf Integer Overflow. Enteger Overflow ist jetzt nicht grundsätzlich ein Fehler, wie ich das sehe, oder zumindest nicht für Anseintüben. Wie funktioniert das? Integer Overflow, wie wir das gemacht haben, ist, das für einen normalen Operation wie in Infix Plus oder Mal, ist ein Overflow ein Fehler. Das heißt, die ganzen Integer-Operationen haben eine Vorbedingung, die testet, dass die Werte nicht so groß sind, dass es zu einem Überlauf gibt. Und wenn man die Diva-Glevel eingeschaltet hat, dann werden diese Vorbedingungen auch getestet. Es gibt aber einen zweiten Satz an Operationen, die, ähnlich wie in Plus in Java, einen Überlauf einfach ignorieren und dann eben den überlaufgelaufenen Wert haben. Also die Operation, das ist vielleicht, was vielleicht jemand hat, eine Idee, wie man das besser machen könnte. Wir benutzen Plus, gefolgt mit einem Grad, wie Grad Celsius-Zeichen, und dann Varianten von Plus und Minus. Das heißt, wenn ich zwei Werte addieren möchte, 32 Bit Inteters und ich möchte, dass ein Überlauf eben möglich ist, dann nimmt man Plus Grad. Wie kriege ich das? Genau, ich habe dann noch eine Frage zu den Effekten. Meld ich mal kurz, ich sehe nicht. Genau. Wird das denn festgeschrieben von der Lüse Tool? Also gerade, wo wir jetzt das mit diesen Rastiz-Müll, das war ja eine Supply Chain Attacke, wird das denn festgeschrieben, so dass, wenn sich die Effekte ändern von einem Modul, warnt mich dann dieses Tool davor? Das ist im Augenblick alles noch nicht implementiert. Aber es wäre absolut notwendig, wenn ich einen Modul extern hinzufüge, dass ich zumindest eine Ausgabe gebe, dass sind die Effekte, die dieses Modul angibt, dass es hat und dass, wenn das eben verwendet wird, dass das auch überprüft wird, dass das nichts weiter ist. Aber es gibt sicher dann noch den mehr oder weniger manuellen Schritt, wenn ich einen Effekt, einen externen Einbind, muss man auch gucken, was sagt denn das, was es tut. Und wenn ich das Einbinde ohne das anzuschauen oder einfach alles akzeptiere, haben wir natürlich immer noch eine Möglichkeit, irgendwie, alles kann man nicht bieten, denke ich, ja. Okay, ich habe eine ganze Menge Fragen, aber ich nehme einfach mal die erste, die ich mir aufgeschrieben habe. Ich schreibe für Servomotoren, Wechselrichter und so weiter und so fort. Und am Anfang hingen so ein bisschen viel Vertrauen in die Kompiler raus. Also Kompiler sind clever und tun das Richtige. Das habe ich so ein bisschen rausgehört. Und es widerspricht sehr meiner Erfahrung aus dem Berufsleben. Kompiler haben Bugs, alle Kompiler. Also ich schreibe C und C++-Code und alle C++-Compiler generieren falschen Code. Man muss immer mit mehreren Kompilern arbeiten, gucken, wo die sich nicht einig sind, Kompiler patchen. Man muss unbedingt in den generierten Assembly-Code gucken, um zu sehen, ob der Kompiler wirklich das tut, was er soll. Das ist so meine Erfahrung aus dem Leben. Und ja, ich kann dieses vertrauen in Kompiler nicht nachvollziehen. Das ist für Safety Critical Code Besorgniserregend, sagen wir so. Es verunsichert mich sehr jetzt. Es würde dich vielleicht nicht überraschen, aber die Leute, die wirklich sehr kritische Safety Critical Systeme zertifizieren, die haben in den Zertifizierungen Standards, aber auch dann das Requirement, dass die Verifikation so weit geht, dass man letztendlich genau das macht, was du sagst, den erzeugten Maschinencode sich anschaut und auf der Ebene dann auch noch einmal verifiziert, dass es auch dieses Mapping zu dem ursprünglichen Code und zu den Requirements gibt. Das heißt, je nachdem, wie kritisch dein System ist, werden solche Sachen auch gemacht. Die Alternative dazu ist, es gibt ein paar wenige zertifizierende Kompiler, die eben ein Beweis mitliefern, dass der Code auch das Richtige macht. Aber da ist dann auch die Frage, wenn man natürlich den Beweis dann traut, aber das gibt auf jeden Fall auch zusätzliche Sicherheit. Aber du hast recht, in vielen Fällen, wo man eben diesen zertifizierten Kompiler noch nicht hat, muss man zumindest für die höchsten Kritikalität Level unter Umständen im Maschinencode nachgucken, dass der genau das Richtige macht. Ja, nochmal zu den Effekten. Eine Anmerkung. Eine Sache, die du natürlich machen kannst, ist, die Effekte in die Signatur packen, implizieren, wenn du es nicht hinschreibst. Und dann beim Callen quasi alle Effekte ausgrauen oder blockieren, die nicht jeder Signatur auftauchen. Das ist halt auch das Supplychain-Problem ein bisschen weniger. Kompiler, falls du wirklich so Probleme hast, guck dir mal, vielleicht kommt zert oder sowas anders. Das sind verifizierte Kompiler, die ja... Ja, vielleicht gerade zu den Signaturen. Wir haben noch keine Syntax dafür, aber wir möchten, im Augenblick ist die Signatur besteht aus den Value-Parametern und Typ-Parametern von einer möglicherweise generischen Funktion. Und wir möchten das erweitern, dass die Effekte auch Teil der Signatur sind. Möchten das aber nicht zur Bedingung machen, dass jeder Code, jedes Hello World, seine Effekte komplett auflistet, sondern das beschränken eben auf Library Code. Und dann, du hast vorhin das Beispiel mit Random gesehen, wo die default Random unglaublich viele Effekte schon beinhaltet, das dann aber auch auf der hohen Ebene, dass nicht die Default-Implementierung hergenommen wird, sondern dass ich sagen kann, diese Library Funktion benutzt aber den Effekt Random und das reicht dann. Je nachdem, wie ich das ausführe, mapft das dann zu allem, was ich mit der Default-Implementierung mitkriege oder wenn ich explizit was angebe, das dann. Aber ja, das muss dokumentiert werden. Das sollte in die Signatur zumindest für Bibeltake-Sache. Jupp, weil wir gerade bei dem Thema Random mitfahren, ist es nicht eigentlich auch sinnvoll, eher die Betriebssystem-Funktionalität zu nehmen, die es da jetzt inzwischen gibt, statt da irgendwie zeitbasierte Sachen zu nehmen, weil es gibt nicht umsonst ja inzwischen getRandom, was dann auch kriptografisch sicher wäre, was so ein timebasiertes typischerweise halt nicht ist. Absolut richtig. Wenn ich eine Anwendung sehe und ich sehe, das hat den Effekt, dass es Random benutzt und die timebasierte Implementierung verwendet, dann muss bei jedem, der irgendwas mit Kriptografie machen müssen, die Alarmglocken klingeln und sagen, das kann nicht sein. Ich brauche hier für diesen Code eine Abhängigkeit zu irgendeinem secure Random Provider für meinen System. Habe ich nicht auf allen Systemen, auf kleinen Systemen mag ich schon von der Hardware vielleicht möglicherweise gar nichts in der Richtung haben. Aber ja, das ist nötig und das ist auch, denke ich, Teil der Aufgabe des Developers dann eben noch zu sehen. Hier habe ich die Abhängigkeit von sowas und ein timebasierandom ist nicht geeignet für irgendwas, was Security-Operationen implementiert. Und dann eine andere Frage zu den Geschichten für die Effekte zum Vergleich jetzt Richtung Haskell. Welche Vorteile bietet man dort Fusion gegenüber, wenn ich jetzt aus der Haskell-Welt komme, wo ich ja eher auch komplett puristisch dort meine Funktion schreiben muss? Ich muss zugeben, ich habe zu wenig Haskell-Erfahrung, um das detailliert zu beantworten. Ich sehe aber hier, dass wir eine Sprache haben, die erstmal einfacher Zugänglicher ist, die eine einfache Interoperabilität mit anderen Sprachen hat, die vielleicht auch von meiner Geschichte ist, eine deutlichere Nähe zu Sprachen wie Java hat, aber in die funktionale Richtung geht. Wir sehen kleinere Einführungs-Pariären da reinzukommen, aber auch mehr Möglichkeiten. Ich erwarte, dass wir letztendlich eine bessere Performance erreichen können. Okay, wir sind eigentlich schon über der Zeit. Vielleicht noch eine letzte Frage. Ist es so eine Abschlussfrage oder eher Detail? Ja gut, also noch eine Frage. Wenn ihr dann noch mehr habt, könnt ihr euch natürlich gerne nochmal am Schluss mit dem Speaker draußen treffen und diskutieren. Ja, sorry, dass ich da noch mal hinten dran komme. Das ist ja jetzt noch recht jung. Man hat ja bei gerade neu sich bildenden Konstrukten immer das Problem, dass man vorsichtig sein muss, was man einführt, um die Evolution für die Zukunft fortzubereiten und gerade jetzt nochmal auf das Random kurz einzugehen. Das ist ein gutes Beispiel dafür. Habt ihr eine Meta-Konvention gebildet, die quasi sagt, hey, wir führen zum Beispiel in der Standardbibliothek nur das bare minimum ein. Also das wirkt jetzt ja schon so, als werden da schon sehr viele Seiteneffekte schon per Definition möglich. Und es ist so dem Prinzip der Geist, den ich rief, werde ich nicht mehr los. Will man das vielleicht weiter reduzieren, dass das wirklich nur random, wirklich bare minimum random constraints enthält, weil, jetzt kommt der Punkt, was passiert, wenn ich jetzt die Implementierung austauschen darf und ich neue constraints brauche, um die Implementierung zu supporten, dann muss ich dir sowieso separat überprüfen oder ich muss dieses gesamte Verifikationskonstrukt durch mein gesamtes Programm durchlaufen lassen. Habt ihr dafür ein Konzept, wie diese, ich sage mal, Austauschbarkeit und neue Einführungen der constraints über die Zeit der Software Evolution passiert? Sorry, das ist ein bisschen komplizierter geworden. Okay, es ist eine sehr weitreichende Frage. Ich muss sagen, wir sind da noch sehr am Anfang. Die Standardbibliothek ist auch noch weitgehend unstrukturiert, ist einfach ein Modul, wo alles, was mir mehr oder weniger jetzt erst mal gebraucht haben, drinnen gelandet ist. Das heißt, muss alles noch deutlich besser strukturiert werden. Aber wir haben definitiv die Möglichkeit eben, zum einen du fragst, es ist schon relativ detailliert, was Effekten da ist. Das ist gewollt. Wir wollen Effekte auf eine relativ feine Granularität haben. Wir wollen nicht nur einfach einen IO-Effekt haben, sondern einen IO-Out, IO-R, IO-File-Read oder sowas, das man relativ genau sieht, was da auch passiert. Aber dann auch eben die Austauschbarkeit haben. Das heißt, jeder Code, der auf irgendeinem Effekt basiert, der basiert erst mal auf dem abstrakten Effekt und welche genaue Implementierung, welchen Händler man dafür benutzt, um das auszuführen, das kann später entschieden werden. Das soll Austauschbar sein, dass man, gerade wenn Code Random verwendet, kann ich den mit SQL Random, vielleicht gibt es irgendwann einen Quantum Random Provider mit dem auszuführen, was auch immer. Okay, vielen, vielen Dank. Ich bin sehr glücklich über die ganzen Fragen hier. Tolles Publikum hier. Danke. Ich bedanke mich auch und bitte noch einmal Applaus für Friedi.