CRE122 Compilerbau und Typtheorie

Vom Übersetzen und Optimieren von Programmcode

Episode image forCRE122 Compilerbau und Typtheorie

Compilerbau ist eine komplexe Materie aber auch keine Magie. Andererseits ist es ein Feld, in dem in letzter Zeit wieder eine Menge Bewegung gekommen ist, teilweise ausgelöst durch neue Erkenntnisse, teilweise durch den hohen Bedarf an schnellen, dynamischen Programmiersprachen im Web. Hannes Mehnert erarbeitet gerade seine Diplomarbeit in diesem Themenfeld mit einem Schwerpunkt auf Optimierung und Typtheorie und erläutert im Gespräch mit Tim Pritlove die Hintergründe dieser Ansätze und gibt einen Überblick über weitgehend unbekanntes Terrain.

avatar
Tim Pritlove
avatar
Hannes Mehnert
Shownotes

Links:

47 Gedanken zu „CRE122 Compilerbau und Typtheorie

  1. Sehr interessant. Hör mir jetzt zum zweitenmal an. weil ich einige stellen nicht wirklich verstanden hatte. also dieser podcast ist wirklich advance und trotzdem awesome. mehr davon please.

  2. Ich höre mir gerade den Podcast an und muss feststellen, Hannes hat leider kaum Ahnung von formalen Sprachen und Automatentheorie. Echt schade!

  3. Wollte nur sagen bezügl. wie ernst das Thema Compilerbau auf der Uni genommen wird: Bei uns auf der Technischen Universität Wien gibt es eine Compilerbau-Institut („complang“) und folgende Lehrveranstaltungen:
    Übersetzerbau (pflicht im Bakk.)+*
    Fortgeschrittener Übersetzerbau (naja, ist nicht wirkl. fortgeschr.)*
    Objektorientierte Programmierung (pflicht im Bakk.)**
    Logikorientierte Programmierung (pflicht im Bakk.)+*
    Funktionale Programmierung (pflicht im Bakk.)+*
    Abstrakte Maschinen (nettes kleines Wahlfach)*
    Programiersprachen (Wahlfach im Master)+*
    Typsysteme (Wahlfach im Master)*
    Fortgeschr. Objektorientierte Programmierung (Wahlfach im Master)+***
    Fortgeschr. Logikorientierte Programmierung (Wahlfach im Master)+
    Fortgeschr. Funktionale Programmierung (Wahlfach im Master)+*

    * hab ich gemacht
    ** hab ich aus der HTL angerechnet und somit nicht an der Uni gemacht
    *** bin grad dabei
    + mit Übung (ansonsten ists ne reine Vorlesung)

    kA ob ich was relevantes aus dem Bereich vergessen hab. Man kann aber schon sagen das es bei uns ein großes Angebot in dem Bereich gibt. :)

    Ok, genug gespamt.

  4. Vielleicht wird das ja noch gesagt (bin grad mitten im Podcast) aber XSLT ist auch eine funktionale Sprache. Und eine rein Funktionale Sprache kann man natürlich verwenden, nur halt nicht als general purpose Sprache. Z.B. eine Sprache die nur Mathematische Ausrücke auswerten kann wäre rein Funktional. Eingabe kann man da noch in der Form von Parametern haben, aber eben kein I/O.

  5. @Sortieren bei Java. Comparable und Comparator etc. sind ganz genau die Konzepte aus funktionalen Sprachen bezügl. higher order functions. Nur ist halt die Syntax SEHR verbose. Könnte sich in der nächsten Java Version ändern. Aber so kompackt wie Haskell, CAML etc. wirds trotzdem nicht.

  6. @Alle Sprachen die nicht das Lambda Kalkül als Grundlage hat sind murks: Da wurden aber die logikorientierten Sprachen wie Prolog. Ich hab mir aber eingebildet das es für C auch einen Beweis gibt. kA.

  7. Schwache Tüpung kann auch Performance bringen. Ein klein wenig jedenfalls. Heutzutage ist das eigentlich kein Argument mehr. Nunja, eventuell auch Mikrocontrollern oder ähnlichem.

  8. @Entweder allse dynamisch oder alles statisch:
    1. Ist das so eigentlich generell falsch, denn in eigentlich jeder OO Sprache gibt es dynamische teile (Casts die erst zur Laufzeit als Fehler erkannt werden).
    2. Gibts in C# 4.0 das dynamic keyword (ich nenns Pseudotyp):
    http://en.wikipedia.org/wiki/C_Sharp_(programming_language)#Dynamic_member_lookup

    Auch sehr interessant zu schaun ist das hier verlinkte Video:
    http://tirania.org/blog/archive/2008/Nov-03-1.html

    Ich bin zwar eher auf der Java Seite, aber das was man da so von C# ließt macht einen schon den Mund wässrig. Aber ich seh da auch viele viele Probleme an C#. An einigen Stellen ists offensichtlich net ganz durchgedacht und die Semantik nicht ganz klar. Das ist auch ein bekanntes Problem. Siehe:
    http://themonkeysgrinder.blogspot.com/2009/04/whos-afraid-of-generic-variance.html

  9. Ich glaub bei mir oder zw. den Lehren verschiedener Professoren gibts eine Begriffsverwirrung. Ich dachte subtypes sind das selbe wie subclasses. Dachte class sagt nur das es halt ein OO Typ ist. Ich schätze da wird der Unterschied zw. subtyping und inheritance gemeint sein. Dieser unterschied ist mir vollkommen klar (semantische Untertypbeziehungen Vs. Code Vererbung). Hätte da gerne eine Bestätigung, dass da das gemeint ist, denn ich hab subclass Vs. subtype auch grad in einen Paper gelesen, das ich wegen einer Seminararbeit lese, und hab mich da schon gewundert. Unser Prof. hat immer die Begriffe Subtyping und Inheritance (bzw. Code Vererbung) benutzt.

  10. @Dependent Types:
    Prof. Puntigam mach in allen seinen Vorlesungen immer einmal Wunschkonzert und einer hat sich bei uns das Thema dependent Types gewünscht, deswegen gibts da jetzt nen Foliensatz auf der Typsysteme Seite dazu:
    http://www.complang.tuwien.ac.at/franz/typsysteme.html
    Event. in dem Zusammenhang auch die Folien zu Prozesstypen lesen!
    Wobei die Folien alleine relat. Schwer zu verstehen sind. Man sollte da immer in die Vorlesung gehen und sich Notizen machen. Prof. Puntigam sagt viel das nicht auf den Folien steht.

  11. @Operatorüberladung: In C++ geht das! :P

    class Foo {
    // habe dazu den Source NICHT
    };

    Foo operator + (const Foo & lhs, const Foo & rhs) {
    return …;
    }

    // natürlich geht auch Foo + int:
    Foo operator + (const Foo & lhs, int rhs) {
    return …;
    }

    Foo operator + (int lhs, const Foo & rhs) {
    return …;
    }

    Ob das jetzt schön ist, ist eine andere Frage, aber es geht und wird denk ich auch verwendet.

  12. Im ersten Teil der Sendung ging es um funktionale Sprachen. Da würd ich dann auch gerne noch meinen Senf zu geben :)

    Man unterscheidet bei funktionale Sprache generell zwischen denen die nur teilweise funktional sind und denen die vollständig funktional sind. Letztere werden häufig als „pure functional“ bezeichnet. Pur bedeutet nun, dass die Sprache frei von Seiteneffekten ist. Das heißt, eine Funktion hängt nur von ihren Eingabeparametern ab, nicht von irgendwelchen globalen Zuständen etc. …

    Diese Freiheit von Seiteneffekten bringt einige Vorteile mit sich. So kann man beweisen, dass eine Funktion auch tatsächlich das tut was sie soll, ja sogar dass sie nur das tut was sie soll.
    Andererseits soll eine Programmiersprache auch einen gewissen Nutzen haben, wie etwas Ausgeben oder auf Eingaben reagieren. Es gibt also Seiteneffekte die gewollt sind :)

    Das faszinierende ist nun, dass sich Seiteneffekte und „purity“ nicht widersprechen müssen. An dieser Stelle kommen dann Monaden ins Spiel.

    Eine Monade ist im Prinzip etwas einfaches, sie zu erklären gelingt aber nicht immer auf Anhieb :) In aller kürze kann man sagen, dass eine Monade ein Zusammenschluss von ein paar Dinge ist, darunter auch eine Funktion.
    Wollte man jetzt z.B. eine Ausgabe machen, so bekommt diese Funktion nicht nur den String den sie ausgeben soll, sondern auch „die gesamte Welt“ als Parameter :) Jetzt wird in der Funktion die gesamte Welt in eine neue Welt überführt, in der unser String ausgegeben wurde :) Das ist jetzt natürlich etwas überzogen, aber im Prinzip nicht verkehrt. (Ich könnte hier ins Detail gehen, aber das ist vielleicht für ein Kommentar zu viel :))

    Mit diesem Konzept wird dann eine rein funktionale Sprache auch nützlich :)

    Ein Beispiel für solch eine rein funktionale Sprache ist Haskell. Und es gibt tatsächlich Menschen, die mit Haskell Probleme lösen, angefangen bei mathematischen Programmen, über Chatbots, bis hin zu ganzen Windowmanagern. Und Haskell wächst und wächst und wächst :)

    Abschließend kann man also sagen, dass funktionale Programmierung an sich ein sehr spannendes Thema ist, welches viele viele sehr spannende Konzepte mitsich bringt, die garantiert eine eigene Sendung füllen würden. :) (Was im übrigen auch sicher spannend währe!)

    So nu hab ich aber genuch gelabert :)
    viele Grüße,
    frosch03

    P.S. jetzt hät ich’s fast vergessen, fand die Sendung wirklich cool und es war echt schön mal wieder was von Dylan zu hören :)

  13. @Hannes: Danke für den Link! Hab das mal überflogen und das schaut tatsächlich so aus als ob das was hier unter Subtyping Vs Subclassing verstanden wird das ist, was uns mit Subtyping Vs Inheritance erklärt wurde.

  14. Hi Tim!

    So lobenswert und interessant ich generell sehr technische CRE-Folgen finde – diese hier gehörte für mich zu den schlechteren Episoden. Zusammengefasst kann man sagen: ein komplexes, sehr wissenschaftliches Thema wurde hier unnötig kompliziert verhackstückt.

    Es gelang nicht, trotz vieler Nachfragen, die einzelnen Zusammenhänge klar darzustellen. Thematisch wurde m.E. zu viele Klammern nicht geschlossen. Der Gesprächspartner wirkte (auf mich) oft leicht genervt; und trotz seiner sicher unbestrittenen Fachkompetenz hat er sich viel zu oft im Kreis gedreht und sich hinter Begriffen versteckt, wenn er etwas nicht schlüssig erläutern konnte.

    Trotz dieser Kritik ein grosses Lob für die geleistete Arbeit. Man kann es nicht oft genug betonen, wie wertvoll CRE für langweilige Autofahrten ist. Qualitätsanspruch für Sound unbedingt beibehalten.

  15. Naja ,obwohl ich nur mittelmäßig Ahnung von dieser Materie habe ist mir die eine oder andere Ungereimtheit aufgefallen. Eigentlich hätte ich mitschreiben müssen, weil ich so vieles vergessen habe. Aufgefallen ist mir aber, dass die Trennung von Strukturen und Funktionen gelobt wurde, als wäre das was Neues. Das ist eigentlich das Prinzip von C. Um dies abzulösen erfand man ja OOP wo man „Strukturen“ also Klassen Operationen zuordnet.

  16. Das Thema spricht mich nun gar nicht an; sei es aus mangelndem technischen Verständnis oder weil bei mir schlicht kein Interesse vorhanden ist – schade chaosradio, vielleicht gelingt´s euch beim nächsten mal!

  17. Hab mich sehr gefreut auf das Thema weil es mich wirklich sehr SEHR interessiert. Du schaffst es ja auch immer sehr kompetente Leute als Gesprächspartner für sowas heran zu ziehen. Leider war es diesmal nicht so. Kaum eine Aussage von ihm war ohne grösseren inhaltlichem Fehler, und dies auch schon bei den elementaren Grundlagen. Naja, wenigstens waren die Verweise auf die anderen aktuellen Arbeiten interessant. Dafür hat sich das anhören schon gelohnt.

  18. Die Aussage, dass Compilerbau ein reines Thema der Informatik ist und kein Wissen anderer Disziplinen erfordert, finde ich sehr gewagt. Man braucht zwar nicht wissen, wie ein Transistor funktioniert, aber man muss schon wissen wie der Prozessor aufgebaut ist, bespielsweise wieviel Bits in ein Register passen. Ich mag mich zwar taeuschen, aber dieses Wissen ordne ich eher in die Disziplin E-Technik statt Informatik ein.
    Auch wurde das Thema leider vorwiegend aus der Sicht der Programmiersprachen beleuchtet. Ebenso wichtig ist es sich anzuschauen welche Schwierigkeiten bei der Codeerzeugung fuer verschiedene Architekturen (nicht jeder Prozessor ist ein x86 Derivat) auftreten.

  19. Leider muss ich sagen, dass ich bei wenigen der letzten CRE-Folgen so oft die Stirn gerunzelt habe wie bei dieser, sei es mit Einsprüchen oder mit „das kann man doch viel einfacher erklären“.

    * AST aufbauen: man kann durchaus auch direkt im Parserdurchlauf Maschinencode rausschreiben, ohne einen AST aufzubauen — der Code ist dann halt unoptimiert und der Compiler schlecht wartbar.

    * um im Programmiersprachenkontext Seiteneffekte zu erklären, kann man, statt das große Fass IO aufzumachen, auch einfach Mutable State nehmen.

    * Außer Lambda-Kalkül gibt es als Zwischencode-Repräsentation mindestens noch Stack-Maschinen (z.B. Java-Bytecode), Zweiadress-Maschinen, Dreiadressmaschinen etc. Und grad Lambda-Kalkül ist als Zwischencode erst mal verwirrend.

    * Man kann durchaus auch bei imperativen Sprachen Korrektheitsbeweise führen (etwa mit dem Hoare-Floyd-Kalkül). Macht keiner, klar.

    Und so weiter. Ich bin halt als CRE-Hörer von der durchschnittlich sehr hohen Qualität der CRE-Folgen verwöhnt. Nach so vielen Interviews mit Leuten, die einfach alles über ihr Thema wissen und genau wissen, wo ihr Wissen endet, fällt eins mit jemandem, der „nur“ Experte ist, eben auf :)

  20. In C kann man auch Funktionen über Funktionspointer in Variablen speichern und als Parameter an andere Funktionen übergeben. Deswegen würde ich C trotzdem noch nicht als funktionale Programmiersprache bezeichnen. Für mich muss eine Sprache zumindest auch anonyme Funktionen und Closures (der Kontext wird eingefroren) unterstützen, bevor ich sie in die funktionale Ecke rücke.

    In Java ist eine anonyme innere Klasse, die ein Interface mit nur einer Methode implementiert (Beispiel ‚Comparable‘) vergleichbar mit einem Closure.

    Seiteneffektfreiheit ist übrigens sehr hilfreich bei paralleler Programmierung.

  21. Was auch immer an dieser Sendung nicht optimal gelaufen sein mag: Das Chaosradio ist eine großartige, dankenswerte Sache! Ich lerne sehr viel dabei (die Beiträge, Ihre Teilnehmer und die hier sichtbaren kontroversen Kommentare motivieren stets dazu, sich selbst zu informieren) und fühle mich gut, weil intelligent und angeregt unterhalten, ganz anders als durch das öffentlich-rechtliche Radio.

    Dank an Euch, an den ccc – mit Grüßen aus dem Ruhrgebiet.

  22. ui, bin bei Minute 35… htte mir das extra aufgehoben für die Feiertage ….
    habe keine Ahnung wie Hannes Mehnert da durch will. Er hat zwar ein gutes Gefühl
    aber wirklich wenig Ahnung … Peyton Jones als alten Professor zu bezeichnen und dann nach 20 Minuten bei den Monaden ankommen, sehr mutig. Vielleicht doch eher die Maxwell Gleichungen?

    Super Thema, hochaktuell, überhaupt nicht theoretisch, aber bis Minute 40 wirklich verkackt. Tim klingt auch schon jetzt recht reserviert.

    mal hörn‘ wie’s weitergeht.

  23. Viele der angesprochenen Sachen kommen mir auch aus C#/.NET bekannt vor, allerdings bin ich noch nicht weit genug, um das richtig beurteilen zu können.
    In den Microsoft Videos ist das natürlich alles ganz Klasse und im CRE wird Microsoft ja traditionsgemäß, außer in der einen Sendung, nicht besonders liebevoll behandelt. Das macht mir auch keine großen Probleme das sich das gut ergänzt, wenn man umfassend informiert sein will. Eine Sendung zu C#/.NET wäre aber schon ganz nett um auch mal eine einigermaßen objektive Meinung zu hören.

  24. mea culpa, es ist viel besser geworden. Super spannend und obwohl Tim aus Hannes die Ursache des Leuchtens nicht herauskitzeln konnte, eine sehr übersichtliche Gesprächsführung. DSLs und die Chancen von „beweisbaren“ Programmstücken, die dann ja auch leicht in die Hardware rutschen können; hierarchisch parallele Datentypen und solche Dinge kamen leider nicht zur Sprache.

    Trotzdem super. Macht einfach Spaß, dieser Podcast.

  25. Coole Sendung!
    Aber ich kam mir noch nicht so dumm vor… *nixversteh*
    Ich muss mir das Teil wohl noch 5 mal anhören.
    Oh mann habe ich Kopfschmerzen

  26. Hallo Tim,

    ich wollte mich mal für Deine Podcasts bedanken! Ich wüsste kaum ein anderes Format, bei denen man sich so angenehm ausführlich lange Zeit nimmt und gleichzeitig weder langweilig noch vollkommen abgehoben diskutiert. Das gilt sogar für Themen, bei denen ich mir Anfangs unsicher bin, ob sie mich überhaupt interessieren. Wer hätte gedacht, dass ich als nicht-Informatiker und bestenfalls Hobby-Programmierer jemals Sendungen über Compilertheorie oder Virtualisierung nicht nur spannend finde, sondern – so denke ich zumindest – grösstenteils kapieren würde. :-)

  27. Hey, wie wäre denn mal eine Sendung über Haskell und vor allem Monaden. Meinst du du kennst jemanden der sich da auskennt Tim?

    Ich fänds sehr interessant.

    Ansonsten war es echt ne tolle Sendung, wobei ich manchmal doch echt den Eindruck hatte das da was falsch rüber gekommen ist (Lambda-Kalkül).

  28. Hallo,

    ich fand den Gesprächsverlauf sehr zerhackt. Und man hätte einiges einfacher erklären können und mit Beispielen untersetzen (für die bildhaft/beispielhaft denkenden Menschen wie mich).

    Ansonsten find ich die CRE-Podcasts extrem interessant. Endlich mal eine Oase der Bildung und Wissensvermittlung!

    MfG, Borzel

  29. Eine Folge, die sich auf Compilerbau beschränkt, wäre deutlich sinnvoller gewesen. Die Disziplin wurde hier ziemlich unsystematisch besprochen und hätte auch vom Moderator besser vorbereitet werden können, um das zu verhindern. Üblicher Aufbau und Arbeitsweise eines Compilers wurden nur dürftig behandelt, obwohl sie nach Art der Fragestellungen nicht vorausgesetzt werden konnten. Hätte man aus der Sendung eine spezialisierte Folge zu einigen Aspekten des Compilerbaus gemacht und für die Grundlagen eine eigene Folge angedacht, wäre diese Sendung sicherlich besser gelungen.

  30. Ich habe gerade mal ein Semester Funktionale Programmierung gehört und mir dennoch bei diversen Aussagen an den Kopf gefasst.
    Die inkompetente Java-Kritik (wie werden String Arrays sortiert?) fand ich traurig.
    Das Unwort der Episode war im übrigen „genau“.

  31. Also ich bin ein wenig enttäuscht von dem Beitrag. Ich sehe ja ein, daß ein Redner in einem recht straffen Interview ja doch in gewisser Weise unter Stress steht und doch den einen oder anderen Fehler macht, aber was ich hier gehört habe, erfreut mich nicht besonders aufgrund der vielen doch recht ungenauen Aussagen. Der Name des Podcasts verspricht jedenfalls bedeutend mehr, als er nachher hält.

    ZB ist das Lambdakalkül ist nur unzureichend erklärt worden.

    „Die Kalküle sind erstmal ein Modell“ ist sehr treffsicher formulert, führt aber am Ziel einer Erkläruns vorbei, da wir gegerell mit Modellen zu tun haben. „Kalküle sind Algebren und basieren auf Axiomen“ hätte ich lieber gehört, denn dann wäre die Sache mit der Beweisbarkeit später auch einfacher zu erklären gewesen.

    Es wird nicht darauf eingegangen, daß der eigentliche Vorteil und die daraus resultierende Flexibilität des Lambdakalküls darin besteht, daß Funktionen Firstclass Objects sind und wie Werte an andere Funktionen übergeben werden können, Thema Closures.

    Es bleibt im Zwischencode-Thema unerwähnt, daß in der Sprachenentwicklung auch andere Sprachen, wie C als Zwischencode genutzt wird (zb. von (Gwydion-)Dylan).

    Die Abneigung gegen Java mag persönliche Gründe haben, aber (im Beispiel der Sortfunktion) ist Hannes Mehnert so ziemlich auf dem Holzpfad, da er das Collections Framework nicht genau zu kennen scheint.

    Es erkennt ausserdem in seinen Ausführungen nicht, daß es einen inhärente Gemeinsamkeit zwischen Klassen und Funktionen, die Closures zufückliefern und Objekten und den Closures selbst gibt und dadurch die objektorientierte der funktionalen Welt näher rückt. Beide Paradigmen haben eine ganze Menge von Gemeinsamkeiten.

    Er erkennt nicht, daß auch Java in der Art funktional ist (nämlich über anonyme Klassen, die man als anonyme Funktionen verwenden kann, ähnlich wie die (Anonymen) Delegates in C#) und nennt scheme in einem Atemzug mit haskell und ml Beweisbar, weil funktional. Das ist totaler Blödsinn, bitte entschuldigt.

    ML und Haskell, wie auch Mercury sind „rein funktionale Programmiersprachen“ und damit „nicht Imperativ“ und damit „besser beweisbar“ – besser deswegen, weil Mathematik auch in dem Sinne „pure funktional“ ist (Konvertierberkeit von lambdakalkül zu formaler logik und zurück ist bereits bewiesen) und weil es in der Mathematik immer noch Beziehungen gibt, die man kennt, aber die sich (bislang) nicht beweisen lassen. Mit anderen Worten: nicht jedes in einer „nicht imperativen“ Programmiersprache geschriebenes Programm ist auch beweisbar.

    Scheme und Lisp sind funktional, aber nicht Pure. und mit etwas Umstand (siehe oben) kann man auch die funktionalen Fratures anderer Programmiersprachen nutzen: C#, python, perl, java. Bedeutend umständlicher wird es in c, denn da kann man keine Closurevariablen anlegen – wer in c funktional programmieren will, sollte einen eigenen Stack verwalten und dann geht auch das wieder oder er baut sich einen Code-Dom, der das kann.

    Ist natürlich klar, rein theoretisch kann ich in jeder turingvollstaendigen PL alles, wie in jeder anderen – die Frage ist natürlich die nach der Lesbarkeit und Eleganz.

    So, das war es für heute, ich hoffe dieser Audio Beitrag bleibt eine Ausnahme, denn als Stammhörer kann ich mich durchaus als verwöhnt bezeichnen von der Masse der Chaosradio-Sendungen.

    Macht weiter so und viel Erfolg bei den nächsten Sendungen.

    Frank.

  32. Nachdem die Aufgaben der lexikalischen Analyse (Scanner) und der syntaktischen Analyse (Parser) gleich zu Beginn verwechselt wurden, und auch das „Hallo“ von Tim nichts ausrichten konnte, habe ich abgebrochen. Schade … eigentlich. Compilerbau war einmal die Königsdisziplin in der Informatik. War. Vorbei.

  33. Wie Anton und andere anmerkten: Einer der schwächsten CRE, weil einfach so viel Unsinn behauptet wurde. Hannes hat auch ziemlich viel durcheinander geworfen und vieles offenbar nicht verstanden. Schade.

  34. Schön, daß dieses Thema endlich auch einmal dran kahm – nur ist leider sehr unschön, daß sich Hannes immer wieder in seine Ecke „verkrochen“ hat, ohne eine übersichtliche Erklärung abzugeben. Das sollte doch keine mündliche Klausurprüfung werden…

    Um genau zu sein: Hannes Ausführungen über Kompiler an sich passen wohl in eine Zehn-Minuten-Zusammenfasung. Schade. Es war zwar interessant, aber vielleicht hätte der Fokus auf Typisierung belassen bleiben sollen – bewaffnet mit ein paar griffigen Infos…
    (Es wäre doch nicht aufgefallen, wenn erst der zweite Versuch veröffentlicht worden wäre).

    Kopf hoch, Hannes! Es isthalt nicht Jeder ist der geborene Erklär-Bär.

Schreibe einen Kommentar zu frosch03 Antworten abbrechen

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre mehr darüber, wie deine Kommentardaten verarbeitet werden.