 Bei mir ist wieder der Neko und es geht hier um moderne Webentwicklung in Haskell. Ich habe schon gehört, es werden keine Monaten erklärt, aber vielleicht ein paar andere Sachen. Ja, hallo zum Lernseil. Nein, doch nicht. Sehr schön. Ja, modernes Web Development in Haskell, ja, am Beispiel des Projektes Marteamt. Zuerst mal will ich erklären, was ich unter moderner Webentwicklung verstehe und da muss man dann erstmal grundsätzlich eine Unterteilung vornehmen, welche Systeme, von welchen Teilen von Webentwicklungen man spricht. In der Regel unterteilt man da in Frontend und Backend, wobei Frontend die eigentliche visuelle Darstellung ist dessen, was der Benutzer sieht und dass Backend die gesamte Datenverarbeitung und Datenhaltung. Also im Backend benutzt man typischerweise etwas statischere Sprachen oder nicht ganz so bekannte Sprachen wie im Frontend PHP, Java im Enterprise-Unfeld, Ruby oder auch Python. Im Frontend verwendet man häufig HTML, CSS, JavaScript, klar, weil man ja was darstellen möchte im Webbrowser, aber dementsprechend spricht man da häufiger von Frameworks, die eben diese Sprachen benutzen, wie zum Beispiel React oder Bootstrap oder als Hilfs-Framework in jQuery. Aber wir reden hier jetzt nicht über typisches Web Development, sondern über Haskell. Was ist Haskell? Haskell ist eine rein funktionale Programmiersprache, d.h. Funktionen sind First-Class-Citizens dieser Programmiersprache und werden sind anderen Datentypen gleichgestellt. Haskell ist nicht strikt evaluiert wie im Gegensatz zu den meisten anderen Programmiersprachen, d.h. der Wert einer Zuweisung wird nicht erst dann, wird nicht ausgewertet, sobald man diesen Wert eingibt, sondern erst wenn er gebraucht wird, wenn tatsächlich eine Auswertung passiert. Also nicht bei der Zuweisung, sondern erst bei der Auswertung. Haskell ist stark statisch typisiert, d.h. die Typen müssen bei der Compile-Zeit schon feststehen und können sich nicht zur Laufzeit ändern. Das mag zwar Blödklingen in der Hinsicht, dass man überall die Typen anschreiben muss, muss man nicht, denn es gibt die sogenannte volle Typ-Inferenz. Der Compiler kann in aller Regel zur Compile-Zeit schon herausfinden, welche Typen da überhaupt durch die Kante schwirren. Wo wird das eingesetzt? Häufig in Big Data. Aufgrund seiner Eigenschaften kann Haskell unendliche Datenstrukturen theoretisch verwalten, solange man sie nicht auswertet, bei sonst dauert die Auswertung unendlich lange. Im Banken- und Finanzsektor wiederum da die Eigenschaften, dass Haskell-Code, man kann sehr gut nachvollziehen, wenn man Haskell gelernt hat, was der Code tut, aufgrund der Abkapselung von Seiteneffekten, die in Haskell passiert. Und in der Wissenschaft, genau, auch deswegen, weil man was in eine Funktion reingeht, auch wieder rausbekommen muss, im Sinne von, die sind vorhersehbar. Was ist also der Haupt Unterschied zur imperativer Programmierung, wie zum Beispiel mit C, C++, Java, PHP? Genau, wie ich schon angesprochen habe, es gibt eine stretende Trennung zwischen der reinen Berechnung, also einer Funktion und Seiteneffekten. Wie zum Beispiel der Zugriff auf das Netzwerk, der Zugriff auf dem Datenbank, der Zugriff auf User-Interfaces, also Maustassatoreingaben, sind alle weggekapselt und müssen quasi erst sauber gemacht werden, damit sie durch die reinen Funktionen durchgeleitet werden können. Variabeln sind unveränderlich. Einmal ist der Wert einmal zugewiesen, ist er fest für den Durchlauf der Funktion, sorgt dafür, dass man sehr sauber programmieren muss. Eigentlich ein Vorteil. Es gibt in Haskell keine Schleifen, also ohne weiter passieren falls. Also mit Konstrukten wie Vorschleife, Wildschleife findet man nicht. Dafür gibt es sogenannte Maps, also das Anwenden einer Liste auf eine Funktion und man erhält zurück eine Liste aus Ergebnissen. Oder wenn einem das nicht weiterhelft, dann kann man mit Rekursionen weiterkommen. Das macht keine Probleme, immerhin macht es das die Sprache immer noch Touring vollständig. Und es gibt kein State. Da Variabeln nicht veränderlich sind, einmal zugewiesen, sind sie fest. Kann man auch keine State-Variable irgendwo im globalen Namespace, wie man sagen würde, definieren, die sich dann immer wieder ändert und den State des Programms irgendwie definiert, gibt es einfach nicht. Oder nicht ohne weiteres. Ja, die Vorteile davon in der Webentwicklung, ja, da gibt es auch einige, zum Beispiel Serialisierung und Deserialisierung von Daten, so wie zum Beispiel Jason, ist relativ unkompliziert in Haskell. Es gibt gute Bibliotheken, die das können. Und die statische Typisierung ist es auch unmöglich, dass Datentypen falsch interpretiert werden, weil sie müssen ja feststehen. Datenverarbeitung kann leichter auf Korrektheit geprüft werden. Wie gesagt, die Funktionen sind nicht seiteffektbehaftet in aller Regel. Dementsprechend kann man auch mit automatisierten Test-Frameworks arbeiten, die einfach Input reingeben und wissen oder eine Erwartung auf das Ergebnis stellen können, welche einfacher nachzuvollziehen ist als bei seiteffektbehafteten Funktionen in anderen Programmiersprachen. Web-Anwendungen sind in der Regel zustandslos, also haben kein State, warum also eine Stateful-Programmiersprache verwenden. Und Web-Anwendungen haben häufig Konkurrente anfragen und dementsprechend müssen da entsprechend die Programmiersprachen oder auch die Frameworks und Bibliotheken erinnern können. Haskell kann das von sich aus relativ gut und dementsprechend hat man da nicht viel Schmerzen mit. Gehen wir nun auf das genaue Projekt Materamt zu. Das Materamt ist der Nachfolger vom Jamat. Der Jamat ist die zurzeit verwendete Getränkeverwaltung bei uns im Club und ist momentan auch immer noch in Benutzung, weil das Materamt noch nicht fertig ist. Aber nun die Konvention bei Materamt, die Programmiersprache ist nach wie vor in Haskell, genauso wie beim Jamat. Aber das Materamt ist nur ein Backend. Es ist nur eine Api. Also es ist keine Webseite wie der Jamat, der einfach einem ein User-Interface bietet, wo man knöpfe drücken kann, sich ein Getränk klickt, sein Guthaben abgebucht bekommt und fertig. Sondern es ist nur ein Backend. Es macht nur die Datenverwaltung und Datenhaltung und bietet nur eine Api an, mit der man über JSON-Objekte mit ihr reden kann. Dementsprechend verfolge ich mit dem Materamt eine Art Microservice-Architektur. Das Backend ist für sich gestellt. Das Frontend muss noch erzeugt werden. Das der Jamat hingegen war ein Monolith. Da wurde alles zusammengemischt. Auf einen Knopfdruck im HTML-Dokument wurde eine Datenbankabfrage gesendet. Hatte auch schon interessante Nebeneffekte bei uns in der Getränkeverwaltung gehabt. War nicht schön. Ja, dementsprechend, wenn es gar kein Frontend gibt, wie bedient man den tatsächlich? Nun, zukünftige Benutzer des Materamtes will ich hier sehr freundlich bitten und einladen und auch unterstützen. Ihre eigenen Clients bzw. Frontends für diese Api zu schreiben in Getweder-Programmiersprache, die sie gerade beherrschen oder auch benutzen möchten oder lernen wollen. Und dadurch, um das zu ermöglichen, unterstütze ich sie gerne auch indirekt, nicht nur persönlich, sondern auch, wie ich das Materamt geschrieben habe. Das Materamt bietet auf einem Endpunkt seine Api, seine Beschreibung, die Beschreibung der Api selbst nach OpenAPI 3.0 Standard und auch eine sogenannte Swagger UI, wo man sich die Anfragen auch in einer Weboberfläche zusammenklicken kann und abschicken kann. Entsprechend kann man so auch die Api Endpunkte erkunden. Einen Referenzclient habe ich auch schon in Arbeit, der heißt der Matebeamte. Ja, der bedient das Materamt und ist, wie gesagt, bereits in Arbeit, kann schon die Kernfunktionalitäten bedienen. Und als nächstes würde ich euch bitte, würde ich euch gerne etwas im Code zeigen oder bisschen zeigen, wie der Code im Materamt aussieht. Ich würde anfangen mit der Api selbst, wie die beschrieben ist. Die Mater Api selbst ist der Datentyp, der alle Endpunkte der Api beschreibt. Sieht etwas wild aus, aber es gibt eine Struktur darin, die hoffentlich erkennbar ist. Also es gibt Authentifizierungsanfragen, die gesendet werden können. Das wird sich noch etwas ändern, weil ich aus meinem selbst gebackenen Authentifizierungsschema ausbrechen will und auf, jetzt sage ich die Abkürzung, nicht falsch aussprechen, JSWT, also JavaScript Web Tokens, ummünzen will. Dementsprechend, alle Endpunkte, die hiermit auf anfangen, werden sich noch ändern. User, alle Endpunkte, die hier mit User anfangen, sind zur Verwaltung des Users gedacht. Also User, also Slash V1, wie hier oben beschrieben wird, also es fängt an mit Slash V1, Slash User und wenn man da ein Post-Request sendet mit einem JSON-Inhalt des Types UserSubmit, legt man einen neuen Nutzer an. So muss man das einfach verstehen, wenn man das liest. Entsprechend kann man sie mit Get-Requests User-Details geben lassen oder wenn man weitere User-Details ändern will, dann schickt man ein Patch-Request, wie es in einer Rest-App durchaus gebräuchlich ist. Entsprechend kann man auch User-Quarian mit einem Get-Request auf Slash User Slash List und Slash User Slash Recharge sagt einem auch hier, ich würde gerne Geld aufladen auf meinen Konto, muss man sich natürlich als dieser User authentifiziert haben und entsprechend im Header die Header-Authentifizierung. Das ist ja etwas vollgeschrittener Typmagie der Library Servant und ja, das geht auch so weiter mit Produkt und Bye und Journal. Journal ist die Übersicht über geleistete Bar-Transaktionen, also wie auch der Jahrmat will das Matheamt nicht unbedingt verfolgen, wer was wann gekauft hat, sondern einfach nur wer hat wann Geld eingezahlt. Es ist angedacht eine Avatar-Verwaltung zu haben, die ist aber noch nicht wirklich implementiert, habe ich relativ weit hinten in der To-Do-Liste, aber es gibt schon Nutzerrollen und entsprechende Berechtigungen, die man setzen und überprüfen kann und dann gibt es noch Settings des Matheamtes selbst, die geändert oder abgefragt werden können, natürlich nur wenn man eine entsprechende Rolle hat und dann gibt es noch eine Metainformation Tag, also eine Metainformations Endpunkt, wo zum Beispiel die Version oder andere Dinge drinstehen. Untergliedert ist das ganze Matheamt in mehrere Module und die sind auch gruppiert. Ich habe da, als ich angefangen habe, einen MVC, also ein Model-View-Control mehr oder weniger angestrebt, aber das Matheamt ist ja eine AP, dementsprechend gibt es kein View, also gibt es auch nur Control-Module und Modelsachen, Types und Classes sind halt Datentypen, also Types, da verstecken sich die ganzen Datentypen dahinter und Classes sind sogenannte Typklassen, in Haskell sind Typklassen etwa vergleichbar mit Interfaces in C++ oder anderen objektorientierten Programmiersprachen, nur mit ihrem eigenen Twist, dass man mehrere von denen implementieren kann, ohne dass man sich verrenken muss. Und Util sind halt Utilities. Datentypen sind in Haskell relativ schön gelöst, zum Beispiel wenn man sich den User anschaut, besteht der User eigentlich nur aus einer ID, seinem Namen, wie viel Gut haben er hat, wann er zuletzt eine Transaktion hatte, eine E-Mail, die optional ist und auch einer optionalen ID eines Avatars. Die folgenden Dreifelder existierten mal, sind aber momentan auskommentiert, weil ich sie nicht mehr brauche. Und hier zum Beispiel Instance-Data-Base-Representation-User ist eine Instanzierung einer sogenannten Typklasse und da ist einfach nur beschrieben, wie ein User, also der Datentyp des Users, wie ein User in der Datenbank aussieht, nur noch mal beschrieben. To-Data-Base ist genau andersherum, also To-Data-Base ist eine Instanz der To-Data-Base-Typklasse und die sorgt dafür, dass ein User in die Datenbank-Definition überführt werden kann und From-Data-Base genau andersherum. Das sind Typklassen, die ich selber geschrieben habe und das war es für den User selbst. Dann gibt es noch Summary, welche eigentlich nur ein Unterpunkt oder nur ein paar Unterfelder des Users sind. Dementsprechend gibt es da auch keine Datenbank-Option dafür, weil die nicht direkt aus der Datenbank geholt werden, sondern über den User definiert sind. Das so als Beispiel für wie man die Datentüten lesen kann. Die wahrscheinlich interessanteren Module sind im Control versteckt und Control sind wie gesagt die ganzen Berechnungen oder die Entscheidungen werden alle in Control gefällt. Wenn man sich zum Beispiel eine richtige Transaktion ansehen möchte, ist man in Control bei, ganz gut aufgehoben und ja, hier hat man eine Funktion, die heißt bei, also wohl würde man da was kaufen können. Sie nimmt entgegen ein Aufobjekt und ein PDS, was ein Purchase Detail, eine Liste von denen sogar ist. Zurück gibt sie ein Martehändler Purchase Result, Martehändler ist eine Monade. Es ist ein spezielles Datenkonstrukt in Haskell, welches ermöglicht, gewisse Dinge zu tun, die sonst in puren Funktionen nicht möglich werden, wie zum Beispiel Seiteneffekte. Datenbank, sprach ich ja vorhin an, ist ein Seiteneffekt. Dementsprechend kann ich über diese Monade tatsächlich auf die Datenbank zugreifen. Dementsprechend kann ich von der Monade die Datenbankverbindung erfragen mit Asks und dann ja der Connection und dann prüfe ich, ob die Produkte, die in den Purchase Details angefragt werden, tatsächlich verfügbar sind. Wenn sie nicht verfügbar sind, werden sie in einer weiteren Liste gespeichert und wenn nicht, dann ist alles in Ordnung. Am Ende wird noch geprüft, wie viel Geld tatsächlich dem Benutzer für seinen Einkauf abgehoben wird und dann ist das eigentlich schon fast durch mit Add to User Balance und einem negativen Preis. Buche ich dann das Guthaben ab, falls man sich als User authentifiziert hat. Es gibt nämlich die Möglichkeit einen sogenannten Bar-Einkauf zu machen. Da passiert das anders und am Ende wird einfach die, also wenn man sich als User authentifiziert hat, wird das Guthaben abgebucht. Man bekommt noch eine Rückmeldung, ob man nun im negativen Credit ist oder ob man noch Guthaben hat und damit ist man dann mit dem Einkauf durch. Hat man sich nicht als User authentifiziert, dann macht man einen sogenannten Bar-Einkauf, dann kommt ein neuer Eintrag ins Journal, also geht man davon aus, dass Bar eingezahlt wurde, dass muss ins Journal kommen und ja, das gibt dann einfach nur aus, hier bezahle bitte deinen Preis und damit ist auch damit der Einkauf beendet. Ich hoffe, damit kann ich die Verwirrung ein bisschen nicht weiter anstiften, die schon wahrscheinlich herrscht. Deswegen gehe ich nun lieber zurück zu meiner Präsentation. Wir sind gelandet. Falls euch der Code doch noch weiter interessiert, ihr findet den Codes sowohl fürs Maatabend als auch für den Maatbeamten auf meinem persönlichen Githi. Die Repos sind öffentlich geschaltet. Ihr könnt den Code euch anschauen, eventuell Verbesserungsvorschläge hinterlassen und so weiter. Gibt es dazu Fragen? Das Mikro kommt, genau. Jetzt könnte man sich natürlich fragen, warum man das ganz denn unbedingt jetzt mit so einer esoterische Sprache wie Haskell machen wollen, ein paar Beispiele hast du ja schon gezeigt. Ich selbst hatte Serven mal ganz kurz in den Händen und aber schon allein dafür, dass mir der Kopf explodiert, was das alles kann. Daher mal so die Frage, welche Vorteile bietet einem denn jetzt eben dieses ganze erweiterte Typsystem, was kann denn jetzt so, ich kann moderne Verbentwicklungen davon profitieren. Also man hat ja gesehen, du hast die API auch direkt auf Typ-Ebene definiert, was kann denn damit noch gemacht werden, damit jetzt irgendwie wird damit nur der Code gecheckt oder kann da noch was draus generiert werden, wie zum Beispiel die API-Diskription oder noch ganz viel andere Magie, die dann letztendlich Arbeitsspat und Korrektheit sicherstellt? Du hast es gerade schon richtig angesprochen. Ja, dadurch, dass die API wirklich als gesamter Datentyp definiert ist, kann ich mir aus diesen Datentypen und seiner Beschreibung, wie sie da stand, die Swagger UI und die Swagger JSON generieren lassen. Also eine Änderung an der API selbst wird sofort automatisch übersetzt. Ich muss da nicht nochmal irgendwelche Dateien händisch anfassen, damit quasi der Zustand der API und der Swagger JSON synchron ist. Weitere Vorteile ergeben sich auch daraus, dass ich anfangen kann, automatisiert mit Testing Frameworks, wie zum Beispiel HPEG oder sogar QuickCheck, mit zufälligen Daten, meine ganze API zu testen. Dann gibt es Plugins quasi für QuickCheck für, die dann, also Servant minus QuickCheck heißt die Library, die das macht. Da kann ich wirklich automatisiert zufällige Daten gegen meine API schießen lassen und schauen, ob der Server tatsächlich auch richtig antwortet. Ich hoffe, das erklärt deine Frage. Hast du dir schon mal Haskell im Frontend angeguckt? Gibt es sowas überhaupt? Also, dass Haskell nach wassen kompiliert wird oder sowas? Also ja, es gibt Haskell auch im Frontend. Man kann sich HTML über so genannte, über die Blaze Bibliothek machen oder bauen lassen. Ja, das sieht ein bisschen wild aus manchmal, aber es geht, der Matebeamte ist tatsächlich so gebaut, aber selbst in der Dokumentation zum Blaze steht manchmal, will man das wirklich so machen? Deswegen bin ich am überlegen, ob ich dann nicht doch eine andere Bibliothek noch verwende. Aber da müsste ich noch, wie gesagt, ein bisschen Forschungsarbeit betreiben. Ich habe noch eine kurze Frage. Wie sieht es mit Websockets aus? Moderne Webprogrammierung bedeutet auch, dass ich solche Technologien wie Websockets einsetzen will. Bietet Haskell dafür eine Möglichkeit? Das habe ich jetzt tatsächlich nicht auf dem Schirm, ob ich Websockets wirklich einsetzen kann. Würde mich wundern, aber wenn nicht. Weitere Fragen? Ja, ich würde mich auch gerne mal interessieren. Also ich komme jetzt eher aus einer Welt, in der man beklassigt programmiert, Java, C, solche Dinge und ich vergleiche jetzt gerade in Gedanken mit deinem Ansatz, das mit Haskell zu machen und ich überlege gerade, wie sind das mit der Testbarkeit des Codes aus? Also wenn ich jetzt meinen JUnit Test schreibe oder was, ist das vergleichbar? Gibt es vergleichbare Instrumente, die man in Haskell verwenden kann oder kommt das automatisch mit oder macht mir das das System einfach zu testen oder was sind denn da deine Erfahrungen? Geht das besser, schlechter? Das hängt ganz davon ab, wie du deinen Code geschrieben hast in Haskell auch teilweise, sobald du halt mit mit Seiteneffekten zu tun hast, wie gut du diese Kapselung tatsächlich einhältst. Aber ja, reine Funktionen in Haskell lassen sich sehr einfach testen, weil aufgrund der Eigenschaften von nicht mutierbaren Variablen oder Statelessness des gesamten Codes kannst du davon ausgehen, dass bei gleichem Input in eine Funktion immer auch der gleiche Output aus der Funktion rauskommt. Dementsprechend sind JUnit Tests auf einer Ebene automatisierbar, dass du eigentlich nicht sehr viel Aufwand damit hast. Und in der echten Welt, also jetzt ein Beispiel mit der Mathe Software, wie sieht es da aus? Kannst du da diese Standards einhalten oder hast du dann doch Seiteneffekte, die dich dann quasi dir das Leben schwer machen? Nein, eigentlich nicht. Also du kannst natürlich auch eine temporäre Datenbank aufsetzen, jetzt im Sinne von Integration Tests. Ob nun, da musst du wiederum diese temporäre Datenbank richtig befüllen, aber die kann dann auch genauso automatisiert in automatisierte Tests eingebunden werden. Ich hoffe, das klärt deine Frage. Noch weitere Fragen? Vielleicht eine eher ironische Frage, aber weiß nicht. Haskell ist ja vor allem dein Hobby, oder? Ich habe gerade nicht verstanden. Haskell programmiert, es ist vor allem eher dein Hobby, oder machst du das auch für Grunerwärme? Also Haskell hat bei mir als Hobby angefangen, aber mittlerweile mache ich Haskell auch beruflich. Okay, gute mich, sonst wäre meine Frage gewesen. Bei vielen Leuten weiß ich nämlich, dass die das quasi einfach so zum Frustabbau, zur Entspannung gegenüber dem machen, was sie sonst irgendwie beruflich machen müssen. Deswegen die Frage, was musstest du kompensieren, um Haskell zu machen? Nee, also ich empfinde Haskell nicht wirklich als Frust. Natürlich mache ich auch andere Dinge in meiner Freizeit als Programmierung. Also sehr vielleicht gestern meinen Vortrag gehört hat, ich zeichne auch Comics, aber das ist jetzt nicht Gegenstand dieses Vortrages. Aber ja, ich mache auch gerne in meiner Freizeit weiter, Haskell, weil ich habe keine oder wenig Schmerzen mit der Programmiersprache. Wie ist denn der, oder hat meine Frage? Wie ist denn der Einstieg in Haskell für jemanden, der neu ist? Also ich habe ja ein bisschen was gemacht im Universitätskodext, Größenordnung 2016, das ist jetzt auch schon ein bisschen her. Ich habe auch nicht allzu viel reingemacht, dass weil hauptsächlich darauf beschränkt was in dem Kurs halt behandelt wurde und da ging es halt hauptsächlich um Fundamentals und Algorithmen und sowas. Wie ergonomisch, sage ich jetzt mal, ist der Einstieg, weil gerade solche neueren Programmiersprachen wie Go oder Rust oder sowas brüsten sich, damit es besonders einfach ist irgendwie schnell anzufangen. Sie haben Detail der Materialien, solche Sachen. Wie sieht es dabei Haskell aus? Ja, das hängt ein bisschen auch vom Hintergrund ab, den man hat, aber man behauptet so gerne und ich muss das leider auch ein bisschen bestätigen, wie Lernco von der Haskell hat Überhänge. Also, sie verläuft, ja, nicht ganz korrekt. Man bleibt manchmal ganz schön hängen. Es ist schwer, insbesondere, wenn man halt objektorientierte Programmierung gewohnt ist oder auch imperative Programmierung. Es gibt es halt sehr, sehr viele Konzepte, die man bei Haskell einfach über Bord schmeißen muss, weil sie so nicht funktionieren. Die Sprache funktioniert einfach nicht objektorientiert, sie funktioniert auch nicht imperativ. Und wenn je nachdem wie fest gefahren man in diesen Konzepten drinnen hängt, wird das schwierig. Ich selber habe ja auch nicht unbedingt mit Haskell angefangen, sondern habe meine Laufbahn als Programmierer mit Java angefangen. Aber das war noch in der Schule. Unsere Informatik-Lehrerin war sehr avantgardistisch, um es mal so auszudrücken. Ich habe auch erst später zu Haskell gefunden, aber auch über andere Programmiensprachen wie Lua oder C. Und Haskell hat mir da sehr gefallen, letztendlich, weil ich habe zu dem Zeitpunkt noch Werkstattwissenschaft studiert, also eine Ingenieurswissenschaft. Und plötzlich konnte ich Konzepte, die ich in der Mathevorlesung hatte, durchaus praktisch anwenden, ohne mir groß Gedanken zu machen, wie implementiere ich das jetzt. Ich konnte es quasi fast genauso ausdrücken, wie es auf der Folie vom Professor stand. Das fand ich sehr charmant. Ja, ich glaube, das ist ein bisschen so, es gibt ja einen Menschenschlag, der abgestreckt ist, wo man neues Programmierparatik mal sieht, und es gibt einen Menschenschlag, der dann total begeistert und ist da reintaucht und so weiter. Ja, genau. So in der Art kann man es beschreiben. Ich habe jetzt auf Arbeit ein bisschen zu tun mit einer Sprache, die ähnlich zu Prolog ist. Aber das ist eine andere Sache. Wenn wir keine weiteren Fragen haben, würde ich in der Stelle mal den Deckel draufmachen und einen noch mal einen herzlichen Dank an Nico sagen.