Ja. Dann oft in die letzten Runde.
Guten Morgen, meine Damen und Herren. Wir müssen heute
noch so ein bisschen aufräumen und ein paar lose Fäden aufnehmen
und sehen über das Semester geordnet zum Abschluss bringen.
Bevor wir damit loslegen, ein paar Ansagen. Ich hoffe,
Sie haben alle in Stine die Nachricht gesehen über unsere Probeklaus,
nicht Probeklause, die auch, aber über das Klausurtutorium.
Also ich habe für diejenigen, die die zweite Klausur mitschreiben wollen,
ein Tutorium angekündigt und zwar Am 23.02.10 bis 12.,
Zeiten gelten CET und voraussichtlich, wenn nicht,
ich habe den Raum R031 im Kellergeschoss vom Haus reserviert dafür, der sollte reichen.
Ja, es ist klar, Sure Tutorium richtet sich wirklich an diejenigen,
die aus irgendeinem Grunde erst die zweite Klausur schreiben können oder wo,
wenn es irgendwas schief gehen sollte, während der ersten die zweite nötig wird.
Ich hoffe, dass diese Klientel der Kleinen ist,
das ist im ersten Anlauf bei der ersten Klappen wird.
Unsere Erfahrung ist einfach, Auch wenn wir absolut,
also die zweite Klausur, fast identisch machen wir die erste,
sie ist nicht schwerer und nichts, aber trotzdem zeigt es sich immer,
dass da im Schnitzen eine halbe Note schlechter dabei rauskommt.
Und meine Vermutung ist einfach, dass wenn sie die Klausur jetzt schreiben,
stande P, so wie sie hier sitzen,
geübt haben, dann entscheidend bekommen und stürzen hinein,
dann haben sie alles noch frisch im Kopf und können das gut.
Die langen Ferien dazwischen, die führen dazu,
dass man Dinge, die vergisst oder wo man lange nachdenken muss,
die man sonst im Schlaf beantworten könnte.
Und um das ein bisschen zu kompensieren,
bieten wir dieses zweite das Klausurtutorium vor der zweiten Klausur an,
dass sie da nochmal eine Chance haben, Fragen zu stellen.
Ja, und dass wir nochmal die wichtigen Punkte sehen und
sehen, noch ein bisschen wieder fitter werden.
Also für die erste Klausur macht das Tutorium einfach keinen Sinn,
das würde sie nur Zeit kosten,
wo sie sich zu Hause selbst auch mal mit einem Skript hinsetzen könnten.
Wir schreiben die erste Klausur ja gleich am Dienstag, dazu auch nochmal organisatorisch ist.
Wir sind zu dem Zeitpunkt auf zwei Hörseele verteilt,
Hörsal A und B, im Hauptgebäude und wir wissen noch nicht genau,
wer Wer, welche Klausur in welchen der Hörseele schreibt.
Also wir werden, wenn wir die Liste alle haben,
die angemeldet sind und es stabil ist,
die Klausuren so verteilen, dass alle,
die alphabetisch bis ungefähr in der Mitte mit ihrem Nachnamen sind,
in den Hörsaal arg kommen und die zweite Hälfte in den Hörsaal B.
Also wenn ihr Nachname mit A beginnt und wenn ihr Nachname Z beginnt,
ist ziemlich sicher schon, in welchem Hörsaal sie ihre Klausur finden werden.
Der Graubereich liegt bei denen mit Nachnamen zwischen L und M
oder so oder bei Nachnamen Oder bei Namen,
wo das Prüfungsamt sich vertut und nicht klar die Zuordnung,
Vorname, Nachname erkennt, wenn sie ausländisch sind.
Also, wenn sie meinen, ihr Name ist für mittelmäßig
begabte Deutsche unbedingt eindeutig erkennbar, was Vor- und Nachname,
schauen Sie bitte in beiden Ohren nach Ihrer Klausur hier.
Oder wie Ihr Name ins Diene eingetragen ist. Dennoch sollte
sich richten. Okay, also die Klausur am Dienstag,
wir haben den Hörsaal von 10.30 Uhr bis 12.30 Uhr.
Wir selbst werden die Zeit von 10.30 Uhr bis
10.45 Uhr benötigen
Um da alles auszulegen und so weiter und das Team zu verteilen auf die beiden Hörsilen.
Also wir werden sie um 10.45 Uhr reinlassen. Ja,
und bereiten Sie es bitte so vor,
dass Sie sicher sind, dass Sie ein Lichtbildausweis,
am besten Perso oder Pass haben,
plus einen Ausweis, der Ihren Materipel-Nummer enthält.
Also wir brauchen einen Ausweis, der ein Bild hat und
einen, der Ihren Materipel-Nummer hat.
Und diese Ausweise legen Sie bitte direkt vor sich auf den Tisch,
dass wir sie während der Klausur anschauen können,
ohne sie stören zu müssen
Wir werden während der Klausur einmal rumgehen und alle abhaken,
die erschienen sind, dabei ihr Bild im Ausweis vergleichen mit dem,
der da sitzt und schreibt.
Und das sollte dann schon gut gehen, wenn Deutschen nicht ihre Müttersprache ist,
bringen sie gerne auch ein Lexikon mit für die deutsche Sprache.
Das dürfen sie auch lesen, sich auf den Tisch haben.
Ansonsten wollen wir auf dem Tisch wirklich nichts weiter sehen,
als vielleicht eine Trinkflasche, der wenn sie irgendwie noch was,
um sich fitter zu fühlen,
Traubenzucker oder so zwischen so eine kleine Stärkung brauchen.
Das ist okay, aber bitte keine Zettel. Außerdem Klausurburg,
den wir ihnen austeilen. Sie werden den Klausurbogen auf dem Tisch finden,
plus ein kleines Funktionslexikon, was wir dann für sie daneben legen,
was so die wichtigsten Recket-Funktionen enthält.
Bringen Sie mehr als einen Schreiber mit, der schreibt,
wir werden keinen Vorrat im Notschreiber haben.
Manchmal passiert es einfach, ich habe schon erlebt,
dass jemand während der Klausur drei Bleistifte abgebrochen hat in der Hektik.
Also ein bis kleiner Vorrat in Schreibmaterial wäre nicht schlecht.
Und ansonsten vielleicht ein Buntstift, mit dem sie Dinge bunt markieren können,
um sie hervorzuheben. Also wenn wir da unsere Randbemerkung eingeflochten haben,
verwenden sie Funktionen höherer Ordnung oder so,
unterstreichen sie sich in rot, damit sie wirklich,
wenn sie dabei sind, eine Endrekursion zu programmieren,
sich daran nein, ach so, ja,
wir sollten eine Funktion höhere Ordnung machen.
Okay, das ist Also der kleine Hinweis zu dem zur Klausur,
dann werden sie exakt zwei Stunden Zeit zum Schreiben haben.
Und ich möchte sie bitten, dass sie, wenn sie keinen Randplatz haben,
am Ende sitzen bleiben und die anderen nicht stören.
Ja, also es ist total lästig für diejenigen, die noch nachdenken müssen,
wenn neben ihnen schon alles aus den Reihen springt und Lärm macht.
Also nutzen Sie die Zeit einfach,
um alles nochmal gut, Korrektur zu lesen.
Ja, das haben wir. Klausurtermin haben wir auch.
Dann können wir damit weitermachen,
das Semester zusammenzuzufassen
Ja. Also was ich heute gern mit Ihnen machen möchte,
einfach ein paar zusammenfassende Folien zeigen,
wo ich nochmal die Akzente setze auf das,
was mir wichtig war, sodass Sie Idee bekommen,
was Sie jetzt eigentlich gelernt haben sollten.
Gut. Okay. Mal ganz ans Ende.
Mensch. Das war noch nicht ganz das,
wo ich hin wollte
Zusammenfassung da. Okay. Ja, was war mir wichtig in diesem Zusammenhang?
Also sie haben im ersten Semester und im zweiten ja vor allem imperativ programmiert.
Sie haben objektorientiert programmiert und die meisten von innen werden das
einfach in Yava gemacht haben. Was das Ziel und der Zweck,
dieses dritten Semesters ist, wo sie mal in anderen Programmiersprachen programmieren.
Das hört man schon eigentlich. Kommt der an? Das ist,
dass sie das Wesen der Funktionalen Abstraktionen kennenlernen oder das Wesen der relationalen Abstraktion.
Jedenfalls eine andere Art auf die Probleme zuzugehen und sie so zu modellieren,
dass sie sie für ein anderes Verarbeitungsmodell beschreiben.
Und wir hatten ganz zu Anfang des Semesters überhaupt erstmal den
Begriff Verarbeitungsmodell nochmal aufgefrischt. Grundidee von allem ist,
dass wir, wenn wir Programme schreiben, Programme entwerfen,
konzipieren, Programmiersprachen benutzen, dass wir die Maschine,
die das Programm ausführen soll,
als eine abstrakte Maschine sehen.
Und diese abstrakte Maschine versteht Sprachelemente
Versteht eine Sprache und kann bestimmte Grundoperationen ausführen. Und wenn wir ein Problem lösen sollen,
ist die erste Aufgabe zu identifizieren,
was für einen Kasten brauchen wir denn eigentlich,
der dieses für uns tun kann und lösen kann,
habe ich da lieber einen,
der Imperativ versteht und Folgen von Anweisungen, nur nimm das,
mach das, nimm das damit und mach es da,
Speicher ist da, hol es da raus.
Oder möchte ich einen haben, der funktionale Ausdrücke versteht,
dem ich sagen kann, zieh mal die Wurzel aus drei
oder aus etwas, was wir funktional beschreiben können.
Oder hier hast du deine Datenbank, gibt es einen schwarzen Raben.
Ja, wenn ja, welcher ist es? Und dieses Verarbeitungsmodell,
was die Kästen da stehen und für das wir Programme schreiben,
das ist so der Kern dessen, der unser Programmierstil bestimmt.
Also wenn wir ein Problem lösen sollen,
dann sollten wir versuchen, das zu beschreiben und die Operationen,
die getan werden sollen, das so zu beschreiben,
dass wir eine Sprache gefehlt haben, die Problemadäquat ist.
Also je besser die Programmiersprache, die wir verwenden,
zu unserem Problem passt
Je intuitiver wir das in der Sprache beschreiben können,
desto einfacher ist es. Teil dieses Semesters zielte daraufhin,
sie dafür fit zu machen,
dass wenn sie ein Missmatch haben zwischen dem Computer und einer Sprache,
die er versteht und dem, was sie sagen wollen.
Und dazwischen ist eine gehende Lehre, weil ihr Computer spricht
Java und sie wollen das Ganze in Prolock beschreiben.
Oder eben in Rected. Dann kommt der Moment,
wo sich zeigt, ob sie Programmiererinnen und Programmierer
sind oder ob sie Informatikerinnen und Informatiker
geworden sind
Informatiker, das Ziel und Zweck der wissenschaftlichen Informatikausbildung ist,
dass sie in der Lage sind, die Brücke zu dem,
was sie real vorfinden und dem, was sie brauchen,
zu schließen und da etwas dazwischen zu tun,
was es ihnen ermöglicht, in der Sprache,
die sie sprechen wollen, ihr Problem zu beschreiben.
Das haben wir in diesem Semester exzessiv gemacht.
Wir haben in die Sprache, die wir vorgefunden haben,
andere Sprachmodelle eingebaut, sodass wir in der Lage waren,
unser Recket-System als eine Sammlung von abstrakten Maschinen
zu sehen,
die viele Programmierstile unterstützen
Ja. Und ja, wo würde ich den Unterschied sehen zwischen Programmierern und Informatikern?
Die Programmierer sind die Klientel in den schlecht bezahlten Gehaltsgruppen,
die nicht viel mehr gelernt haben als eine oder zwei Programmiersprachen.
Und dies gewohnt sind, dass man diesen Auftragszettel geht,
auf denen es steht,
schreibe mir eine Funktion oder ein Stück Programm,
dass genau diese und jene Spezifikation erfüllt oder noch schlimmer
das Programm ist schon vorformuliert und es soll nur noch
kodiert werden
Also die Dinge, die eigentlich Maschinen viel besser können.
Was ich von Informatikern und Informatikerinnen erwarte,
wenn sie eine gute Ausbildung bekommen haben, ist,
dass sie Probleme analysieren können, dass sie sehen können,
ah ja, hier habe ich meine Kunden,
hier habe ich mein Problem.
Was ist es, was gebraucht wird? Was soll es können?
Und dann zu überlegen, wie schaffe ich das nötige Werkzeug dafür? Erkennen,
was typische Aufgaben der Probleme, Aspekte der Probleme sind,
Entwurfsmuster erkennen, Klassen von Problemen wiedererkennen,
die sie schön haben, die richtigen Werkzeuge erkennen.
Sie haben das zum großen Teil, zumindest hoffe ich,
dass im zweiten Semester gemacht, als sie objektorientiert,
programmiert haben und gelernt haben, die typischen Entwurfsmuster kennenzulernen,
Werkzeuge zu erkennen, Klassen von Werkzeugen und so weiter.
Das ist, soweit es bei uns im ersten zwei Semester gemacht wird,
zieht es vor allem, zielt es vor allem auf die Fälle,
wo sie Anwendungsprobleme lösen wollen.
Die funktionale Programmierung kommt zum großen Teil, aber auch aus dem Forschungsbereich,
wo wir vor der Aufgabe stehen, für Probleme,
die bisher ungelöst sind, passende Algorithmen zu finden.
Komplexität zu reduzieren, komplexe Probleme beherrschbar zu machen.
Und genau da liegen die Wurzeln der Beispiele, die ich
Ihnen gezeigt habe, aus dem Bereich der künstlichen Intelligenz.
Wohnen. Wir einfach vor so komplexen Aufgaben standen,
dass man zu Fuß in einer emperativen Sprache dafür,
das einfach nicht vernünftig formulieren kann.
Und die Algorithmen nicht finden kann. Und von daher
der Ansatz für bestimmte Teillösung, Werkzeuge zu schaffen,
die uns das Muster geben, wir dann parametrisieren können.
Allgemeine Bausteine wie ein allgemeines Back-Tracking. Wir geben die Beschreibung unseres Problems
hinein und müssen das Back-Tracking nicht jedes Mal neu erfinden.
Oder eben relationale Datenbanken und mit Fakten, mit Regeln und dazu ein Baustein,
der automatisch die Suche und die Unifikation macht.
Also das, was für den Menschen, der es programmieren soll, sehr schwierig ist.
In einem sehr komplexen Raum nach Lösungen zu suchen,
das wird eben sehr gut unterstützt zu den Programmierstielen,
die wir hier angesprochen haben. Also für schwierige Probleme,
die viel mit Kombinatorik und Suche und Explorieren zu tun haben,
das zu machen. Eine ganze große Welt daneben,
die wir hier nicht angesprochen haben, die sie aber in anderen Vorlesungen kennenlernen.
Das sind so Simulationsaufgaben, wo wir viel mit parallelen Prozessen arbeiten müssen und so.
Also das habe ich hier ein bisschen in den Hintergrund gestellt. Ja,
aber das ist also für mich das Wesentliche gewesen,
wo ich sie hinbringen wollte, dass sie erkennen,
dass nichts schlimmer ist als ein Diktat,
nehmen sie diese Programmiersprache und jetzt machen sie mal.
Als wenn sie Ein Transportunternehmen haben, aber aus Firmenpolitik
werden ihnen nur Mähdrescher als Fahrzeug zur Verfügung gestellt.
Und je nachdem, was die Transportaufgabe wäre,
hätten sie doch vielleicht mal lieber einen Laster oder ein schnelles
anderes Fahrzeug oder eins mit größeren Sicherheitseinrichtungen oder größerer Tragfähigkeit.
Wenn die Politik sagt, nehmen sie das und machen sie es damit.
Naja gut, mit Informatikstudium sollten sie in der
möglichst sein auf jede Programmiersprache, die man ihnen zumutet.
Da Ebenen drüber zu setzen,
sodass sie dann auf der Ebene diese selbst geschrieben haben,
mit einem anderen Programmierspiel denken und entwerfen können
Programmiersprachen, die nicht nur dazu, dass anschließend ein Rechner
das Programm ausführen kann und dass wir das Programm schreiben können,
die dienen auch dazu, dass wir damit Probleme beschreiben können.
Das haben wir auch gesehen, dass wir eine Programmiersprache nutzen,
um einfach zu kommunizieren mit anderen, die am selben Problem arbeiten.
Gucken wir mal jetzt genau auf die einzelnen Techniken,
die wir angesprochen haben. Zunächst mal, was macht die
funktionale Abstraktion aus? Wir haben in dem Zusammenhang gesehen,
dass wir zu einem Konzept von Funktionen kommen,
in dem wir Berechnungsschritte finden,
die immer wieder in gleicher Weise ausgeführt werden
Mit variierenden paar Rahmenmetern. Und die abstrahieren wir zu einer Funktion,
geben dem Kind einen Namen und haben dann eine Welt von Funktionen.
Die zweite Frage, die dann kam, ja,
wenn wir funktionale Ausdrücke geschrieben haben, was bedeutet das?
Was wird unsere Maschine, die da steht und unsere Funktionen
funktionalen Ausdrücke auswerten soll, was wird sie denn tun?
Das ist quer durch alle Programmiersprachen, die Frage der Symantik.
Was bedeutet es, was wir gesagt haben und
wie genau in präzise beschreiben wir sie?
In der Welt der lisinnlichen Sprachen wird es über Slamderkalkül beschrieben
Und die Reduktionsstrategien, die wir besprochen haben,
waren einmal Striktheit, dass wir sagen, egal was geschrieben wird,
es muss nur zu einem Wert führen, wenn alle Argumente definiert sind.
Eine Funktion, die undefinierte Argumente hat,
für die drängen wir gar nicht erst über einen Wert nach,
dass in strikten Sprachen wird erwartet, dass alle Argumente definiert sind.
Das ist die Listwelt. Dann haben wir gesprochen,
verzögerte Auswertung, vorgezogene Auswertung. Mit der verzögerten Wird immer
nur der Code so weit expandiert, wie es gebraucht wird,
um weiterzumachen und die Argumente erst am Ende ausgewertet,
wenn auf sie zugegriffen wird.
Bei der vorgezogenen, erst aller Argumente auswerten.
Und dann schaut man sich die Funktion an und sieht,
man die Argumente überhaupt braucht. Wichtig war in dem Zusammenhang,
dass, solange eins gewährleistet ist, Bezugstransparenz,
dass es vollkommen gleichgültig sein sollte,
bevorgezogene Ausleitung oder verzögerte Auswertung haben,
weil der Wert Reihenfolge
unabhängig ist
Bei Bezugstransparenz gewährt uns, dass wir gewährleistet, dass wir,
wenn wir es selbe mehrfach schreiben, es jedes Mal zum selben Wert führt.
Also können wir es auswerten, wann und wo wir wollen und auch Teilausdrücke,
die wir schon einmal ausgewertet haben, ersetzen und damit Brechenzeit sparen.
Bezugstransparenz, wenn die gewährleistet ist,
sind vorgezogene und verzögerte Auswertung gleichwertig für uns im gleichen Ergebnis.
Das einzige, wo sie sich unterscheiden können, ist die Rechenzeit.
Gut, das haben wir an vielen Beispielen gesehen. Wir haben uns im Zusammenhang damit,
dann auch noch angeschaut,
was die Bezugstransparenz dann verletzen könnte und haben gesehen,
klar, das ist, sobald wir imperativ werden,
warum wird man in funktionalen Programmiersprachen imperativ,
weil wir eine Berechnungsuniverselle Programmiersprache haben wollen und als General-Purpose-Programmiersprache sollte es möglich sein,
auch Probleme zu bearbeiten, die imperativ einfacher zu beschreiben sind.
Dinge, wo es auf einen Wechsel von Zuständen ankommt.
Also sind diese Sprachelemente da, ja,
aber wenn wir sie benutzen,
ist die Bezugstransparenz hin
So, dann haben wir als nächstes besprochen, Funktionen höherer Ordnung,
als die Möglichkeit, auch funktionale Programme zu strukturieren.
Ich bin es vielleicht aufgefallen, wir haben herzlich wenig Kontrollstrukturen in.
Rackett in der ganzen funktionalen Welt, ja,
das sind im Wesentlichen Schreiben wir Funktionen, wir müssen dafür sorgen,
dass sie in geordneter Reihenfolge ausgeführt werden.
Und diese Sammlung von Funktionen zu verwenden, mehrfach zu verwenden,
geht am besten über Funktionen höherer Ordnung, Funktionen, die andere als Parameter bekommen.
Und diese Funktionen höherer Ordnung sind für uns das,
was Sonst Kontrollstrukturen, Weilschleifen und so weiter ausmacht.
Ja, anderer Punkt,
der jetzt auf die Komplexität hinkam und auf das Meistern von schwierigen Problemen,
jetzt im Sinne von Algorithmen, die in schwierigen Problemräumen suchen müssen.
Das war die Rekursion. Wir haben rekursive Datenstrukturen definiert,
vorzugsweise Listen, Bäume. Wir haben über rekursive Prozesse gesprochen,
wie sie sie unterscheiden und zu verschiedenen Berechnungsaufwand führen.
Wir haben über Algorithmen gesprochen. Typische Algorithmen,
die rekursiv sind, wie Backtracking zum Beispiel
Und das Backtracking war für uns das erste Beispiel,
wo wir eine eigene Funktion höherer Ordnung geschrieben haben,
die Kontrollstruktur am Charakter hatte.
Ja, also Funktionen, General Backtracking, wie haben wir
sie parametrisiert? Mit allem, was den Problemraum beschreibt,
in dem wir suchen. Und die einzelnen Schritte,
wie wir in diesem Problemraum weiterkommen und zu Teillösungen kommen.
Das war einmal das Genderal Backtracking als Parameter, einen Ausgangszustand bekam.
Es bekam eine Funktion, die testet,
ob der Zustand, den wir gerade am Wickel haben,
ob der das Problem löst
Eine andere Funktion, die prüft, ob das überhaupt zulässig ist,
guckt sich den Zustand an und sagt, nee,
nee, du stehst jetzt mitten in der Hecke vom Labyrinth,
schön brav außen rumgehen.
Also der Zustand zulässig, oder nicht? Und
dann hatten wir noch eine Funktion von dem Zustand,
wo wir sind und sich überlegt, eine Liste aufstellt von allen möglichen Folgezuständen,
die wir mit einem einzigen Schritt erreichen können.
Ja, und dann wird zum Beispiel nach links gehen,
geradeaus gehen, nach rechts gehen. Und mit diesen,
diese Funktion höherer Ordnung, mit ihren drei Parametern,
die konnte dann loslegen und suchen automatisch für uns,
ohne dass wir selbst uns überlegen müssen,
was tun wir in jedem Schritt
Da haben wir also zum ersten Mal Kontrollabstraktion selbst programmiert.
Ja, dann so um die Weihnachtszeit drum haben wir dann angefangen,
in die anderen Programmierstile hineinzuschauen. Und als erstes mal geguckt,
wie sieht es denn aus, mit dem Objektorientierten? Ich meine,
wenn ich mir die ganzen Lehrbücher zur objektorientierten Programmierung anschaue,
die tun alle so, als wäre Objektorientiertheit etwas,
was inherent zum Imperativen Programmierstil gehört und woanders gar keinen Sinn macht.
Zumindestens in der funktionalen Programmierung, da können wir
genauso gut objektorientiert programmieren
In der emperativen Welt. Und der Vorteil,
den wir in den lisp-innlichen Programmiersprachen haben, wenn wir dort objektorientiert programmieren,
können wir sogar die Metaprogrammierung sehr gut objektorientiert mit generischen Funktionen verbinden.
Also der Weg, den wir kennengelernt haben, waren generische Funktionen,
anstelle von Operationen auf Objekten zu machen. Und generische Funktionen,
wann eben, sind eine Klasse von Funktionen,
die für uns die abstrakten Mit Methoden beschreibt, also es ist abstrakt das,
was wir sonst als abstrakte Methode in Java-Klassen hätten.
Und wir implementieren sie mit Defined Message, indem wir diese generischen Funktionen implementieren.
Und wir können damit klassenspezifisch Operationen definieren und sie erben.
Das Erben ist dasjenige,
was die objektorientierte Programmierung besonders mächtig macht im Funktionalen Programmierstil,
weil wir auch gesehen haben,
dass wir eine ausgefeilte Kontrolle über den Vererbungsmechanismus haben
Es ist nicht so, dass wirklich nur der Normalfall eintritt,
sondern C-Logs-Programmierer sollte man schon Erbschaftsanwälte dabei haben, die im Streitfall das auch regeln.
Wir haben Kontrolle über das Vererben von einer Klasse zu ändern und haben damit ein mächtiges Werkzeug,
um Software durch Vererbung zu erweitern und zu spezialisieren.
Wir können bestimmen, wie die Ererbten Operationen,
wenn viele möglich wären, die wir erben könnten,
wie das geregelt wird, indem wir Methodenkombinationen schreiben und sagen,
na gut,
Mensch,
wenn ich,
warum soll ich
so bescheiden sein
Ich erbe jetzt diese Methode Hände, ja. Warum muss
ich mich entscheiden, dass ich nur eine davon kriege?
Gib mir doch alle, ja. Oder gib mir das
Beste oder das Schnellste, das teuerste oder das Sedelste.
Wir können für jeden Zweck beschreiben, was aus der Menge der
Menglichen Dinge, die wir erben, geerbt werden soll.
Und wenn es darum geht, die Slots,
also die Attribute von Objekten zu erben, auch da,
wenn wir von vielen Klassen erben, können wir,
wir haben wir Kontrolle darüber,
in welcher Reihenfolge das geschieht
Es ist klar geregelt, indem ein Klassenpräsidenzgrad erstellt wird,
aber auch diesen Algorithmus, den Klassenpräzedenzgraf zu erzeugen,
können wir selbst schreiben und beeinflussen.
Also von der Objektorientiertheit passt in den funktionalen Programmierstil sehr, sehr viel hinein.
Es gibt nur einen Punkt, wo es im funktionalen Programmierstil wehtut.
Das ist ziemlich klar und offensichtlich. In vielen,
vielen Beispielen, wo ob jetzt orientiert programmiert wird,
liegt die Bedeutung darin, dass durch das Programm,
die Zustände von Objekten geändert werden.
Also diese Zustandsänderung, die dazu führt,
in einer simulierten Welt, dass sie irgendetwas ändertrin tut.
Das passt nicht gut in den funktionalen Programmierstil hinein.
Was wunderbar passt, ist die ganze Spezialisierung von Software,
erweitern von Paketen durch Vererbung, auf der Methodenseite,
auf der Attributseite, auf der Klassenhierarchie.
In dem Moment, wo wir die Objekte,
aber dynamisch verändern wollen, da können wir das natürlich.
Wir haben ja das Imperative Schlupfloch,
aber das ist die Stelle,
an der wir aufpassen müssen,
weil wir dann eben
unsere Bezugstransparenz verlieren
Trotzdem. In dem Simulationssystem, das ich Ihnen gezeigt habe
, habe ich genau das getan.
Gelegentlich wurden wir imperativ mit ZF Bang und das war's dann.
Aber man muss es wohl überlegt tun. Ja,
dann haben wir uns nur angeschaut, wo man sonst gern imperativ wird,
zum Beispiel, wenn es um Effizienzverbesserung geht.
Das klingt jetzt so, als wäre relationales und funktionales Programmieren ineffizient.
Und wenn wir schneller wollen, müssen wir doch imperativ sein.
So ist es nicht. Es gibt eine, manche Stellen,
wo einen der Zwang, Bezugstransparenz zu wahren,
einfach zu unwirtschaftlichen Dingen zwingt.
Ja, und dann wird man imperativ. Nimmen Sie an,
Sie wollen zwei riesige Listen verbinden. Jeder in zehn Millionen
Elemente, ja. Und so ganz ans Ende dieser Liste
wollen wir ganz hinten noch zwei Elemente reinhängen.
So. Die Bezugstransparente Lösung, die führt dazu,
dass ihre erste zehn Millionen Elemente lange Liste kopiert wird und hinten die zwei reingehängt.
Wenn Sie sich hundertprozentig sicher sind oder sagen wir sogar 110 Prozent sicher,
dass Sie diese Originalliste gar nicht mehr brauchen, Ja Gott,
dann nimmt man Replace-Kutter und hängt hinten seine zwei Elemente dran und hat es in kürzester Zeit getan,
statt alles zu kopieren.
Und ich muss mit Plunzki beim Anders einstellen. Oder mal
gleich zu den Folien kommen, da sind wir ja auch gleich, okay.
Okay, also das haben wir gesehen am Beispiel Memoisieren von Funktionen und Stromorientierte
Programmierung in den Bereichen, haben wir auch mal einfach so imperativ programmiert.
Relationale Programmierung werde ich gleich nochmal genauer darauf eingehen,
aber gehen wir jetzt erstmal
In Einzelteile. Indem wir uns einfach eins für das,
die drei Programmierstile, die wir kennengelernt haben, Facetten nebeneinander stellen.
Skim, Beckett, da haben wir in der ganzen Lizwelt,
haben wir funktional programmiert, dass der klassische funktionale Programmierstil,
wenn sie gefragt werden, was ist die Bedeutung eines funktionalen Ausdrucks?
Klassische Antwort ist der Wert, zu dem er reduziert wird.
Ja, und es hängt vom Reduktionsmodell ab, welcher Wert er rauskommt.
Der Programmierstil im Prolog ist relational, prolog in Reckett haben wir Relation,
ja. Haben wir Fakten in der Datenbank eingetragen,
haben Regeln in eine Datenbank eingetragen und mit Unifikationen und Suche dort nach Lösungen gesucht.
Aber das Modell dahinter für diesen relationalen Programmierstil ist eben die Welt der Relation und der Logik.
In Javas, imperativ und objektorientiert, ja, kennen Sie.
Die Verarbeitungsmodelle, die dahinter stecken im Programmierstil,
in Racket und Stream, Anwendung von Funktionen auf Werte.
Ja, das ist die Essenz des Ganzen. Wir nehmen einen Wert,
applizieren eine Funktion und deshalb heißt es auch applikativer Programmierstil.
Ein Pro-Look Der ist Verarbeitungsmodell. Wir haben dort unsere Kiste sitzen,
die hat ihre relationale Datenbank mit den Zusicherungen,
mit den Regeln da drin und kann Schluss folgern und wir stellen Anfragen.
Statt selbst zu suchen und zu sagen, prüfe mal erst das,
prüfe das, prüfe das, Fragen war, ist übermorgen Tauwetter.
Und wir kriegen die Antwort ja oder nein,
je nachdem, ob eine Belegung von Werten gefunden wird,
die die Antwort,
morgen ist Tauwetter warm macht oder ob da überhaupt nichts
drüber gefunden wird,
dann kriegen wir auch die Antwort nein
In Java ist das Verarbeitungsmodell. Wir schreiben Folgen von Anweisungen
und es ändert sich der Zustand der Berechnung.
Und der Sinn und Zweck des Programms ist es,
dass ich bin Indern, in unseren Variablen und Objekten der Zustand ändert.
Und diese Zustandsänderungen erfahren wir als Resultat. Was das Programm bedeutet,
ist erstens wichtig, wenn wir uns drüber Gedanken machen,
ist das, was wir geschrieben haben.
Hat es irgendwas mit unserem Problem zu tun und erfüllt es
den Zweck
Es erinnert mich dran, ich habe als Erst- und Zweit-Semester,
habe ich in den Kursen vom regionalen Rechenzentrum immer die Programmierübungen betreut. Und diejenigen,
die mit Programmieren angefangen haben und aus fachen Fächern kamen und
wo sie vorher nie im Leben programmiert haben, bei denen,
weil die Anfangsstrategie, wenn die Aufgabe war,
schreiben sie ein Programm, das ein Erre von Zeilen sortiert,
dass sie das Skript der Zettel genommen haben und irgendwas hingeschrieben haben.
Und kamen dann an, haben gesagt, mein Programm sortiert
gar keine Zahlen, da kommt was ganz anderes raus.
Und ich dann gefragt habe, ja,
weshalb haben sie denn
die Hoffnung
Dass dieses Programm Zahlen sortiert. Ja, weil der steht im Skript auf Seite
2. Es war überhaupt, es musste erst mal das Problembewusstsein erweckt werden.
Was muss ich dem Rechner mitteilen, damit er etwas über
mein Problem erfährt und dann anfängt, es zu lösen.
Und wenn man die Kurve kriegt, dass man weiß,
es gibt Probleme und man kann sie in der Programmiersprache beschreiben und
die treffen Ausdrücke gelernt hat, dann verwendet man die.
Aber bis dahin ist ein harter Weg. Gut,
und die Bedeutung eines Programms, die müssen wir eben
formell beweisen können, indem wir sagen können, ja,
was habe ich da geschrieben, was bedeutet es?
Ist festgelegt, in der denotationellen Semantik,
da steht Die beschreibt, was die Bedeutung eines Ausdrucks ist.
Und da haben wir eben in Breckett lispsgebendes Landerkalkül.
In Pola kann man Logik und Relation und die Anfragen.
Und in Java haben wir einfach Folgen von Anweisungen und Vor- und Nachbedingungen.
Und für die Welt der Imperativen Programmierung ist es immer
noch nicht sehr benutzerfreundlich, was die formale Semantik betrifft.
Haben Sie eigentlich im ersten Semester geübt,
die Korrektheit von Schleifen
zu beweisen
Nie gemacht. Überhaupt je in den ersten zwei Semestern bewiesen,
ob eines der Programme korrekt ist. Auch nicht. Ja
, kann ich verstehen. Als ich Informatik gelernt habe,
gehörte es zum guten Ton und es war total üblich und
stets und ständig wurden wir damit geplagt.
Wenn man seine Schleifen geschrieben hat, suche eine Schleifeninnenvariante für dieses Gebilde.
Schreibt die Vorbedingungen auf, schreibt die Nachbedingungen auf Beweise,
dass das Programm korrekt ist.
Und das zu finden und zu extrahieren,
der scheitert meistens schon daran,
dass es für die Programmiersprache selbst
keine Beschreibung gibt
Die sagt, was die vor- und bin nach Bedingungen der
Sprache, der einzelnen Sprachelemente sind. Die Programmiersprache Pascal,
in der ich so als sechs Semester habe programmieren dürfen,
da war tatsächlich bei der Definition der Sprache zum ersten Mal das Experiment unternommen worden,
dass es eine formale Semantik für eine imperative Programmiersprache gab.
Und Peter Amann, der dies geschrieben, den Compiler dafür geschrieben hat,
hat auch wirklich für jedes Sprachelement der Sprache Pascal für jedes Schleifenelement hingeschrieben.
Vorher gilt, das hinterher gilt das und dieses
Der Kurt ändert den Zustand der Berechnung in dieser Weise.
Er hat für den gesamten Compiler bewiesen, dass er korrekt ist.
Nur raten Sie mal, ob der Compiler Fehler hatte.
Er hatte natürlich welche, ne? Einfach, weil das Beweisen
der Korrektheit so schwierig ist. Macht man beim Versuch,
mit Vor- und Nachbedingungen zu beweisen, dass es korrekt ist,
exakt dieselben Denkfehler, die man gemacht hat,
als man den Code hingeschrieben hat.
Also kurz und gut in der ganzen imperativen Welt ist die
notationelle Semantik meistens vor allem dadurch dass man einfach treffende Variablennamen
nimmt und dass man ein User-Guide hat und ein Referenzhandbuch,
das einigermaßen in natürlicher Sprache versucht zu beschreiben, was das Ganze tut.
Als ich dann selbst Übungshelferin war, in den Allgäu-Programmierkursen,
hatte unser damaliger Informatikprofessor die Aufgabe gestellt,
an die Erstsemester, schreiben Sie ein Programm,
das eine gegebene Liste von Zahlen aufsteigend sortiert.
Also dass wir wirklich keine große Herausforderung.
Die Herausforderung war und beweisen Sie,
dass dieses Programm korrekt sortiert
Ja. Die Musterlösung, die verteilt wurde, bewiesen,
das hat ja einen Beweis, der zeigte,
dass dieses Programm korrekt war.
Wenn ich sie jetzt frag, weil die Musterlösung richtig,
sie ahnen das schon, die war auch falsch.
Was tat dieses Programm? Also wenn man das aufruft mit Eris,
in denen keine doppelten Elemente vorkommen, was prima.
Hat wunderbar funktioniert. Woran weder beim Programmieren dieser Musterlösung
gedacht wurde und dann auch beim Beweis,
ist die Zusatzforderung mit zu beweisen,
dass hinterher noch alle Zahlen da sind
Hatte keiner dran gedacht beim Sortierprogramm,
dass man auch diese, ist diese Forderung wichtig ist,
dass dieses Sortierprogramm nicht Zahlen wegschmeißt.
Also dieses Sortieren durch Einfügen, hat einfach alle Zahlen,
die doppelt vor, die schon mal vorkamen,
weggelassen und das sortierte Eriva hinter sortiert, aber ziemlich kurz.
Und es war im Sinne des Beweises korrekt.
Das ist die ganze Krux bei den Korrektheitsbeweisen für Programmen.
Das, was wir nicht fordern, wird nicht gegeben sein.
Das ist so der sehr teuflische Pakt. Und das zweite ist,
woran wir überhaupt nicht gedacht haben,
das kann eben auch schiefgehen
Man kann ja auch die Vor-nach-Bedingungen falsch gelesen haben. Okay,
also das ist die Dinotationelle Semantik,
die ist relativ einfach in den Sprachen,
die einfachen mathematisch, wo die Sprachelemente mathematischer Formalismus sind.
In Recletless definieren von Funktionen, das haben seit tausend Jahren
die Mathematiker gemacht, ja.
Und da haben wir einen wunderbaren Formalismus. Mit Logik und
Relation, da ist das Werkzeug auch schon da.
Da brauchen wir uns gar nicht darum zu kümmern.
Wir haben einfach die Sprache aus der Mathematik gebobbt und aus
der Logik und haben damit eine Programmiersprache.
Gut, der andere Kasus knackt so
Mit denen wir gesprochen haben. Vielleicht im Gefecht,
einfach das Gefecht ist ein bisschen untergegangen, aber es ist die operationale Semantik.
Das trifft einen im Frohlock noch ein bisschen härter als in Reckett.
Wir haben eine universelle Programmiersprache, mit der wir Dinge sagen können,
die man gar nicht berechnen kann. Und damit ist schon mal klar,
selbst wenn wir etwas sind, taktisch richtige Sinn geschrieben haben,
so wie die Menge aller Mengen, die sie nicht selbst entschalten.
Wir können ziemlich lange darauf warten, bis uns der Computer
die Antwort darauf gibt und das berechnet hat.
Weil das, da können wir beweisen, dass es nicht
berechenbar ist. Die Mächtigkeit einer universell berechenbaren Programmiersprache lässt es
aber zu
Dass wir Dinge schreiben, die nicht lösbar sind.
Und der Punkt, wo das für uns ein bisschen auseinanderfällt,
dir operationale Semantik und die Dinatationelle ist eben,
dass die Sprache für uns versucht, den Wert zu errechnen.
Und diese Sprache, wenn sie implementiert ist,
die hat einen Baustein, der legt los,
das ist die berechenbare Funktion, genannt Semantik,
die jede Programmiersprache hat,
die rechnet los und versucht,
diesen Ausdruck auszuwerten
Und wenn der nicht auswertbar ist,
dann kriegen wir Fehlermeldungen mehr oder weniger freundlich.
Oder eben eine Endlosschleife oder was auch immer. In Racket
Liz Skim, da haben wir Reduktionsstrategien, vorgezogene Auswertung.
Und diese Mantikfunktion, die dieses tut, die halt kennen
wir schon. Die hat schlichtweg den Namen Eval.
Die nimmt unseren funktionalen Ausdruck, evaluiert ihn.
In Pro-Log haben wir diese beiden Unifikationen und Suche,
die loslegen und operational versuchen,
die Anfrage zu erfüllen.
In Java
Da haben wir auch eine Semantik und das ist die,
ja, The Virtual Machine.
Die nimmt sich unser Programm vor und führt es aus,
ja. Und per Definition ist Java maschinenunabhängig.
Die Java Virtual Machine sollte mit Glück auf jedem Computer,
in jedem Betriebssystem dieselben Ergebnisse liefen, tut sie aber nicht ganz, ne.
Aber trotzdem, es ist das hehre Ziel und die Semantik
ist eben die Virtual Machine. Also wenn sie wissen wollen,
was ein Java-Ausdruck bedeutet, dann rückassemblieren sie die Java Virtual Machine,
Machine und sie haben diese Mantik formal definiert
Ja, gut, das wichtigste Wort, Bezug,
Bezugstransparenz in Recket Yara, Lisp, Quatsch,
Recket Lisp, haben wir Skim uns geben,
da haben wir die Bezugstransparenz, aber eben nur so lang,
wie wir keine Modifikatoren benutzt haben.
Im Urlaub ist sie da. Warum? Wir haben keine Modifikatoren,
ja. Da sind wir schon mal auf der sicheren Seite und in Yava. Ja,
weil wir total verfehlt, wenn es Bezugstransparent wäre, ja,
dann macht es einfach keinen Sinn, das zu fordern,
weil die ganze Wirkung eines imperativen Programms darin besteht,
dass wir den Zustand ändern,
Per Definition ist das, was wir haben wollen und damit
ist es in Bezugstransparenz nicht da. Richtungsunabhängigkeit. Ja,
was heißt das,
dass wir einen gegebenen Ausdruck vorwärts wie rückwärts auswerten können und
den haben wir leider nicht in der funktionalen Welt funktionale Ausdrücke,
da haben wir eine Ein-Mann-Straße bei der Auswertung.
Die Werte müssen definiert sein, dann werden sie ausgewertet und
wir kriegen ein Wertergebnis. Wir können nicht umgekehrt fragen,
damit man Resultat von Xox 4 gleich 3 ist,
welchen Wert muss X haben.
Das können wir
Im Pro-Log machen, wenn wir das in einer Weise formulieren,
die die Richtungsunabhängigkeit bewahrt. Meistens, solange wir nicht die
funktionale Auswerteumgebung im Pro-Log benutzen, prima, gar kein Problem.
Dann haben wir die Richtungsunabhängigkeit und das hohe Ziel
erreicht und können dieselbe Anfrage in verschiedenen Instanzierierungsvarianten stellen.
Wir können zuerst die erste Variable belegen,
die zweite Freilassen, umgekehrt die zweite Belegung,
die erste Freilassen und uns nach allen möglichen Variationen suchen und fragen,
dasselbe Programm Dieselbe Anfrage kann zu vielen unterschiedlichen Programmen führen.
Java, nein, nix da. Wir haben Schlupffläche,
eingebettete Programmierstile in der funktionalen Welt mit Skim und so weiter.
Ja, da ist vorgegeben, per Sprachdefinition das Imperative Schlupfloch.
Und wir können zum Sprach Standard aller funktionalen Programmiersprachen der Liz-Familie
gehört, ist, dass wir Zustände ändern können.
Das ist anders in den funktionalen Programmiersprachen,
Sprengen getypt sind und in diese Miranda-Häskel-Welt gehören, ja,
da ist von vornherein das Imperative abgeschaltet, geht nicht.
Pronoc, da haben wir das Funktionale, Schlupfloch, mit allen Konsequenzen.
In Java habe ich unfairerweise hier einen Strich gemacht.
Was hätte man da hinschreiben können? Ja. Genau,
es gibt ja aber Erweiterungen, die funktional zulassen. Und es gibt auch Möglichkeiten,
Maschinencode und so einzubinden, ja, dass wir,
ich habe den einfach auch unter Imperativ subsumiert und Außen vor gelassen,
aber es ist möglich, dass man natürlich Spracherweiterungen einbindet.
Typprüfungen. Über Datentypen haben wir kaum gesprochen. Es ist einfach so,
in der Listenwelt, die wir kennengelernt haben,
alle Werte, die wir haben, haben einen Typ,
der kann auch ein Mann frei ermittelt werden.
Aber wir müssen eh wieder die Objekte verwenden. Nicht vorher
dem System sagen, was für ein Typ das sein soll.
Wir haben praktisch an keiner Stelle außer ein bisschen mal
im Zählers Datentypen deklariert
Und trotzdem funktioniert es, weil wir einfach ein latentes Typsystem haben,
die Werte haben einen Typ und es wird damit gerechnet.
Und Operationen entscheiden sich anhand des Typs,
welches genommen wird und wenn es geht, dann geht's.
Und wenn es wir einen Typkonflikt haben, knallt es eben.
Genauso in ProLog, in Japan haben wir ein manifestes Typsystem,
bevor wir überhaupt irgendwas tun können,
im Programm kompilieren können, müssen wir die Typen festlegen.
Es hat natürlich für die Effizienz einen entscheidenden Vorteil.
Wir können besser optimieren, wenn es zur Übersetzungszeit
die Datentypen feststehen
Können wir effizienteren Kurten machen. Und das andere ist,
die Dokumentation, es ist klar,
für jeden das Programm erweitern willst du zu jedem Zeitpunkt,
welchen Datentyp die Objekte haben, die wir da beschrieben haben.
Und viele Fehler werden zur Übersetzungszeit erkannt und nicht erst beim
ersten Versuch, das Programm laufen zu lassen.
Das ist aber auch genau der Nachteil,
bevor wir ein Programm überhaupt jemals ausprobieren können,
müssen wir in unserem Compiler davon zu überzeugen, dass das übersetzt.
Das kann eine ziemlich lange Durststrecke sein, bis es uns gelingt,
das Programm zum ersten Mal zu übersetzen.
Aber meistens ist es dann so,
in diesen Sprachen mit einem manifesten Typsystem,
dass man ziemlich viele Fehler ausgebaut hat
Gut. Umgekehrt vermeidet man die Fehler erst einzubauen,
wenn man in einen Shopritter interaktiv kleine Teile immer gleich wieder ausprobieren kann
und erfährt ziemlich früh, dass es dynamisch keinen Sinn macht.
Die Prüfung haben wir also in Recket und so weiter zur Laufzeit,
in Prolock zur Laufzeit, in Java zur Übersetzungszeit.
Vorteil, kurze Programme, die Symbolverarbeitung. Das ist das,
was uns durch das dynamische, latente Typsystem möglich wird.
Wir schreiben erstmal Symbole hin, können denen Werte geben oder auch nicht,
wir können die Symbole und die Variablen selbst manipulieren und nicht nur ihre Werte manipulieren.
Und das machte die Meta-Programmierung sehr einfach und die Kurterzeugung der Laufzeit.
Gut, ein Java, das brauche ich nicht zu wiederholen,
das wissen Sie für einen soliden Softwareentwurf,
haben Sie auf diese Weise wohl definierte Schnittstellen, frühzeitige Fehlererkennung.
Die Programmierumgebung, wir haben die ganze Zeit eigentlich nur mit
dem Interpreter gearbeitet und den Compiler ziemlich ignoriert, um das explorative Programmieren kennenzulernen,
einfach Ideen hinschreiben, ausprobieren und los geht's.
Was ich Ihnen gerne noch vermittelt hätte,
Aber dazu war einfach nicht die Zeit gehabt.
Das ist, dass man exploratives Programmieren wohl dokumentiert machen kann,
in einer Umgebung, wo während man das macht,
auch gleich die Dokumentation geschrieben wird.
Rackett hat dafür ein gebettetes Skribbelsystem. Und im Skribbel schreiben sie
einfach das Handbuch zu dem, was sie machen wollen.
Und den Code, den sie ins Handbuch schreiben,
aus dem wird ihr Programm zusammengesucht.
Man schreibt zuerst die Dokumentation und die Teile,
die gebraucht werden, erprobt sie im Törpretter,
während man diese Doku schreibt und die Teile zusammensetzt,
ergeben hinterher
ihr Programm
Also in Skripbelt haben wir diese wunderbare Welt,
dass während des Programmierens gleich die Dokumentation entsteht.
Und wenn sie die Dokumentation abgeben, geben sie auch ihr
fertiges Programm ab, es ist eingebettet da drin.
Das Programm verteilte irgendwo in ihrer Doku steht, ist eigentlich
nicht das Problem. Das kann das Recket-System schon auseinanderhalten.
Aber man liest das Programm eigentlich nur mit der Dokumentation zusammen.
Und das ist wahnsinnig. Wir können das im Programmierpraktikum ausprobieren,
da haben wir ein bisschen mehr Zeit, sowas zu machen.
Aber hier in der Vorlesung hätte ich auch das Grippeln noch
ausführlich erklären müssen,
obwohl es
wirklich toll ist
Pro Log ist ähnlich. Ich weiß nicht,
ob es da inzwischen etwas grippelähnliches gibt. Praktisch meinst du
, nichts erzählt, ne? Ja, da haben wir
den Compiler. Ja. Kommen wir nochmal zur Frage zurück,
wann wählen wir denn jetzt welchen Programmierstil, ne?
Also wir haben vor allem zwei unterschiedliche Verarbeitungsmodelle besprochen, nämlich einmal das Relationale und das Funktionale. Es ist,
wenn wir uns entscheiden müssen, eben für Sie, Die wichtigste Aufgabe,
dass sie, wenn man ihnen jetzt sagt, okay,
hier ist ihre Aufgabe und programmieren Sie es bitte in einer funktionalen Programmiersprache,
beispielsweise in Recket, dass sie dann nicht hingehen und sagen,
okay, ich soll Wasser türen, ich weiß,
wie man das macht, ich nehme eine Vorschleife und nimme meinen Eri,
ja, dann haben sie ein wunderbares Imperatives Programm,
aber arbeiten vorbei an den Werkzeugen,
die sie bekommen haben.
Nehmen Sie die treffenden Werkzeuge, die in dieser Sprache sind. Und das Wichtigste ist,
dass man für jede Programmiersprache die User Guides ordentlich liest,
weil da Fallstudien drin stehen, wie welche Probleme gelöst werden,
wie diese Sprache benutzt werden soll. Also wenn ich,
dass sie, wenn sie eine Länge messen sollen,
nicht das Thermometer nehmen und die Fassade des Hauses hochklettern und
das Thermometer in 20 Zentimeter Schritten an der Fassade anlegen.
Ja, es wäre einfacher gewesen, man nimmt ein Massband oder sowas.
Und das ist eben genau die Aufgabe zu erkennen,
was die Stärken der Programmiersprache sind. Welche Aufgaben,
mit welchem Idiom gelöst werden sollten und ihr Problem in diesen Idioten zu formulieren. Und wenn Sie dann feststellen,
aufverflixt, also alles, was sich machen soll,
so schön direkt ist, aber das ist etwas,
wo ich im Wesentlichen Zustände von Objekten ändern soll, ja gut,
und kein Problem, dann lösen Sie es in einer imperativen Programmiersprache,
ja, wählen Sie das Treffendste.
Aber wenn ich ein Problem habe, wo ich sehe,
ich muss im Wesentlichen eine Datenbasis von Fakten aufsetzen und Beziehungen definieren,
wenn ich zu voll bin, wieder neuere Prolog zu installieren,
dann nehme ich eben direkten Po-Log in Recket und fertig und bitte,
dass der eine in meine Sprache, ja.
Also Peter Norweg hat es in seinem schönen Buch am Ende so formuliert,
für einen guten Programmierspiel, wie Specific, ja.
Also versuchen sie, wenn sie einen relativ komplexes Problem haben,
dann nicht zunächst mal ein allgemeines Problemlösesystem zu implementieren,
sondern versuchen sie, die Kerne des Problems zu isolieren und zu sehen,
ob es dann nicht was Fertiges für gibt und es gut gelöst werden kann.
Abstraktionen, ja
, warum
Fraktionen retten uns davor, dass man ständig das Rad neu erfindet.
Also wenn sie sich dabei ertappen, dass sie in ihrem Programm
drei- oder viermal immer wieder nach denselben Sachen suchen,
dann schreibt abstrahieren sie den Kern als eine eigene Funktion.
Besten Funktionen, höhere Ordnung, diese vernünftig parametrisieren können.
Sie haben einen für alle Mal das Werkzeug.
Wir haben das gesehen am Beispiel von Elisak,
da haben wir einmal das Pattern-Mädchen geschrieben und als wir gesehen haben,
wir brauchen es fürs Judenprogramm nochmal,
da haben wir dieses Beispiel den Pattern-Matcher genommen und haben ihn als Funktion höherer Ordnung extrahiert,
sodass wir ihn einfach im anderen Programm benutzen konnten.
Genauso mit der Dialogschleife einmal ein Werkzeug,
so ein Dialogtool, das ein Kontrollrahmen aufruft und fertig.
Und damit kann man das neue Problem dann lösen,
indem man gezielt ein paar Daten ändert, aber im Wesentlichen dieselben Kontrollschleifen benutzt.
Die vorgesehenen Werkzeuge benutzen. Nicht obskur sein. Oh ja. Vielleicht ist es Ihnen aufgefallen,
aber die Funktionen höherer Ordnung, die sind so Aussage und formulierungskräftig,
dass wir Dasselbe auf vielerlei Weise sagen können.
Wenn wir irgendwas, die Länge einer Liste haben,
man kann die einfachsten Sachen mit Funktionen, höherer Ordnung so verklausulieren,
dass selbst ein Informatiker mit Master zwei Stunden braucht,
um zu verstehen, was wir da gemacht haben.
Es ist, ich hatte in meinem allerersten Skript einen funktionalen Programmieren,
nur Schande über mich, auch solche Beispiele drin.
Also einfach, um zu zeigen,
es sind Funktionen höherer Ordnung machen, könnte aber zu dem Zeitpunkt,
wo ich zu der Vorlesung erklären sollte,
wusste ich auch nicht mehr,
was ich
da geschrieben habe
Jetzt zum Beispiel ein simples Mapping, ja? Man kann,
wenn man eine Funktion über eine Liste mit Map schickt,
kann man das schlicht und einfach und jeder versteht so machen,
dass man sagt, nimm die Funktionen,
die erhöht um eins und schicke sie mit Meth über die Liste und wir haben eine Liste,
jeder wert im Eins erhöht ist.
Sie können aber auch genauso hingehen und sagen, ja,
nimm das Map, nimm das Curry,
map ein Curry von dieser Funktion über die Liste
und dann ende ich bei einer Liste von Funktionen,
die ihren Wert im Eins erhöhen im Zweierhöhen und Dreierhöhen
um vier erhöhen
Dann lass dir was einfallen, wie die aus dieser Liste
von Funktionen die Zahlen wieder rauskriegst. Mit einem anderen Map
. Und kann man machen. Es sorgt für Heiterkeitserfolge,
wenn man die verstanden hat, wie das geht.
Aber man kann sich nicht länger als zwei Tage merken,
wie diese Funktion funktionieren. Und deshalb immer versuchen sie,
die einfachste Lösung zu finden. Also wenn sie sich dabei ertippt,
tappen, dass sie einen geschachtelten Ausdruck schreiben müssen,
wo sie zehn Funktionen höhere Ordnung ineinander verschachtelt haben,
dann sind sie entweder ein Genie,
geh mal davon aus.
Oder aber sie haben
eine simple Lösung übersehen
Okay. Und möglichst alles konsistent verwenden. Ja,
wenn sie dann nicht für dieselbe Art von Sachen,
dasselbe immer wieder in unterschiedlicher Art machen.
Das sprengt die Leser an. Und wenn sie etwas aus
bestimmten Gründen tatsächlich ungewöhnlich tun müssen. Ja gut,
dann schreiben Sie bitte einen Kommentar ran. Weiß nicht,
so Beispiele, wo ich als Programmieranfängerin immer herum grübeln müssen und
echt nicht so recht dahinter kam und wo ich mir gewünscht hätte,
dass die Leute mir mit Kommentaren arbeiten.
Ich musste meiner Studien arbeiten Compiler verwenden und musste einen Runtime-Support
ändern von dem Compiler, damit überhaupt die Bildverarbeitung ging.
Und ich gucke die mir das an und ich habe echt,
da stand es ständig, stand im Code, das war Maschinencode,
nachdem ich Podcasts embleiert hatte, subtrahiere minus 1,
subtrahiere minus 1 und ich kann und kam nicht dahinter,
wieso ein Mensch minus 1, 7, 3, jetzt statt 1 zu addieren.
Bis ich mir die Speicherbelegung angeschaut habe, der Rechner hatte nur 32K-Speicher,
das war schon unser mit dem größten Rechner.
Und das Programm war dicht an der 32K-Grenze. Der Programmierer,
der das geschrieben hat, der hat gesehen, Mensch,
ich brauche 300 mal Adiere
Und der Befehlen subtrahiere minus 1 ist um einen Wald
kürzer als der Adira 1. Das war das einzige,
was das Programm lauffähig gemacht hat auf dem Rechner.
Aber trotzdem, für jemanden, der das Programm ändern soll
, da schreibt doch bitte einen Kommentar dran.
Das nächste, wo ich gestützt habe und da musste ich
wirklich dann den Programmierer mal fragen.
Warum speicherst du diese Variablen im Ausgaberegister? Er hat gesagt,
ja, wir gehen die Variablen aus. Es ist,
nö, ich will keine Oscarbe schreiben,
aber war der einzige Platz, der da frei war.
Mit dem Programmierer bin ich inzwischen verheiratet.
Wir haben ziemlich zusammenraufen müssen,
im Laufe dieser Zeit
Okay. Ja. Also wir sind hier mit den Folien
jetzt durch. Ich hatte für heute ja noch versprochen,
dass wir uns eine der Probeklausuren angucken. Da werden wir
auch gleich nochmal reinschauen. Ich wollte auch noch ein paar Ideen geben,
wo man das, was man hier gelernt hat, vertiefen kann.
Also zum einen, Benjamin Seppke und ich,
wir machen jedes Mal im Wintersemester ein Praktikprogrammierpraktikum,
wo sie ihren Praktikumschein machen können,
mit funktionaler Programmierung in Reckett,
was wir dort als Thema nehmen,
ist meistens das für eine kleine Bildverarbeitungsaufgabe einbauen
Also was in dem Praktikum versucht wird, ist,
dass wir das Universe-System aus Recket nehmen,
um verteilte Spiele über mehrere Rechner im Netzwerk zu schreiben.
Und es sollten Spiele sein, bei denen ein Spielstand erkannt wird,
in dem eine Kamera auf dem Spielfeld guckt.
Ja, Mensch, ärger dich, finde ich,
fällt, wo stehen die Steinchen oder irgendetwas in der Art.
Also sie schreiben ein Bildverarbeitungsprogramm,
was den Spielstand erkennt und spielen verteilt auf mehreren Rechnern,
indem sie mit dem Recket-Universe-System in diesen verschiedenen Welten das machen.
Das ist meistens so der Gegenstand von diesem Praktikum,
ach so, hier steht Sommersemester,
vermutlich haben wir jetzt im Sommersemester auch wieder eins
Sie können natürlich, wenn Sie den Bereich ProLog vertiefen wollen,
sich in Modulen zu Wissensverarbeitung reinklinken.
Sie können meine Vorlesung Interactive Visual Computing besuchen, um die
dort auch mal das Programmieren in einer Grafiksprache zu üben.
Ja, wir verwenden da im Moment die Sprache Poffery,
eine interpretierte Sprache, mit der wir simulierte Welpen darstellen können.
Und überhaupt die Module Bildverarbeitung 1 und 2,
in denen machen wir die Übungen und die ganzen Sachen
sind einer anderen funktionalen Sprache,
nämlich Python
Also wer Interesse daran hat,
mit Python und vielleicht auch mit Ceeples Plast zu programmieren und darauf Templites kennenzulernen,
wie man am Bildverarbeitung mit solchen generischen Kämpfe jetzt machen kann,
der kann auch für die Programmierung in dem Bereich noch was lernen.
Ja. Okay, dann gucken wir mal in eine Klausur rein.
Sie haben die ja alle in den Übungen schon besprochen.
Und Sie haben auch gesehen, dass wir Instine
zwei Klausuren stehen haben
Im Moment. Okay. So, wenn Sie,
also zumindest in meinen Übungsgruppen, habe ich die Klausuren auch
schon mal durchgesprochen. Wenn wir uns am Dienstagmorgen treffen,
10.30 Uhr geht das Schreiben wieder los,
haben Sie diesen Bogen vor sich liegen und da tragen Sie bitte,
der sollte hier, wo es jetzt frei ist,
ein Etikett kleben mit ihrem Namen.
Also wird als erstes gucken, ob sie vor dem richtigen Bogen sitzen, ja.
Und wenn da Probleme sind, sofort melden. Gut,
note Begründung trage ich ein, das brauchen nicht Sie machen.
Ab der zweiten Seite unterschreiben Sie bitte hier, ja,
die Klausur sollte geheftet sein
Das heißt, und diese Heftklammer im oberen linken Rand lassen sie drin,
dass ich nicht ihre Seiten mit denen eines weniger Begabten vermischen.
Sie haben auf allen Seiten, ist ein bisschen Platz.
Die Länge des freien Platzes hier entscheidet,
wie lang die Antwort ist, die wir von Ihnen erwarten.
Die kullern sagen, wie viele Punkte es dafür gibt.
Am Anfang, die ersten Aufgaben beziehen sich darauf,
wo wir einfach testen, ob sie Record lesen können.
Sind sie in der Lage zu erkennen,
bei den Listenfunktionen, was ist die Funktion Kark?
Und wenn hier eine Liste steht, dass sie erkennen können,
wie viele Elemente diese Liste hat.
Wie viele Elemente hat diese Liste überhaupt? Schon mal ein
gutes Angebot, ein anderes. Das Argument von K,
die Liste. Eins, ne? Diese Liste enthält
eine Liste, also genau auf die Klammernbitte achten.
Und die ist hier dreifach geschachtelt hier.
Und es kommt aber wirklich nur eine Liste drin.
Apropos Klammern
Ich hatte die Klausur, die sie am Dienstag schreiben,
werden zum Drucken geschickt und natürlich kam, nachdem ich sie abgeschickt hatte,
habe ich gesehen, dass eine Klammer fehlt.
Habe versucht, die Druckerei zu erreichen,
die hat eine Mittagspause, hat die Drückerei wieder erreicht,
habe, hatten sie das Ding schon gedruckt.
Also ich möchte bitten, wir werden eine kleine Änderung bei Aufgabe 1,
3, an die Tafel schreiben,
wo sie von Hand dann bitte noch eigene Klammer zufügen.
Es ist ausgerechnet, die Klammer fehlt an der Stelle,
wo über die Irren und Fehlern gesprochen wird,
als Beispiel Text
Naja, gut. Die Goethe. Vielleicht nichts,
was wir halt auch von hinten,
wir sprechen weiter in unserem Flussgruppe und der ist das
nicht ganz so bis zu den Vorurteilen.
Ja, klar, wir fangen mit dem letzten an.
Ich wollte Ihnen nur so die generelle Idee mal geben.
Wir haben eine halbe Stunde Zeit, fangen wir mal von hinten an.
Ganz am Ende sehen Sie in diesem Muster noch einen Pro-Log ins Gym-Lexikon.
Ja, das bekommen Sie als separates Blatt ausgeteilt.
Sie haben einfach ein Blatt, wo Zählersklassen pro-Log ins Gym,
Map-Apply Itorate, diese Funktion mit ihren Argumenten alle da sind.
Da haben Sie also eine kleine Sandwuchs.
Jetzt gehen wir mal zur letzten Aufgabe
Ja. Also die typischen Aufgaben, muss ich es vergrößern oder können Sie es lesen?
Also die typischen Aufgaben sind so von der Art jetzt auch für den Kronok-Teil,
dass wir da einfach einen Auszug aus dem, aus der Datenbank haben,
dass Sie sehen hier das Slot-Makro, das hier einträgt.
Für dieses Beispiel, wo wir, wo ein Mensch hingeht,
der Gustav Geizig und möchte im Internet das Angebot für die beste Kamera finden,
der hat also eine Anbieterrelation, da steht drin,
der Anbieter 1 ist der billige Jakob und Da haben wir,
der hat eine Erkennung, das ist drei,
hat eine Lieferzeit und Garantie und sowas.
Versandkosten in Euro. Und diese Relation mit diesen Daten steht hier,
hier oben steht drin, okay, die Signatur, ja.
Die zweite Relation, Angebot, da steht drin,
was kostet welche Kamera, Kameranummer,
bei welchem Anbieter und was ist der Preis.
Auch zugesichert. Und dann haben wir hier noch für
jedes Kameramodell die Modelleigenschaften. Also irgendwas in der Art,
wo sie vielleicht Objekte haben mit ihren Eigenschaften zugesichert über das Modell und so.
Das wird in der Klausur garantiert vorkommen. Und dass sie
drei Relationen zueinander in Beziehung setzen müssen. So, was muss
hier gemacht werden? Bei dieser Klausur? Die erste Aufgabe war jetzt,
also wir haben hier die Anbieter mit ihren Eigenschaften,
die Angebote, wir haben das, was angeboten ist.
Und sie sollen jetzt in Pro-Log-Fragen stellen. Also es ist nicht so gemeint,
dass sie selbst jetzt die Relationen lesen und die Antwort raussuchen
und da die Unifikation und Suchern machen, sondern sie sollen hier fragen,
Bulllock in Rackett für sie, die Unifikationen macht.
Ja, wie fragen wir, welche Kamera hat einen Zoom-Faktor
von 24? Welche Relation müssen wir da erstmal aufschlagen?
Wir nehmen die Kamera-Relationen so. Und da gucken wir mal,
die hat eins, zwei, drei, vier, fünf.
Variablen und der Zoom-Faktor steht anstelle vier. Also würden wir fragen,
Kamera, dann eine Variable angeben für die Kamerakennung. Ja,
kann man rein, wo da die Kennung anonym lassen,
wenn du die Wenn ich den Namen habe,
sondern nur den Kameranamen und dann führt zum Beispiel Fragezeichen,
Name als zweites, Fragezeichen für den Hersteller brauchen wir nicht,
dann Fragezeichen, Zoom, auf Lösung brauchen wir nicht Fragezeichen oder so.
Das wäre die Anfrage, die wir bestellen müssten, ja.
So, beim Zoom-Faktor, also die echt dann die 24 eintragen.
Das haben Sie vermutlich gesehen, die Probeklausuren,
die Antworten stehen hier drin. In weißer Tinte,
also wenn Sie das mit Copy und Pist auf irgendein anderes Formular setzen,
dann können Sie es lesen.
Versuchen wir mal
Ob das hier auch klappt? Bist du, wie es
aus dem Netz runtergeladen habe? Ja, gut. Dann
sehen wir hier jetzt mal eine andere Farbe, ne?
Also das wäre die Antwort, ne?
Kamera kam 24, ja. Also mit Copy und Freest
einfach in ein Dokument reinsetzen.
Dann können sie für die Probeklausuren
die Antworten lesen
Gut, ich habe mich überzeugt, während der Klausur hilft
es nichts, wenn sie eine Ultraviolettlampe oder so mitbringen.
Also da ist keine echte weiße Tinte auf dem Papier.
Frage dazu, ja. Ja, da muss man
auch die Liskationen angegeben oder was?
Ich weiß nicht, ob ich das weiß.
Also bei den Anfragen reichen wir hier die Anfragen.
Das ist die Unifikation, wie gesagt, danach ist nicht gefragt.
Wenn jetzt als nächstes fragen sollen, was kostet eine Kamera mit 18-fach-zoom?
Da müssen wir auch noch den Preis rauskriegen und wo steht der Preis?
Ja, ein Preis haben wir in der Angebotrelation.
Das ist die letzte Stelle. Das heißt,
hier müssen wir jetzt einen Joint machen zwischen zwei Relationen über
Die Kameraerkennung, ne? Also zum einen in einem Teil fragen,
hier eine Anfrage über die Kamerarille dazu,
weil eine Variable haben, die die Kamerakennung raussucht und diese
gleiche Kamerakennung mit Co-Referenz muss in die Angeburtsrelation reingehen.
Das ist das,
was wir
hier hinkriegen müssten
Also, das Join, wir fragen, Kamera,
kamen als Variabte den Namen in der,
als Variable Hersteller 18, als der Zoom-Faktor,
nach dem gefragt ist, dann suchen wir das Angebot,
hier muss dieselbe Kameravariablen nehmen wie da,
damit wir über Chorreferenz die Bindung herkriegen.
Und hier ist der Preis, den wir als Ergebnis bekommen.
Und rauskommen sollte dann in dem Fall,
der Name ist Cybershot-Hersteller, Fotoprofi und Kamera 1 ist gleich,
Kamera ist gleich Kamera 1, ja,
und irgendeine eben.
Und der Preis ist
Und damit haben wir die Antwort. Sie können,
das haben wir ja bei Prolog in Reckett besprochen,
anonyme Variablen reinnehmen, indem sie einfach nur das Fragezeichen reinsetzen wie hier.
Und ich wollte noch mal betonen, dass diejenigen,
die die Klausur im richtigen Prolog schreiben,
bei Herrn Menzel am selben Tag,
dass die gerne die Anfragen im richtigen Prolog stellen können.
Schreiben Sie es nur da rein. Wir haben alle Klausuren
gespickt mit konzeptuellen Fragen
Also zum Beispiel würde hier gefragt werden in Sprache,
Bullock und Bullock, in Skim oder Racket, sind funktionale Sprachelemente eingewettet.
Nennen Sie mal ein Beispiel. Was haben wir für
funktionale Programmelemente in Pro-Look in Racket? Ja, wir haben
das ist, wir können direkte Wertzuweisungen machen.
Normalerweise würde in Prolock, die Wertbindung über Unifikation stattfinden.
Und wir können nicht einfach sagen, nun machen wir mein X-Ma
3. Wir können aber, es ist drin,
dass wir sagen können, ist X-3. Wir haben ein weiteres
funktionales Sprachelement kennengelernt, das ist der Test. Ja,
wir können Tests sagen und als Argument von Tests können wir
irgendeinen Ausdruck, den wir in Recket formulieren können, übergeben.
Und der wird evaluiert. Und das Ergebnis kommt zurück. Das heißt,
wir können auf diese Weise im Frohlock, in Recket,
indem wir sagen, Tests und da schreiben wir einen Ausdruck rein,
erreichen, dass dieser Ausdruck ausgewertet wird und das gesamte Recket
steht uns zur Verfügung.
Ja,
in diesem Schlüpfloch
Und was geht verloren, wenn wir das tun?
Ja, richtungsunabhängigkeit, genau, voll fit.
Genau. Also das ist das, was wir hier haben.
Ja, gut. Das wäre also in diesem Fall in der Klausur
so gelöst, weil wir hier so viel Textaufgaben hatten.
Wir waren hier keine Aufgabe zur Unifikation drin. Ersatzweise könnte
auch gefragt werden, unifizieren Sie dies und das, ja?
So, hier ist dann ein Beispiel für Celos
drin in dieser Klausur
Also was Sie an den Zählortsaufgaben immer wieder finden, ist,
dass wir uns irgendeinen Presse aus den Fingern gesaugt haben.
Als ein Beispiel, wo es sinnvoll sein könnte,
ein Aggregat zu erzeugen, in dem man mehrfach Vererbung von mehreren Klassen macht.
Wenn Sie Ihre Zielortsaufgabe in der Klausur sehen, nicht lange grüben,
grübeln bitte, ist in dem Fall mehrfach Vererbung sinnvoll oder nicht.
Wir haben versucht, es so hinzuquälen, dass Sie mehrfach Vererbung nehmen sollen.
Tun Sie es einfach. Und tun Sie uns den Gefallen
und modellieren Sie es mit mehrfach Vererbung. Und dann denken Sie drüber nach,
ob Sie Methodenkombination entweder mit Before- und After-Methoden verbinden oder ob sie Methoden,
Kombinationen wie Generic Plus Combination oder so sinnvoll einsetzen können.
Das ist immer das Ziel und Zweck dieser Frage.
Wie kombiniere ich die Ererbten Methoden? In dem Fall haben wir das Beispiel,
wir haben eine Klasse von Messgeräten und jetzt kauft sich jemand so ein Kombi-Gerät.
Ich bin ja eigentlich mehr ein Typ, der möchte ein Werkzeug,
einen Zweck und nicht so ein Schweizer Messer haben,
aber In dem Fall hat sich also gleich eine ganze Wetterstation gekauft und da ist drin ein Thermometer und ein Barometer und ein Regenmettmesser.
Und jetzt sollen sie die Klasse Wetterstation so modellieren.
Und diese spezielleren Klassen, indem sie sich was einfallen lassen. Und gut,
in diesem Fall, ich nehme es mal vorweg,
wäre die Lösung, dass sie eine Klasse,
Klasse Messgerät haben, von der er abends Thermometer,
Barometer Regenmesser und die Wetterstationen, die alles kann,
erbt von allen drei speziellen Klassenthermometer,
Barometer Regenmesser
Und da sind jetzt weitere Fragen.
Diesmal das Skript nochmal nach, was die Klassenpräzedenzliste ist.
Und dann nehmen Sie an, dass es Operationen gibt,
die jetzt durch generische Funktionen realisiert sind. Ich habe ja gesagt,
was immer eine Operation ist in der Welt der Funktionalen Programmierung,
in der Zählerswelt haben wir dafür generische Funktionen, die abstrakten Signatur vorgeben.
Und diese abstrakte Signatur, die sollten Sie einmal annehmen,
existiert, wer gibt Einheit und gibt Genauigkeit. So,
und jetzt bei diesen Geräten kann man einmal überlegen,
Wenn ich jetzt meine Wetterstation so modelliert habe,
dass ich von Thermometer, Barometer und Regenmesser erbt.
Und ich frage diese Wetterstation, was ist die Genauigkeit?
Ja, in Prozent, ein Prozent, zwei Prozent, 0,001 Prozent.
Was soll sie mir zurückgeben? Die Genauigkeit des Thermomyters,
des Baromyters, des Regenmessers oder was anderes?
Oder wir fragen, welche Einheit ist es
Frag meine Wetterstation, in welchen Einheiten müsst du eigentlich?
In Lichtjahren, in Hecto Pascal. Ein Lied dann für
den Regen? Was würde man sich als Ergebnis wünschen?
Wenn man die Wetterstation nach der Einheit fragt, ja?
Das ist nicht den Einheiten,
die halt der Bewürdigheit in der Dokumentation erwarten,
welche Einheiten es vielleicht am besten reden wird und halt in der Liste von Freiheiten.
Genau, also da würde man um die Liste der Einheiten
zu kriegen,
welche Generic Combination macht das
Generic List Combination. Die kombiniert alles zu einer Liste.
Und bei der Einheit, bei der Genauigkeit,
10 Prozent, 20 Prozent, 3 Prozent,
der eine müsst unglaublich genau, der andere sehr ungenau.
Könnte man Ihre Antwort genauso nehmen, eine Liste.
Da weiß man aber nicht, was wozu gehört.
Man könnte auch sagen, wenn nichts anpreisen will, im Werbeprospekt,
könnte ich sagen, kann bis zu 0,001 Prozent genau sein.
Wenn ich eine Sicherheitsprüfung machen will,
wäre es mir vielleicht lieber zu erfahren,
dass die schlimmste Ungenauigkeit
10 Prozent ist
Und dann würde man in dem Fall die Denaric Mind-Kombination nehmen.
Die Zahlen so kombinieren, dass man die schlechteste Genauigkeit als
Werk bekommt, um auf der sicheren Seite zu sein.
Ja, das ist also das, worauf sie beim Zählers achten sollten.
Bei der Aufgabe. Bei den Funktionen, höhere Ordnung.
Ja, haben Sie das in den Übungen noch besprochen,
an Ihrer anderen Beispiel-Aufgabe? Also diese Aufgabe 5 ist ein
ganz typisches Schema. Es ist immer so angelegt,
dass sie bei einer Programmieraufgabe mehrere Funktionen schreiben müssen und zeigen können sollen,
dass sie in der Lage sind, Funktionen weiter unten zu schreiben,
die aufbauen, auf denen sie weiter oben definiert haben.
Ja. Also sagen wir mal, sie sollen aus einer Liste das Minimum finden.
Diese Funktion ist da und weiter unten kommt eine Aufgabe,
wo sie aus vielen Listen, dass die minimal aller Listen raussuchen sollten,
da können sie natürlich ihre Minimumfunktionen da oben verwenden.
Wir sind beim Korrigieren auch so fair, Damit sie nicht
mit der Folgefehlern leiden. Sie schreiben in Aufgabe 5,
1 bis 5, 5 schreiben sie viele nette kleine Funktionen.
Und die brauchen sie alle in Aufgabe 5,
6. Sie können bei oft über 5, 6 so tun,
als hätten sie alles drüber perfekt gelöst, diese Funktionen aufrufen.
Und selbst wenn die davor alle daneben gegangen sind,
sie bekommen die Punkte für die Lösung,
wo sie ihre falschen Funktionen verwendet haben.
Wenn sie sie nur richtig verwenden. So ist es
gemeint. Was haben wir in diesem Beispiel hier?
Ich glaube, das hatten wir sogar mal als Übungsaufgabe in
diesem Semester
Aufgabe fiel mir ein, da war ich gerade auf dem Turn von Bergen
nach Dublin und hatte ein bisschen Freizeit auf der Wache,
musste mir neue Klausur ausdenken.
Und das Los war auf mich gefallen, die Bordkasse zu führen.
Also es stellen sich vor, in der Vor-Euro-Zeit, ja,
ein Segelschwanz durch Europa, in jedem Hafen eine andere Währung.
Ich war froh, dass sie einen Rechner dabei hatte,
der es geben konnte.
Und hatte mir für die Bordkasse eben auch gleich ein Programm geschrieben.
Das hat sich dann, zeigt sich hier in der Klausur.
Also die Bordkasse war gefüllt mit dänischen Kronen, mit norwegischen Kronen,
mit US-Dollar. Also irgendjemand war gerade aus der Karibik zurück,
wie kommen wir da auch noch Dollar dabei.
Und wir hatten noch Euro. Und alles wurde genommen,
eingezahlt, dann musste die Summen addieren. So,
also hier wird zuerst mal eine Bordkasse gefüllt und da steht
ziemlich viel drin in verschiedenen Währungen. Und jetzt möchte man ausrechnen,
wie viel Geld haben wir eigentlich und das alles richtig konvertieren.
Und dann wäre die erste Aufgabe rauszurechnen, was ist jetzt eigentlich das,
was die Leute in dänischen Kronen und norwegischen Kronen eingezahlt haben?
Was ist das denn in Euro wert? Und ja,
wie würden Sie es machen,
wenn Sie eine Liste haben?
Da stehen lauter
solche Paare drin
Möchte die Gesamtsumme haben? Ja, sie brauchen eine Funktion höherer Ordnung,
die erstmal jeden Eintrag wandelt in einen standardisierten Beitrag.
Alles in Euro wandelt. Und dann eine zweite Funktion,
die alles nimmt und addiert.
Und die Eurostin datiert. Also zuerst mal eine Funktion schreiben,
Kasse nach Euro, wäre die erste Aufgabe.
Das wäre also ein klarer Fall für ein Map hier.
Dann Summe in Euro. Wir haben die Euro-Werteinheiten drin,
sollen sie addieren
Das heißt, ja, eine Liste geht rein,
ein einzelner Wert soll zurückkommen.
Und das wäre ein Fall für Falten, ja?
Fold. Und jetzt wollen wir wissen, oh,
jetzt sind wir in Norwegen, haben wir eigentlich norwegische Kronen.
Wir gehen unsere Bordkasse durch und wollen alles finden,
was wir in norwegischen Kronen haben.
Welche Funktionen höherer Ordnung brauchen wir da? Ja? Filter
, genau. Also diese Aufgabe, damit können Sie rechnen,
was immer bei Aufgabe 5 steht,
das ist darauf angelegt,
dass Sie
Map Fold filtern
Funktionen höhere Ordnung nehmen und damit irgendwas über Listen machen.
Auch der Summe aller Währungen, gut,
und dann noch so ein paar Wissensfragen,
wann ist eine Funktion, eine Funktion höhere Ordnung?
Tja, es gab zwei Fälle. Entweder wenn die Argumente
einer Funktion Funktionen sind oder das Resultat eine Funktion ist.
Was sie auch finden,
ist immer ein Teil von der Aufgabe vier oder fünf,
wo sie Dinge vorgegeben haben als Assoziationslisten und in diesem Beispiel
mit der Bordkasse ist die Liste der Kurse
Was ist welche Währung wert, gegeben,
wie in der Übungsaufgabe, die sie zum Schluss berechnet hatten,
wo sie den abstrakten Datentyp verlängern hatten und addiert hatten.
Nachdemselbe ein Schema, finden sie vermutlich irgendwas,
wo sie Umrechnungsfaktoren haben. Und in dieser Liste dann suchen,
wenn wir diese Liste haben, mit welcher Funktion suchen wir,
wenn wir jetzt zum Beispiel die Schwedenkronen suchen wollen.
Würden Sie es machen, wenn Sie jetzt die Frage beantworten müssen,
was ist der Umrechnungsfaktor für schwedische Grund
Das auch. Ja, genau. Also wenn sie so
eine Assoziationsliste sehen, nicht in Panik verfallen,
nicht anfangen, jetzt ihre eigene rekursive Suchfunktion schreiben,
sondern einfach mutig zum Assoc greifen und die Werte rausholen, ja?
Gut. Okay, das sind diese einfachen Stipsfunktionen.
Wir haben die, ich hoffe,
so weit sind sie beim Üben in ihrer Übungsgruppe gekommen.
Aufgabe zwei oder drei wird immer eine sein,
wo sie Funktionen in verschiedener Form rekursiv definieren sollen.
Ja,
entrekursiv oder allgemein
linear rekursiv
Und ich denke, damit haben wir diese so ziemlich
allen Honig aus dieser Klausur rausgesaugt.
Die anderen hatten sie erst schon besprochen in ihrer Falsche.
Hatten wir die schon gesehen
Also was ihr noch suchen wolltet, Beispiele,
die wir auch in den Übungen geübt haben,
kann auch in der Klausur vorkommen,
dass ich ihnen einfach eine Liste von Funktionen an dem Kopf knalle.
Und dann kommt die Frage, welche Art von Rekursion haben wir denn da?
Also schärfen Sie Ihren Blick dafür, dass Sie einer Funktion ansehen?
Ist Sie linear, rekursiv, ist sie baumrekursiv?
Ist sie gar nicht rekursiv? Die verschiedenen Formen der Rekursion
sollten Sie jedenfalls treffen, erkennen können.
Welche der Funktionen auf dieser Seite
ist baumrekursiv
Ist das hier baumrekursiv? Linear? Entrekursiv. Okay,
genau. Dies hier? Mehrmals. Das hat hier innen
drin eine rekursive Funktion, ne?
Mull, mull. Okay. Was ist mit dem Burschen
hier?
Mehrmals drei
Baum. Ja. Warum? Weil wir hier zwei Aufrufe
mit Plus verknüpfen müssen und da, also im selben Zweig,
im selben Arzt 2 kommt der Aufruf zweimal vor.
Und was haben wir hier? Mehrmals vier.
Führt auch zu einer Baumreposion, aber zu einer speziellen.
Mehrmals, hat mehrmals auf Parameterposition nochmal im Aufruf.
Das heißt, wir haben hier eine Geschachtelte Rekursion
Und hier, bei den beiden, indirekte. Ja.
Also ich denke, damit haben wir alle Fälle angesprochen,
was so in der Klausur auftreten könnte.
Bleibt nur eigentlich nur noch in viel Erfolg dafür zu wünschen.
Und lass mich dann, mir bringt diese Vorlesung immer viel Spaß,
weil ich selbst sehr viel Vergnügen habe an diesen,
überhaupt am Programmieren, ja,
die empfinden es nicht als Belastung und speziell am funktionalen und am Vergleich vieler Programmiersprachen.
Und ich hoffe, einige von Ihnen ein bisschen von
diesem Spaß mitgekriegt. Danke für die Aufmerksamkeit.
Viel Erfolg