Ja, dann lassen Sie uns mal loslegen.
Herzlich willkommen zur letzten SE3-Veranstaltung für funktionale in diesem Jahr.
Wir haben das letzte Mal uns ja als ein Beispiel für
baumrekursives Programmieren, Funktionen höher, Ordnung des Eliza-Modul angeschaut.
Und ich wollte Ihnen noch zeigen, wie Sie es selbst ausprobieren können.
Also wenn Sie Ihre SE3-Bit öffnen, dann finden Sie innerhalb
der SE3-BIP an Modul, das heißt Eliza Modul.
Wenn Sie das öffnen, sehen Sie,
dass da zwei Varianten von Eliza drin sind. Ja,
das eine ist einmal eine ganz simple Art, Eliza,
das tut nicht viel, wenn man die testen will,
dann muss man waldiger Listen liest, immer alles als Liste eingeben.
Also wir würden aufrufen, Eliza Hello da. Und dann kommt
auch eine Liste zurück. Es gibt verschiedene Sätze von Eliza-Regeln,
die simplen Eliza-Rouls sind hier gebunden an die globale Variable Eliza Rules,
mit der man arbeiten kann.
Und es gibt auch eine etwas ostgefaltere
Also die Eliza Simple Variante als Demo, die ruft,
verwendet eben die simplen Regeln und Eliza Fancy,
die etwas ausgefeilteren, ja.
Zum Testen. Am einfachsten ist es,
wenn sie sich das Eingeben von Listen ersparen wollen,
dass sie ganz zum Schluss dieses Jahr aufrufen, Eliza Demo.
Und das öffnet ein Dialogfenster und da können sie jetzt freundlich Eliza begrüßen.
Hello Dare, einfach den Text ohne Listen klammern, ja.
Wenn sie fertig geschrieben haben,
immer okay drücken
Und dann wird die leise antworten. Ja, und
was sagt go on? Da hat sie übernimmts verstanden.
Sagen wir immer, irgendwas, was einem zurzeit bedrückt,
I need to buy Christmas Presence.
Hallo, da war ich. Und erst mal zuerst.
What would be the feel got to by Christmas Presence?
Ich könnte ja auch mal versuchen, hier die Eingabe zu machen.
Ich weiß gar nicht, ob das hier,
dann geht mein Dialog verwendet
Na, da liest es das nicht,
also müssen wir es nochmal in Squee reintun.
Wo ist es jetzt abgeblieben? Oh nee,
ich fahre hier, das ist was zu essen.
Das ist vorher irgendjemand, da war ich ein bisschen was bei dir.
Ich habe es jetzt kaputt gemacht, was?
Ja, nochmal. So, für Effekt. Wow,
that money ways date. Ich bin jetzt getrennt.
Ja. I need to present for
my perrence
Oh need to press to two on my teller.
Before etwa we need to get got. Okay. Also
fangen Sie einfach mal an, aufrufen, Fragen rein tippen,
immer den OK-Knopf drücken und dann abwarten, was passiert.
Also das kann man an dem Beispiel ausprobieren. Okay.
Also in der SE3 wird bisher vielleicht noch nicht erwähnt,
aber sind wirklich für die meisten Beispiele aus dem Skript auch Beispiele drin,
dass sie es auch echt ausprobieren können.
Ja, gehen wir mal jetzt auf die Sachen,
die wir das letzte Mal ausprobiert haben
Wir hatten, ja,
uns Eliza angeschaut und daran gesehen, die beiden Hauptprobleme,
die wir lösen mussten, war einmal ein Patternmatcher schreiben,
der aus den Regeln immer die passende Ausfüllte das richtige ersetzt.
Und außerdem brauchten wir noch eine Dialogschleife.
Was soll ich heute machen möchte, ist,
dass wir diese Dinge als allgemeine Werkzeuge zur Verfügung stellen.
Und wenn wir die haben, dann machen wir daraus ein
ganz anderes System, ja?
Was man an Liza gut üben kann, ist eben,
dass wir da einen Prototyp,
wenn regelbasierten Übersetzer haben
Haben es im Wesentlichen dadurch programmiert,
dass wir diese Sätze an Regeln aufgestellt haben,
reingeschrieben haben, was Eliza an Struktur erkennen soll.
Und wenn die Struktur erkannt wird, was als Ausgabestruktur erzeugt werden soll.
Und das ging mit dem Pattern-Matcher. Wir machen jetzt Ost
Eliza zwei Werkzeuge. Das eine ist ein regelbasierter Übersetzer,
wo wir genau solche Regeln vorgeben können, einfach als lange Liste von Regeln.
Und dann wird übersetzt in eine andere Sprache. Ich habe
für heute mir das Beispiel rausgesucht, dass man Immer in das Gegenteil verkehrt.
Also immer wird etwas positiv gesagt, dann bekommt das Negative raus,
was negativ gesagt wird, für das Positive draus gemacht.
So frei nach dem Motto, ich bin der Geist, der stets verneint.
Also das werden wir jetzt mal am Beispiel üben,
um einfach das Werkzeug, das wir aus Elisa heraus machen,
zu nehmen, um was ganz anderes zu machen,
mit einem anderen Satz von Daten.
Und die Dialogschleife auch als Werkzeug. Okay. Nee,
leise hatten wir ja einfach suchende Regeln für das Muster,
was wir gefunden haben,
wenn wir die Regel an und transformiere das Resultat
Und das wird jetzt der Rule-based Translator für uns machen.
Natürlich ist es wieder eine Funktion, höhere Ordnung,
wo wir gerade beim Thema sind. Das Werkzeug soll generisch
sein und den Typ der Regel wollen wir nicht festlegen.
Also haben wir den Regeltyp als abstrakten Datentyp mit Zugriffsfunktionen,
den IF-Teil, das, was gefunden wird und den Sendenteil, was gemacht wird.
Ja, diese beiden Akzessorfunktionen übergeben jetzt an unsere Funktionen höhere Ordnung,
die so eine Liste von Regeln nimmt und da nach Regeln sucht.
Denn brauchen wir natürlich, zu transformieren der Eingabe, irgendwas,
was eingegeben wird, so wie wir im Guri getippt haben, machen Hello da.
Und dann die Aktion zur Transformation des Resultats. Also wenn jetzt
eine passende Regel gefunden wird, muss ja irgendwas geschehen.
Und dafür übergeben wir dann eine Funktion, das passende Resultat
daraus macht. Und dann hatten wir noch gesehen,
beim Anwenden von Regeln gibt mir Pattern-Matcher uns für all die Variablen,
die in dem Muster stehen, Wertebindungen zurück.
Ja, und die zu Besicht berücksichtigen, Variablenbindungen,
die müssen wir auch als Parameter übergeben
Die Transformationen anwenden. Also unser Rule-Based Translator, unsere zweite wichtige Funktion
höhere Ordnung, die wir jetzt nach dem Backtracking geschrieben haben.
Die hat einmal die Eingabe, die gerade gelesen wird,
die Regeln, die angewendet werden sollen.
Ein Matchup. Ja, das ist, da könnten wir
Pattern-Matching übergeben oder Unifikation oder was wir so haben.
Das Rule-If, das Royal Zen, eine Funktion,
die die Aktionen ausführt und die Bindung, die zurzeit gefunden wurden.
Und die Transformation, als Teil von diesem allgemeinen Übersetzer.
Das ist einfach folgendes. Wir rufen hier eine Funktion zusammen auf.
Die hat hier den seltsamen Namen CL Doppelpunkt Sam.
Kommendes hat die schöne Funktion Sam. Die kriegt eine Menge
oder eine Liste als Eingabe und ein Kredikat und testet,
ob irgendeins Some Element, ja,
irgendein Element dieser Liste die Bedingung erfüllt.
Und da ich das aus kommenden Listen exportiert habe,
habe ich es mit dem Pre-Effix C11 für Kommendes exportiert.
Genauer gesagt habe, wie es aus Windel
Exportiert, Zwindel hat eben das Schöne. So,
und die Funktion, die aufgerufen wird, ist das hier.
Ja, die hat die Regel, die getestet werden soll,
dann ruft sie die Funktion Metscher auf,
die haben wir hier als einen Parameter an den Übersetzer übergeben.
Und da guckt sie, ob der If-Teil,
der Exzessor Rudolf ist, auch als Funktion übergeben worden von dieser Regel,
ob der angewendet auf den Input mit den bestehenden Bindungen,
ob der sagt, ja, das passt oder nicht.
Wenn für irgendeine Regel der Metscher etwas gefunden hat,
wenden wir die Aktionen drauf an.
Das sehen wir hier, Action, ja.
Und zwar wird diese Aktion angewendet auf das Resultat,
das wir zurückbekommen haben und den Zen-Teil der Regel, ja.
Also hier dieses große Sun geht, die ganze Liste der Regeln durch,
sucht ein mit Hilfe der Funktionen Metcher, die wir übergeben haben,
eine Regel, der passt.
Beim Passen muss man gucken, was ist der IF-Teil der Regel,
was ist der Den-Teil der Regel?
Und Hinterher wenden wir die übergebene Aktion an.
Also wir haben damit einen ganz allgemeinen Rahmen mit dem,
wo wir Funktionen reinstöpseln können, Zugriffsfunktionen auf die Regeln,
Aktionen, die ausgeführt werden, einen Matcher.
Und damit können wir loslegen und eine neue Sprache bauen.
Ja, und ganz hier unten ist das Argument zu diesem Sum,
das ist eben die Liste unserer Regeln, ja.
Und jetzt bauen wir unseren Negierer. Also mit diesem kleinen,
fertigen Werkzeug können wir jetzt anfangen, Übersetzer von einer Sprache in eine andere zu schreiben.
In diesem Fall geht es eben, wie gesagt,
ich bin der Geist, der stets verneint,
um das Negieren
Weil wir sehen unsere Regeln aus, wenn in der Eingabe
irgendwo nur vorkommt und irgendwas dahinter soll daraus werden,
ein Yes und irgendwas dahinter.
Wenn da irgendwo du Not drin vorkommst, sollen wir einfach,
dass du das Not weglassen und zwischen das X und Y,
was wir gefunden haben, ein Du setzen.
Oder wenn da nur ein Dusch steht,
dann sagen wir, im Gegenteil, eben du Not.
Bei Ist Not machen wir ein Ist draus,
was ist, machen wir, is not.
Aus often machen wir Saldom mit, noch vielleicht Realy machen können,
aus Never machen wir always und so weiter.
Und aus Laffen machen wir Hate und Ostoned
machen wir Du
Okay, ich hätte vielleicht noch vorsehen sollen,
Hate in Love zu wandeln, na gut.
Ja, und jetzt können wir schreiben, eine Funktion,
die Oposit für irgendwelche Worte, die wir übergeben als Satz.
Wir rufen Rule-Based Translator auf. Übergeben die Worte,
das ist die Angabe, die übersetzt werden soll.
Wir übergeben die Niggation Rules, die wir eben aufgesetzt haben.
Die Arcessorfunktion für die Regeln sind einfach Car und Cutter.
Ja, wir müssen das erste und das zweite Element der
Liste haben. Und das, was getan werden soll,
ist das Anwenden der Funktion Zubles, mit der wir die Bindungen,
die bestehen, nehmen, und es ins Gegenteil zu verkehren.
Wird zuerst aufgerufen mit No-Bad-Bindings. Zu Anfang haben wir
keine Bindung. Und das ist es dann, ja.
Und wenn wir das jetzt noch im Dialog aufrufen wollen,
dann brauchen wir noch eine Abstraktion der Dialogschleife.
Also wir brauchen etwas, was immer die Eingabe liest.
Die Eingabe transformiert, das Resultat anzeigt,
können wir auch als Funktion höhere Ordnung machen,
Wir brauchen eine Funktion, die uns eine Liste zurückgibt,
haben wir einen allgemeinen Parameter Get-Input.
Wir brauchen den Fremdsformer und wir brauchen etwas, was das Resultat angezeigt.
Also die Style-Lock-Tool hat drei Funktionen als Parameter. Und in der Schleife,
da wird einfach immer nur aufgerufen, zeige das Resultat,
wende den Transformierer an auf das, was bei Get-Input rauskommt.
Und das iterieren wir so lange, bis der Dialog irgendwann gleich beigeworden ist.
Irgendjemand sagt tschüss. Jetzt können wir unsere Nication Loop,
das ist ein Regier-Programm zu schreiben, das wird Dia-Lock-Tool aufrufen.
Da wird immer gezeigt, Niggete. Hier mach mal
eine Eingabe, dann wird die Funktion Ried aufgerufen.
Und dann das Gegenteil und fertig. Und mein Beispiel lauft
mit unseren neuen Werkzeugen. Ich sag dem Niggete,
I don't not like eyescrim, es kommt raus, I do like eyescreme.
All always look at the bright side of life,
never look and the bright side of life, ja.
Deadman don't fair plate, did man do a plate,
I do la frag it, I do not love rag it.
Und I love, ja, aber
Hate ja, aber dann sage ich immer bei,
es tut politisch wird. Also sie haben jetzt schon gesehen,
wenn man die Bausteine, die wir gebaut haben,
abstrahiert zu Werkzeugen, Kontrollrahmen,
dann haben wir Entwurfsmust dafür ziemlich komplizierte Werkzeuge und können einfach
durch das Einstöpseln von Funktionen höherer Ordnung daraus etwas zu aufwendigere Systeme bauen.
Und was wir hier vor allem genutzt haben,
um es einfach zu machen, ist,
dass wir den Teil der,
den Inhalt bestimmt,
gar nicht mehr als Racketcode geschrieben haben,
sondern als Datenstrukturen
Also alles, was damit zu tun hat,
was mache ich, wenn jemand du sagt,
dann mach ein Do not draus und so weiter.
Das sind Daten. Wir sind übergegangen, so ganz klammheimlich zur datengesteuerten Programmierung,
wo die wichtigen Dinge, die den Ablauf bestimmen werden,
eigentlich nur im Satz von einem Satz von Regeln vorgesehen sind.
Und wir haben einen Baustein,
der als Schleife immer drüber lobt und einen Baustein,
der nach Mustern in unseren Daten sucht und dann das passende Verhalten raussucht.
Wir sind der Schmidt schon ganz schön dicht drangekommen als das,
an das,
was bei der Programmierung in Prolog
nachher wichtig wird
Ja. Ich habe für diese Art von Programmierung
noch zwei Beispiele im Skript. Das erste werde ich
heute zeigen. Das andere Beispiel heben wir uns auf,
falls wir am Ende des Semesters noch Platz haben.
Also das eine ist das Programm ist Judent,
was ich liebe. Und das andere ist das Programm,
was den schlimmsten Namen aller denkbaren Programme hat.
Also insofern ein ziemlicher Unfall der künstlichen Intelligenz, der General
Problem Server. Also wurde tatsächlich verkauft unter dem Anspruch,
ich kann jedes Problem lösen, man muss es mir nur vernünftig erklären.
Und auch das Programm schauen wir jetzt am Ende des Semesters
an als Highlight,
wenn wir dann noch Zeit haben
Gucken wir uns erst mal bei den Fallstudien jetzt das Programm Student an.
Es hat dieses letzte Mal ja schon angedeutet,
von Bob Bro als Doktorarbeit geschrieben. Und es ist so
ein Klassiker aus dem Rechen- oder Mathematikunterricht in der Schule,
wo man einfach Textaufgaben lösen muss.
Dieses Programm kann eine als im Platttext gegebene Aufgabe auf Englisch geschrieben nehmen.
Aus dem Text, aus dem natürlich sprachlichen Text die Gleichung extrahieren,
die gelöst werden müssen und sie dann auch noch lösen
Und dafür verwenden wir das Werkzeug Rule-Based Transleta, was wir gerade eingeführt haben.
Also ich zeige dieses Student-Programm jetzt in der Variante,
wie Peter Norwick es in seinem Buch über AI-Programming neu programmiert hat im Kommen Lisp.
Das habe ich in Record übersetzt. Okay. Also Beispiele,
was das ursprüngliche Programm von Bobrov damals konnte,
das war 1998, war das wirklich ein Durchbruch, ja?
Man konnte eine Textaufgabe so geben von der Art Friends Age,
die vided bei Robin Seed,
ist One Half of Kellys IQ
Kelly's IQ minus 80 is robin said.
If Robin is for feature, how old is fran?
Ja? Da kann man also üben. Dreisatzrechnung dran
zu machen. Und das erste besteht erst mal darin,
jetzt aus diesem Klartext einen Satz von Gleichung zu erstellen mit
den Variablen, die gelöst werden müssen.
Das sind eine ganze Menge Gleichungen drin. Und für einen
haben wir einen festen Wert. Wir kennen die Variable Robin
Sade. Wir wollen aber wissen, die Variable,
wie alt ist Fran und den Zusammenhang zwischen Frans Alter.
Und so haben wir hier gegeben. Ja,
also wir brauchen ein Verfahren,
um die definierenden Gleichungen zu extrahieren,
die Gleichungen dann zu lösen und dann
die Lösung anzeigen
So, ich glaube, wir in der Listewelt sind,
ein Racket und so weiter,
überführen wir unsere Textaufgabe jetzt erstmal in eine Liste.
Wir sehen die Mächtigkeit der Symbolsverarbeitung. Und das Problem ist nur,
im natürlichen Text sind Punkte und die können wir nicht
einfach weglassen, weil sie wichtig sind.
Aber ein Punkt ist in einer Liste ein spezielles,
ein taktisches Element, also müssen wir die schützen.
Und deshalb püllen wir die Punkte hier in senkrechte Striche ein.
Ansonsten steht der Text genauso da wie in der Aufgabe.
Gegeben wurde
Und dann, um das Pattern-Matching nicht zu aufwendig zu machen,
schmeißen wir alle Füllworte raus,
die wir in der Aufgabe für unwichtig halten.
Die Funktion Neues Wort, die schmeißt alles raus,
was so an Partikeln und so da rumhängt,
so wie A and the this number off und ein Dollar-Zeichen, ja.
Die nehmen, also wenn das Wort eins davon ist,
lassen wir es weg. So, und wir wollen die Muster
nur für Kleinschreibung schreiben, gemäßigt, ja, oder.
Und deshalb ersetzen wir jetzt noch eine Funktion,
das nach einer Tabelle, also alles,
was groß geschrieben ist,
komplett durch Kleinschreibung
Funktionen, Translate, Upper,
wo wir diese Paare nehmen und diese Ersetzungen vornehmen.
Gut, die Zahlworte wollen wir in richtige Zahlen übersetzen.
Also diese vorgegebenen Zahlworte, wenn die nicht als Zahlen geschrieben
sind, ersetzen wir nach dem gleichen Verfahren.
Translate Number, ja. Und jetzt können wir schon eine
kleine Hilfsfunktion Lexica Liscan Words schreiben, die diese ganze Vorbereinigung macht.
Und was macht sie? Die macht ein Filtering?
Also das Gegenteil von Noise Words soll übrig bleiben.
Da wenden wir die höhere Funktion, die geht auf Noise
Word an. Wir wenden Translate Upper auf Words an,
Und das filtern wir eben mit dem Gegenteil von Noise Word. So,
wenn ich das Lexicalis Gen Words Aufruf für Word,
loo your get, when you multiply the Number 6 by 7,
dann kommt er eben raus, what do you get,
when you multiply 6 by 7, ja?
Und jetzt müssen wir uns mal etwas überlegen,
wie sehen eigentlich mathematische Gleichungen aus, ja?
Im Text kam mir sowas vor wie Van Half of Kellys IQ und
so weiter. Und das wollen wir in Gleichungen übersetzen.
Und das machen wir einfach, indem wir Muster vorgeben,
wann Half X, wenn das irgendwo im Text steht,
übersetzen wir es durch
Durch Variable X2. Ja, oder Twice X ersetzen wir mal zwei X.
Und dies hier sollen jetzt Segment muss ja sein in diesem Fall. Also die Regeln,
die bei Student vorkommen, sind alle so von der Art,
wenn wir eine Gleichung haben, also wenn jemand schreibt,
X-Equal 2, dann wird daraus Gleichheitszeichen, Prefix-Notation,
XY oder CMS wird auch alles in Ausdrücke für Gleichheit.
Ja, wenn hier jemand etwas subtrahiert, dann machen wir,
ist Minuszeichen draus oder das Wort Minus verwendet,
wird es in so etwas überführt oder difference,
mit wen wird ersetzt durch das,
Difference oder eine Addition und so weiter. Plus some product multiply
at subtract times wird alles hier in die Grundrechenarten übersetzt.
Und jetzt für den ersten Schritt, um das in einen
Satz von Gleichung zu übersetzen, verwenden wir mit den Regeln,
die wir eben aufgestellt haben, unseren Rule-Based Translator.
Das müssen wir nur rekursiv machen, weil die Ausdrücke geschachtelt
sein können in natürlicher Sprache, die uns da gegeben werden.
Und dadurch haben wir eine indirekte Rekursion Für dies Translate Pair,
das die Bindung rekursiv auflösen muss. Das sehen wir gleich
. Also das Ergebnis, was wir zurückkriegen,
das ist entweder eine Liste von Bindung oder eine Variable,
deren Name aus dem Eingabetext erzeugt wurde.
Translate to Expression. Da rufen wir also unseren Rule Bills Translate auf. Der kriegt diese Textaufgabe,
die Regeln, die wir geschrieben haben, es sagt Wannhaaf,
muss ersetzt werden durch X irgendwas 2. Ja,
ein Patternmatcher und wir sagen noch,
wie wir aus diesen Mustern was rauskriegen,
mit Schule Pattern und Schule Response.
Die Aktion, die ausgeführt werden soll, besteht darin,
dass wir Translate Pair über die Bindung schicken, die wir haben.
Und das Anwenden auf Suppless mit den Bindungen,
die wir bekommen haben, dies wird in der Eingabe ersetzt.
Und das Ganze geht los, nehmen wir zu Anfang keine Bindung haben.
Und am Ende erzeugen wir noch aus den Worten,
die wir da bekommen haben, eine Variable fürs Ergebnis.
Okay, damit wir die Eingabe ersetzt.
Also für die Variablen nehmen wir einfach das Erste der Worte.
Und deshalb ist es so wichtig, dass wir dieses neues Wort rausschmeißen.
Ja, also nicht irgendwie if then und so weiter,
sondern Der erste Name, der auftaucht, wie Friend oder Peter soll genommen werden.
Deshalb müssen die Neues Worts vor allem weg. So,
das Translate Pair, das guckt sich die Bindungen an,
die zurückgekommen sind und macht daraus ein Translate to Expression und das gucken wir uns auch gleich nochmal an.
Translate to Expression, das macht also diesen lexikalischen Scan,
alles rausschmeißen. Und jetzt sehen wir mal,
was mit dem, was wir vorbereitet haben,
da schon draus wird, aus meiner simplen Frage,
what do you get than you multiply 6 by 7,
wird gleich, ja,
weil das als eine Gleichheitsfrage interpretiert wird,
das Wort Tier
Und also wir wollen wissen, was ist Wortgleich,
Wort und übrig bleibt aus dem Venue Multipliders ersetzt worden,
zu mal sechs, sieben.
Und da steht jetzt ein Ausdruck, den reckelt sofort ausrechnen kann.
Ja, wir müssen das nur ausrechnen lassen. So,
wenn wir die ursprüngliche Textaufgabe uns mal anschauen, Lexikalisken,
Translate to Expression von Lexikalis Gun Words,
Friends Age Devided und so weiter,
da kriegen wir jetzt draus
eine Gleichung
Also der steht Friend durch Robin, ist gleich Kelly halbe.
Kelly minus 80 ist gleich Robin, Robin ist vier.
Und die Frage ist, how old is friend?
Ja? Wir haben vier Variable, vier Gleichungen,
das sieht schon mal gut aus.
Könnte man lösen, ja? Wenn die Gleichheit etwas komplizierter sind,
sind sie geschachtelt, dann muss man noch was tun.
Das muss jetzt, also wirklich in eine Liste von separaten Gleichungen
überführt werden und dann können wir loslegen, diese Gleichung zu lösen.
Create list of exquisions von so einer Expression.
Also wenn die Expression leer ist,
kommt nichts zurück
Wenn das erste Element atomar ist,
dann geben wir einfach eine Liste von diesem Element zurück,
weil wir wollen eine Liste haben und in allen anderen Fällen,
rufen wir rekasiv auf,
create list of equations für das erste Element und für die Restliste.
Okay, so,
wenn wir das jetzt für unser Friend and Robin-Problem machen,
dann kriegen wir jetzt mit dem Trendslate und
so weiter heraus tatsächlich diese vier Gleichungen,
die alle mit gleich beginnen und wo wir diese Teile
recht stehen haben
Gut. Wie lösen wir das jetzt? Erinnern wir uns mal selbst dran,
wenn wir so im Schulunterricht vor der Aufgabe saßen,
X plus Y ist 3 und Y minus X ist
4. Wie kriegen wir X und Y raus?
Man muss eine Gleichung nach einem davon auflösen und das in die andere einsetzen. Ja,
und genau das müssen wir jetzt den Racket programmieren,
dass wir, wenn wir hier eine Variable haben, wie Robin,
dass wir das, dass wir das hier nach Robin auflösen,
den Robin hier einsetzen, dann können wir es nach Kelly auflösen.
Dann setzen wir die Kelly hier ein und dann können wir
fremd durch Robin ausrechnen
Ja, weil wir Robin auch schon kennen. Und dieses Suchen,
wo fangen wir an? Das ist im Sjuden ein Tick
vereinfacht. Also ich gebe mal gleich von vornherein zu,
wir können nicht jeden Satz von Gleichungen damit lösen,
sondern damit es überhaupt geht, wird erwartet,
dass mindestens eine Gleichung dabei ist,
wo eine Variable nur ein einziges Mal vorkommt.
Das sind was so ein Einstieg findet.
Das werden wir gleich sehen, warum. Ja,
es ist also ein ganz klein wenig vereinfacht,
aber ich finde es immer noch beeindruckend.
Also wir suchen eine Gleichung, die nur eine einzige Unbekannte
enthält und die auch nur einmal.
Ja, zum Beispiel x mal 7 ist
Dann isolieren wir die Unbekannte auf der linken Seite der Gleichung.
Und da stindern ja keine Unbekannten mehr. Also können wir
es ausrechnen. Brechen wir die rechte Seite der Gleichung.
Das Resultat, was rauskommt, das setzen wir jetzt in
alle anderen Gleichungen ein, wo diese Variable vorkommt.
Und dann legen wir von vorne los. Wir suchen,
haben wir jetzt schon wieder eine Gleichung, die nur eine
einzige Variable hat und isolieren die und so weiter und so weiter.
Und Gleichung, die gelöst sind, entfernen wir aus der Liste.
Also, wie löse ich eine Aufgabe mit mehreren Unbekannten,
mit arathmetischen Grundrechen arbeiten, passt auf eine Folie.
Gucken wir uns das hier mal an. Also,
wir haben eine Funktion Zolf, ja,
die soll lösen, die bekommt hier die Gleichung,
das ist die Liste Vergleichung, die wir eben erzeugt haben.
Und this known, das ist eine Liste von Wertbindung für
Variable, die wir schon ausgerechnet haben.
Zu Anfang ist sie leer und in der Zeit wird sie hoffentlich länger.
So, und jetzt verwenden wir wieder unser Sam hier.
Aus der Liste der Gleichung, ja, finde eine Gleichung,
die nur eine einzige Unbekannte hat, ja.
Und Diese Gleichung nennen wir X. So. Okay,
wenn wir eine gefunden haben, dann rufen wir auf,
Solve Arismatic, also Löse, die Gleichung,
nachdem wir die Funktion Eissolet aufgerufen haben, Eissolet,
stellt die Gleichung um, das X alleine links steht und rechts der Ausdruck steht.
Ja, und das Solve Arismatic rechnet das dann aus.
Ja, und dann wird anschließend ein Solve rekursiv wieder aufgerufen für den Rest der Gleichung.
Den Rest der Gleichung kriegen wir, indem wir die Gleichung,
die wir gerade gelöst haben, entfernen mit Remove aus der Liste der Gleichung.
Und indem wir Das, was wir hier als Antwort bekommen haben,
Arnser, in der rechten Seite und der linken Seite der Gleichung,
die wir haben, einsetzen.
Also wir ersetzen vorher, wenn wir X-Grad rausgekriegt haben,
rausgekriegt haben, X ist 3 oder Robin ist 4,
wir ersetzen jetzt den Robin, den wir gefunden haben,
in allen Gleichungen durch 4.
Das geschieht an der Stelle und hier wird eben die Gleichung,
die wir gerade gelöst haben, rausgenommen.
Und die Antwort, die wir bekommen haben hier,
die hängen wir hier hinten an die Liste der Bekannten Variablen
Und wenn alles geschehen ist, rekursiv, immer wieder,
und wir sind fertig, dann geben wir die Bekannten Werde zurück.
Das Solve Arismatic, das ruft auf Translay to Expression,
das hätten wir uns vorher schon mal,
das wenden wir an auf Translay to Expression, sorry.
Und vorher müssen auch lexikalisch die Worte rausgeschmissen werden,
so what do you get by multiply 6 by 7,
der erste Test hier gibt uns die Antwort aus dem Hitchhiker
Sky to the Galaxy,
what is 42?
Ja. Okay
Gut. Jetzt brauchen wir nur eine Möglichkeit,
wie markieren wir eigentlich Unbekannte in den Gleichungen?
Und das machen wir einfach, indem wir ein Symbol nehmen,
dessen Name mit dem Fragezeichen beginnt. Also Simble,
wenn das im Ausdruck vorkommt, ist es die Unbekannte.
Okay. Und Quatsch, ohne Fragezeichen. Die Fragezeichen,
wann war Eliza? Und um jetzt festzustellen,
ob ein solches Symbol in der Gleichung vorkommt,
dann müssen wir einfach testen, ob rekursiv für alle Teilausdrücke,
ob es vorkommt oder nicht.
Und das machen wir in der Baumrekursion für die linke Seite
und die rechte Seite des Ausdrucks
Also, hier testen wir, ob diese Ausdruck vorkommt,
in der linken Seite des Ausdrucks oder an der rechten Seite.
Wenn gar keine Unbekannten drin vorkommen, das testet.
Diese Funktion. Und ob nur eine vorkommt, die Tel
geht ja auch systematisch durch. Ist es eine Unbekannte,
die ja, ist sie atomar, dann ist es,
dann haben wir gar keinen Ausdruck, dann kommt vollst zurück.
No unknown. Wenn es wir, wenn es da ist,
in der einen Seite und in der anderen Seite kommt eine vor oder umgekehrt.
In der einen Seite Hier,
rechts kommt es nicht vor und links kommt es vor,
in allen anderen Fällen kommt falsch zurück, ja.
Um jetzt das zu lösen, aufzulösen, da erinnern Sie sich ja dran,
wenn Sie stehen haben, X ist a halbe oder so.
Und wir wollen das jetzt nach A auflösen. Dann müssen wir
dieses geteilt durch zwei auf die andere Seite der Gleichung bringen.
Und das heißt, wir müssen das Gegenteil der Division tun. Das heißt,
wir brauchen für jeden Operator, um die Divisionen aufzuheben,
mit einer Multiplikation, die inverse Operationen,
für die Addition, die Subtraktionen und so weiter.
Und deshalb haben wir hier jetzt die Liste der Inversen zu jedem Operator,
also für Plus gleich minus, für minus gleich Plus,
für mal gleich durch und so weiter.
Und dafür gibt es keinen Inversen. Also den inversen Opperator
suchen wir mit der Funktion Essoc, die kennen wir auch.
Und wenn es kommutativ ist, dann haben wir es leichter.
Das ist bei Plus, beim Mal, beigleich.
So, jetzt eine einzige Variable isolieren,
das können wir nach diesen Vorbereitungen wunderbar machen.
Also entweder das X ist schon auf der linken Seite isoliert,
müssen wir gar nichts tun
Wenn wir jetzt aber eine Gleichung von der Form haben,
auf der linken Seite,
steht irgendwas und das ist eine Funktion von X,
dann müssen wir das auflösen nach dem A- und Rekursiv lösen, ja?
Also wenn wir stehen haben, FAN X mal ASB,
machen wir daraus FAN X SB durch A,
wenn der A mal FAN X steht, machen wir.
Auch B durch A daraus, wenn A durch FAN X steht,
dann machen wir FAN X gleich A durch B raus.
Und auf diese Weise werden wir mit der Zeit
alles umstellen und die Gleichung isoliert haben
Jetzt gucken wir uns mal an, was das Ice Solate macht.
Wenn wir hier diese Funktion Eis so lädt,
die soll, die Gleichung, die wir hier stehen haben,
fremden durch Robin, ist Kelly halbe, Auflösung nach Kelly.
Übergeben gleich, fremden durch Robin und Kelly halbe. Und dann wird es,
dass zuerst mal hier so stehen haben, wie wir es übergeben haben,
dann wird es im nächsten Schritt das durch zwei hier aufheben.
Also erstmal das Kelly nach links bringen
Nach links bringen. Jetzt haben wir es da.
Nächsten Schritt aus dem Durch-Zwei-Einmal machen. Also wenn wir das
hier mit zwei multiplizieren, Kelly Hulk, kommt Kelly raus,
aber wir müssen im Gegenzug die andere Hälfte natürlich mit zwei multiplizieren.
Die wird einen Tick komplizierter leider. Ja, und jetzt
haben wir hier tatsächlich rausgekriegt, Kelly ist mal Fremd durchrobbinswei.
So. Und wenn wir jetzt im nächsten Schritt dessen nach Fremd auflösen,
dann muss einmal Inverse Op aufgerufen werden für die Division
hier und dann kriegen wir eben raus,
Fremd ist mal Kelly
halbe Robbin
So, das Soulth Equations, das ist jetzt der Schlüsselstein
in dem Ganzen, der steht in einem Aufruf,
dass wir Soulth für Equations aufrufen und die Lösung zurückkommen.
Und wenn die Lösung da ist, dann drucken wir sie und andernfalls keine Lösung.
Jetzt müssen wir das Ganze auch noch schön anzeigen.
Also unsere Datenbank war ja so oft gesagt,
dass wir alles in Prefix haben, aber wir wollen es,
führten den Benutzer einfach zu machen,
alles in Infix-Notationen anzeigen.
Und das können wir
Auch sehr schön machen, indem wir einfach Brillfix to Infix aufrufen. Und das,
also rekursiv sich selbst, Prefix to Infix für den ganzen Ausdruck,
wir machen einen Map-Prefix infix über das, was wir bekommen,
wenn es nimmt. Binary Expression ist, ja,
je näher, dann geben wir die Liste zurück,
wo wir erst das linke Argument nehmen, dann den Operator,
dann das rechte Argument und in allen anderen Fällen geben wir den Ausdruck selbst zurück.
Und wenn das Argument einfach atomar war, dann können wir es direkt zurückgeben.
Also Prefix to Infix wird über Dieses rübergeschickt mit dieser Bedingung.
Okay. Und für die Anzeige machen wir ein Mapping,
in dem wir die Listen alle,
die Liste der Liste der Ausdrücke nimmen und machen eine Zusammensetzung
aus Wrightline und Prefix to Infix und damit können wir die Ausdrücke dann anzeigen.
Ja. Gut, lösen wir mal diese Aufgabe hier
mit Soul-Vicuations 3 plus 4, gleich 5 minus 2,
X mal 7 und 3 mal X plus Y gleich 12.
Das wird in Gleichungsform, wenn wir es übersetzt haben,
mit der Syntaxanalyse zu diesem Ausdruck hier werden und die Unbekannten
da sind zweimal das X und einmal das Y.
Und unser Lösealgorithmus wird sich daher zuerst auf die Gleichung stürzen,
die hier das X nur einmal enthält.
Und das ist die einzige Variable, das nach X auflösen.
Und das hat er mit nach ein bisschen Umstellen,
wo er die ganzen Plus und Mal aufhebt.
Müssen wir denn am Ende X ist,
minus minus 5 plus und so weiter, ja.
Und jetzt müssen wir rekursiv die Gleichung, die übrig bleiben,
nehmen. Also die Gleichung mit dem X ist verbrannt.
Jetzt brauchen wir nur noch die mit dem Y. Und diese
Gleichung mit dem Y hier, Die muss jetzt gelöst werden,
da kommt Y auch nur einmal vor.
Und wir haben schon eine wahre Habblindbindung, die wir an Zeuf übergeben.
Und damit wird jetzt noch ein Eisolet fürs Y gemacht.
Und dann kriegen wir raus, Y ist minus zwölf.
Mal dreimal zwei. Und das wird in Ost gerechnet.
Und die Lösung wird angezeigt, Y gleich sechs,
x gleich zwei. Das klappt also ganz gut. Das
Programm Student besteht jetzt einfach aus dem Aufruf von Salph Equations,
wie ich es eben vorgeführt habe.
Wobei die Worte lexikalisch gescannt werden
Ausdrücke übersetzt, mit Translittle Expression. Und das wird
regulsiv verfeinert mit dem Create List of Equition.
Da wird es flach geklopft und das geben wir an Scialfication.
Und die Worte werden eingegeben. Und da kommt nochmal wieder
die Testfrage aus dem Mitschalker Skuide, what do you get?
Ja, what? Ist sechsmal sieben, ja?
The Solution is what is 44. So, jetzt zur Frage
von Friends Age. Die Gleichung, die er lösen muss,
kriegt er raus. Friend durch Robin ist Kelly halbe.
Kelly minus 80 ist Robin, Robin ist vier und how
old is friend
Und als Solution, Fremde ist ganz schön alt.
Ja, Fremde ist 168. Kellys IQ ist 84,
ist eigentlich auch nicht so eindrucksvoll.
Und Robin ist vier Fuß hoch. Ja,
also solche Textaufgaben können sie mit dem Student sehr gut lösen.
Ja, das, was wir ans Ende zurückstellen wollen,
ist ja die typische Frage der Means-Ends-Analyse.
Ich habe ein Problem, ich muss mein Kind in den Kindergarten fahren,
aber das Auto fährt nicht und so weiter.
Und das versuchen wir mal rauszukriegen.
Das machen wir aber
Denn nach Weihnachten, ich möchte jetzt wirklich einmal ins wichtigen Baustein gehen,
Pech für die, die heute nicht da sind.
Gehen wir von der reinen funktionalen Programmierung zur objektorientierten funktionalen Programmierung
über. Und ich finde es mal ein bisschen schade,
wenn Sie in den ersten beiden Semestern das Objektorientierte lernen, wird es
Weil die Sprache, ja, war so imperativ,
ist vor allem aus der Sicht der Imperativen Programmierung gezeigt.
Und das kommt dann so rüber, als wäre inherent Objektorientiertheit
an das Imperative gebunden. Aber die Dinge,
die in der Objektorientierten Programmierung wichtig sind, für das Software-Engineering,
genau die kann man auch wunderbar im funktionalen Programmierstil verwenden.
Also das Wichtigste an der Objektorientierung aus meiner Sicht ist,
dass wir zum einen bestehende Software mit Vererbung erweitern und verfeinerten und spezialisieren können, das geht
Das werden wir hier sehen, in einer vernünftigen funktionalen Programmiersprache
sogar noch besser als in Java. Und das andere ist,
dass wir nicht auf Spezialfälle achten müssen, an jeder Stelle,
sondern dass wir eine dynamische Bindung von Methoden haben.
Ja, wir können Objekte weitergeben und können generell generisch schreiben,
indem wir sagen,
ich habe ein Objekt und auf das möchte ich eine Operation,
hole die Größe raus anwenden und abhängig von der Klasse
des Objektes
Wird aus der Menge der Möglichen Methoden,
die diese Operation implementiert, automatisch die richtige gewählt.
Und auch dieser Teil des Objektorientierten Programmierens geht ganz nahtlos,
prima, locker und lässig und einfach auch in der Welt der funktionalen Programmierung,
wenn wir dort eine objektorientierte Erweiterung haben.
Und der Schlüssel dazu sind generische Funktionen. Und was in dem System,
was ich gerne vorstellen möchte, Sillas, bestechend ist,
ist, dass dazu auch eine Ein ausgefeiltes Mitte-Object-Protokoll gehört und wir daran üben können,
mit der Programmierung zu machen und Spracherweiterungen vorzunehmen.
Und das werden wir sehen, weil wir können wirklich jedes Objekt,
jede Methode, jede Operation fragen, nach ihren Eigenschaften,
bevor wir sie anwenden.
Also alles, was automatisch an Methoden angewendet wird von generischen Funktionen,
können wir, bevor wir die generische Funktion anwenden, fragen.
Wir haben eine Operation und wollen Wissen und wollen die Größe haben.
Wir können uns vorher vergewissern und fragen,
welche Methoden kennst du eigentlich, um die Größe zu finden
Ist eine dabei, die für mein Objekt passt,
ja oder nein, ja. Und wenn da zurückkommt,
ich kenne zehn Methoden, können wir uns überlegen,
welche der Zehen wir anwenden wollen.
Wir sind nicht darauf angewiesen, nur eine davon zu nehmen,
ja. Und diese Art des Programmierens mit der Metaprogrammierung,
die finde ich sehr wichtig, weil es uns möglich macht,
eben auch sicher so, was wir mehrfachvererbung zu verwenden.
Also in der Zählerswelt ist es sehr, sehr beliebt,
wenn es darum geht, Aggregate von Objekten zu modellieren,
das so zu machen,
indem man
eine Mehrfachfachvererbung verwendet
Und zwar eine Symmetrische. Ja, wir müssen nicht uns entscheiden,
was in der Hauptklasse ist und alles andere über ein Interface machen,
sondern wir können gleichberechtigt von so vielen Klassenerben, wie wir wollen,
und brauchen keine Angst vor Erbschaftsstreitigkeiten und Konflikten zu haben,
weil wir mit Klassenpräzedenzgrafen und vielen Werkzeugen dann hingehen können und sagen können,
was wir erben wollen, wie wir es erben wollen,
ob wir die Erbschaft überhaupt ablehnen.
Und das sind also die Dinge,
die ich in bei der Gelegenheit zeigen möchte,
wie man in einem funktionalen Programmierstil,
generische Funktionen einbetten kann, die uns es möglich machen,
Vererbung zu verwenden, um Software zu spezialisieren.
Okay, und die Schlüsselpunkte sind einmal was der Unterschied zwischen der Art der Operationen,
die wir in Java haben, zu generischen Funktionen.
Wie gehen wir sauber mit Mehrfachvererbung um und wie spezialisieren wir
Ererbte, Operationen? Das ist ein Teil der,
wenn wir von einer Klasse erben und die andere soll etwas spezieller sein,
finde ich, aus meiner Sicht, in Jahr war nicht so sonderlich elegant gelöst,
ist, wenn man immer nur einen Supercall machen muss.
Da hat die Zielauswelt Besseres zu bieten, wenn man die bestehenden Dinge verwenden will. Okay,
was ich Ihnen empfehlen möchte, um es nachzulesen,
das Zielaussystem ist das erste Mal gut beschrieben worden,
1989, als es erfunden wurde,
von Sanya Kinny und Dossi ist ein netter kleiner Schmöker,
Object Oriented Programming common list programmer sky to zählers.
Also da werden die wichtigen grundlegenden Konzepte, an denen man den Unterschied Zur Art,
wie es in imperativen Sprachen realisiert ist, wirklich sehr,
sehr gut versteht. Wenn man einfach nur einen How-to-Guide braucht,
wie benutze ich es und wie mache ich es,
dann nehmen Sie das Buch von Peter Graham an Sie kommen,
Lesb, ja, der hat viele schöne Beispiele drin und zeigt an ausgefeilten Beispielen, wie man es macht.
Und ich habe im Wesentlichen diese Beispiele hier im Skript übernommen.
Also das kann man bei Peter Graham sehr gut nachlesen.
Racket ist des Commonlisb Object System voll verfügbar und das
ist eingebettet in die Sprache, fulls windel.
Wir haben bisher im Wesentlichen die Sprache Racket verwendet.
Die Sprache Volkswindel ist eine neue Implementation von Kommendes,
also von wesentlichen Teilen aus Kommendes.
Und weil es eben Afracted Off setzt, heißt das Dingswindel.
Und wichtige Bibliotheken, die ich verwenden werde aus dem Bereich
ist ZF, für die Imperativen Teile.
Man kann den Wert einer Form verändern. Ja,
das Element des Attribut in einem Objekt und so weiter.
Da verwenden wir das ZF statt Z-Bing aus Racket.
Und Misk hat viele nette Dinge, die wir schon verwendet haben.
Also verwenden Sie, wenn Sie die Zielausteile nachprogrammieren wollen,
Langswindel und verwenden auch Swindow ZF ins Windelmisk.
Ja, in Madquire. So, um jetzt Klassen einzuführen und generische Funktionen,
das sollen die realisieren für uns die Operationen auf den Objekten der Klasse.
Und dann brauchen wir noch Death Message,
um diese generischen Funktionen auch zu implementieren, der Operation,
eine Implementation zu geben.
Dann hat die Sprache noch imperative Sprachelemente,
das ist klar, Modifikatoren, Schleifen, ein Objekt
Die klassische Art mit Objekten zu programmieren, ist natürlich,
dass man deren Zustand ändert, ja.
Und wir haben noch Schlüsselwortparameter in der Syntax. Ich nehme mal als ein simples Beispiel,
daran sind noch nicht ganz die Mächtigkeit,
aber sie kriegen die Idee, wie es geht,
dass wir eine Klasse von Warteschlangen oder überhaupt von Schlangen realisieren.
Und eine Schlange soll einfach etwas sein,
heißt Klasse Q und wir haben Operationen, die darauf arbeiten,
NQ, was reinhängen, Dick Q was rausnehmen.
Mehrere Elemente reinhängen, NQ Items,
Wir können das erste Element der Schlange nehmen.
Wir können feststellen, ob sie leer ist.
Wir können alle Elemente aufzählen und sie als Liste zurückgeben.
Und wir können alle rausschmeißen aus der Schlange.
Kassel wird dicht gemacht. Ja, Reset-Cue.
Und diese Klasse steht in Relation zu einer Klasse Q-Items.
Top ist in Zählers die Oberklasse aller Klassen. Wir legen da
also nicht fest, welche spezielle Klasse das sein soll.
Wer immer, was immer, der kommt, soll sich anstellen dürfen.
Ja, und das ist in der Relation.
Jedes Element steht nur in einer Schlange.
Also man steht mit einem Bein in der anderen und,
sondern eben wirklich nur in einer. Und da dürfen aber
viele drinstehen. So, wie schreiben wir ein Dev Glass?
Das ist jetzt gewöhnungsbedürftig. Also wir sind in der Listfeld
und damit ist es natürlich das alte Spielchen, Klammer auf,
Klammer zu. Ja, dann führt kein Weg dran vorbei.
Wir sind hier in langen Swindel und ich sage jetzt,
ich möchte eine Klasse Q einführen. So, und dieses leere Klammernpaar,
Das zählt auf, wann welchen Klassen wir erben wollen,
wenn mich da nichts angebe, erbe ich nur von der Klasse top.
Ansonsten könnte ich hier aber beliebig viele Oberklassen aufführen und von allen Gleichberechtigt erben.
So, dann hat ein Objekt der Klasse Q,
hat Attribute und diese Attribute heißen Item, heißen Slots in Celos.
Ich habe hier einen ersten Slot Items. So,
und jetzt die Art, wie ich in Celos sagen kann,
was ich mit dem Attribut eines Objektes machen darf,
steht darin, indem ich verschiedene Arten von Zugriffsmethoden aufzähle.
Ja, ich kann,
muss nicht ein Objekt als ganzes geheim halten oder verbergen,
sondern ich kann für jedes Slot ganz gezielt sagen,
darf ich es lesen, darf ich schreiben, darf ich beides, ja?
Also wenn ich will, dass dieses Element gelesen werden kann,
dann übergebe ich eine generische Funktion als Reader.
Und die Sarida heißt You QItems, ja? Also wenn
ich das hier hinschreibe, dann habe ich damit sichergestellt,
dass es eine generische Funktion QItems gibt,
mit der kann ich auf ein Objekt der Klasse Q
zugreifen und ich kann es lesen
Wenn ich will, dass es geändert werden kann,
dann gebe ich hier das Schlüsselwort Writer an.
Das Schlüsselworte sind Symbole, die mit einem Doppelpunkt beginnen.
Das sind Symbole, die immer zu sich selbst evaluieren.
Also ich gebe hier eins Writer an und sage Setcue Items. Also das,
wenn ich das so in der Deklaration der Klasse mache,
dann wird für diesen Slot eine Funktion erzeugt,
mit der ich die Werte verändern kann.
Und die heißt Setcue Items. Ich kann einen Initialisierungswert angeben.
Wenn ich streng bin, kann ich auch einen Typ angeben.
Und ich sage, okay, der Typ soll die Klasse
Liste sein.
Ich kann
eine Documentation angeben
Also in Commonlist werden alle Documentations-Strings gelesen und wir können damit
die Klassen dokumentieren. Racket ignoriert sie einfach, aber
ich schreibe sie trotzdem immer rein. Wir können sagen,
ob automatisch ein Prädikat erzeugt werden soll, das testet,
ob ein Objekt der Klasse, von dieser Klasse ist.
Ja, wir sagen, es soll automatisch ein Print-Object-Methode erzeugt werden.
Und das ist die Dokumentation der Klasse. Ja,
also diese Klasse hat nur ein einziges Attribut,
das sind die Items, die da drin hängen.
Ja? Diese ganzen Dinge, die da im Doppelpunkt stehen,
sind das sozusagen Schlüsselworte oder kennen da irgendwas steht
Standardisiert. Also dies hier,
wir können selbst solche Symbole erfinden für unsere eigenen Zwecke.
In Zählers gehört Treader, Writer, Indeed Value zum Sprachstandard.
Documentation. Also das sind wirklich, sind taktische Schlüsselworte in Zählers.
Okay. Ja, was wir jetzt noch überlegen müssen,
ist wollen wir solche Attribute für jedes Element separates Feld haben
oder wollen wir es einmal für die ganze Klasse speichern?
Also Objektattribute, die für alle Instanzen in der Klasse
denselben Wert haben sollen, können wir als Attribute der Klasse betrachten.
Die werden nur einmal für die ganze Klasse repräsentiert.
Und da schreiben wir dann noch das Schlüsselwort Elocation Class rein.
Damit haben wir dann ein Attribut, das für alle Elemente
der Klasse praktisch so als globale Variable gilt.
Mit Elocation Instance würde es für jedes Objekt neu erzeugt werden
und wäre für alle verschieden. Und das ist der Default,
deshalb brauchen wir es nicht zu schreiben.
Nur wenn es eine Klassenattribut sein soll,
dann schreiben wir Elocation Class rein
Ja. Gut. Syntax von Dev Klaas, jemandem.
Also als erstes schreibt man Dev Klaas, macht die Klammer
hier hinten zu, denkt sich einen Namen aus.
Und dann in einem Klammerpaar werden einfach die Oberklassen,
von denen wir erben, aufgezählt.
Kann leer sein, wenn wir von niemand erben wollen.
Dann kommt eine Liste, Klammer auf, Klammer zu,
von Slots. Und diese Slots,
da können wir eben beliebig viele haben,
so wie wir hier eben
diesen Slot Item setten
Und da geben wir Rieder, Reiter und alles an,
was wir wollen. Und dann können noch Klasse und Schlüssel sein,
wo wir sagen, können eben wie Elocation Class und so weiter.
So, ich hatte jetzt Tieren schon ein Dev-Class reingeschrieben, einen Stern dahinter gemacht.
Wenn wir Klassen so definieren und sie sind in einem Modul definiert,
dann wird der Name dieser Klasse und alle Zugriffsfunktionen,
die da drin definiert sind, werden automatisch exportiert.
Wir brauchen es dann nicht mehr im Provide zu schreiben.
Also dieser Stern das, was in dieser Klasse definiert,
ist automatisch mit einem privat nach außen sichtbar machen.
Gut. Jetzt kommen wir mal zu den Operationen.
Also wir können jetzt schon mal sowas wie eine klasse Schlange oder so haben,
können von was erben und Attribute vorsehen, Slots in Zählers.
Jetzt wollen wir auch noch was damit anfangen wollen und wollen
jetzt Operationen darauf definieren und für diese Methoden implementieren.
Also die Operationen werden in Zählers als generische Funktionen definiert.
Generische Funktionen sind Auf jeden Fall überall da verwendbar,
wo man eine Funktion verwenden kann. Also wir können sie
mit Funktionen höherer Ordnung verwenden und allem, ja.
Aber sie können mehr, wir können sie spezialisieren.
Und wir können solche generischen Funktionen zunächst als abstrakte Operationen einführen und eine Signatur vorgeben.
Und dann später implementieren, wann immer wir eine Implementation brauchen,
mit Death Message eben eine Implementation zufügen.
Also wenn wir eine abstrakte Operation haben wollen,
schreiben wir nur die generische Funktion hin und implementieren nichts,
Ist die Operation vorgesehen,
beschreibt das Interface und die Implementationen können wir geheim halten,
in einem anderen Modul implementieren zum Beispiel.
Wir wollen jetzt also in unsere Schlange da Elemente reinhängen und
dazu sagen wir Dev Generic NQ und übergeben ein Objekt der Klasse Kuptiu.
So. Und die Syntax für Argumente,
die von einer bestimmten Klasse sein sollen,
die ist jetzt, dass wir hier gleich eine Doppelklammer aufmachen
Also erste Klammer sagt, also NQ, das sind die
Argumente von NQ. Und das erste Argument von NQ,
das ist ein Objekt der Klasse Q. Ja,
und das zweite ist irgendwas, das ist von keiner Klasse,
haben wir keine Klassenbindung vorgesehen, das schreiben wir hin wie immer.
Also für alles,
wo NQ für ein Objekt in eine bestimmte Klasse abhängig sein sollte,
das müssen wir eben in diese zweite Klammer setzen und den Namen der Klasse dahinter setzen.
Wir können bei generischen Funktionen,
wenn wir sie definieren,
auch in Documentations
dringend angeben
Und so weiter. Wir definieren hier jetzt mal das ganze
Schnittstelle, wie ich sie in dem Klassendiagramm gezeichnet hatte.
Also wir sagen, wir wollen auf jeden Fall eine generische Funktion Decue haben.
Wir übergeben irgendeine Q und die gibt uns dann ein Resultat zurück.
Wir wollen das NQ Items haben. Ja, das erste ist
eine Q. Das zweite, da haben wir nur gesagt,
es soll vom Typ Liste sein, aber es ist keine Klasse.
Weil Dev Generic haben wir gesagt, okay,
für Headcue, das erste Element der Q,
da haben wir nur das Argument der
Testen, ob es eine MTQ ist, haben wir auch
nur das Argument von der Classic Q. Newberred Q and Reset Cute.
Wir brauchen alle keine weiteren Argumente. Was man ja in
diesem Beispiel nicht sieht, ist,
dass die generischen Funktionen von Objekten vielerlei Klassen auf einmal abhängen können.
Also wir definieren generische Funktionen in der Regel für mehr als eine Klasse.
Und sie sind nicht automatisch nur einer Klasse zugeordnet und werden
irgendwie nur in einen Pfeil reingeschrieben für diese Klasse,
sondern wir können die generischen Funktionen definieren in einem separaten Fall,
wir können die Implementationen dahin schreiben, wo wir wollen,
wo wir sie brauchen.
Sie müssen nicht notwendigerweise für eine Klasse geschrieben werden.
Also in Zedlers ist, besteht kein enger Zusammenhang zwischen den Pfeils,
wo eine Klasse beschrieben wird und den Implementationen der Operationen und
so weiter und der Definitionen der Klasse.
Also diese Einheit ist nicht da. Ja,
wir strukturieren, indem wir Module schreiben, wir strukturieren,
indem man es Klassen ausdenken,
aber Module und Klassen sind nicht unbedingt eins und
schon gar nicht die Pfeils.
Wir nehmen jetzt mal an,
dass wir die Implementation für unsere generischen Funktionen so machen,
indem wir da einfach die Liste der Elemente in der Q einfach als Liste implementieren,
indem können wir mit Bush und Pop einfach auf diese Listen was drauf tun,
ja?
Also sei die Elemente der Liste, der Schlange als Liste gegeben,
dann können wir eben das erste Element bekommen,
indem wir einfach sagen,
first,
eine Frage nach dem Q-Items
kriegen die Liste zurück
Und davon das erste Element, dann haben wir den Headdacue.
Testen, ob die Liste die Schlange leer ist.
Wir fragen, ob die Q-Items null sind. Zum Zurücksetzen,
dann verwenden wir Set Q-Items und setzen die Q auf die leere Liste.
Das war ja eine Accessor-Funktion da drin. Und um die Liste
der Elemente aufzuzählen, da sie schon als Liste repräsentiert sind,
müssen wir eigentlich nur die Q-Items zurückgeben.
Also das Death Messity, das implementiert jetzt,
was wir hier mit Death Generic definiert haben.
Und jetzt hat jede dieser Signaturen
eine Implementation zumindest
So, das Deck Cue,
das rausnehmen, da verwenden wir die Windelfunktionen Pop.
Das ist eine Funktion, die eine bestehende Liste modifiziert,
gibt das erste Element zurück und verändert die Liste.
Das erste Element wird rausgenommen. Und beim NQIteems,
wenn wir vieles reinhängen wollen, dann machen wir einen Curry
mit NQ und schicken das einfach über die Liste der Items.
So, wie geht's jetzt mit Vererbung?
Ich habe jetzt bei dieser Schlange ja gar nicht gesagt,
was für eine Art von Schlange das sein sollte.
Das ist nur ein Ding,
das hat Elemente
Und wir können ein Element zurückkriegen, wir können was einhängen, weil keine bestimmte Ordnung vorgesehen für die Liste.
Wenn wir jetzt spezielle Typen von Unterklassen dieser Schlangen haben wollen,
dann könnte es zum Beispiel interessant sein,
die Last in first out, cute, es wäre ein typischer Stack,
wer sich zuletzt angestellt hat, wird als Erster bedient,
oder eine echte Warteschlange, das wäre eine Fifocue,
First in first out und dann eine Ranked Cue,
wo jeder nach dem Rang und den Sternen auf dem Uniform Jackett in die Schlange eingereiht wird.
Oder eine Random Cue, das würde unsere Mensa gut modulieren.
Also man kommt an, stellt sich an und landet dann irgendwo.
Das ist, also diese vier unterschiedlichen Klassen von Cues wollen
wir mal realisieren. Und was wir da ändern müssen,
ist, dass jede dieser Klassen, die NQ-Operation spezialisiert.
Also man landet an einer anderen Stelle in der Cue.
Und bei der Ranked Cue brauchen wir noch ein Zufallsprädikat,
das uns oder ein Rankprädikat, das uns einen Rang gibt.
Und bei der Random Cue Da brauchen wir noch einen Zufallsgenerator,
der sagt, mit welcher Verteilung der Zufall da wirken soll.
Ob wir eine Gleichverteilung haben oder ähnliches. Gut,
starten wir mal mit der Last-in-First-Outcue, also dem typischen Stack.
Da können wir fürs Endcue, also als erstes mal sagen,
diese Klasse Last-in-First-Outcue, die erbt von der Klasse Q,
hat damit alle Implementationen geerbt, die wir haben, alle Methoden,
die schon für die generischen Funktionen, da sind alle Accessor-Funktionen und so weiter.
Was wir jetzt aber machen, ist,
wir sehen ein neues Element, eine neue Implementation für Encue vor,
die nur für diese spezielle Klasse da ist.
Und da sagen wir einfach Push, Item, auf die Q-Items.
Also was gerade kommt, wird vorne in der Schlange eingehängt.
Für die First-in-First-Ide-Cue, da müssen wir die Leute hinten anhängen in der Schlange.
Und deshalb müssen wir wissen, wo hinten ist.
Und jetzt führen wir hier noch einen weiteren Slot for Tale.
Der kommt dann also nur in dieser Unterklasse FIFA Cue vor.
Und wenn wir da was reinhängen wollen, dann müssen wir eben das letzte Element
So ändern, dass wir ein neues Kons erzeugen,
dass eine neue Liste, ja,
und da hängen wir den bisherigen Rest rein, so, mit Q-Items.
Also ganz am Ende der Liste reinhängen und eine neue Kunstzelle und diese neue Kunstzelle müssen wir,
in das Feld eintragen, wo das letzte Element ist,
deshalb müssen wir das Set Tail jedes Mal in der Klasse überschreiben mit dem neuen Element.
Ja, Was wichtig ist in Zillos, ist,
dass definierte Klassen, Instanzen der Klasse Klaas sind.
Und dann mit der Klasse Klaas kann man eine ganze Menge
machen und sie danach fragen, im Meta-Object-Protokoll,
das sehen wir später noch.
Und definierte generische Funktionen sind Instanzen der Klasse Generic.
Und mit der Klasse kann man auch eine ganze Menge machen.
Und die Generics sind eine echte Unterklasse von Function.
Und Function ist das, was wir bisher verwendet haben,
die Procedures
Wenn wir jetzt Operationen auf Klassenvariablen machen oder überhaupt auf Klassen,
wir können zum Beispiel fragen, wir erzeugen jetzt eine random Q,
ja, die habe ich dem Implementationen,
habe ich eben übergangen, aber was soll's?
Wir können, wenn wir ein solches Objekt vor uns haben,
fragen, was ist deine Klasse?
Und mit Glassoff, das gibt uns die Klasse zurück.
Wir können fragen, wenn wir nicht ganz sicher sind, random
QQ bist du eine Unterklasse der Klasse Q und wenn wir diese Frage stellen,
dann bekommen wir als Antwort Alle Oberklassen, erstens tatsächlich,
das ist eine Unterklasse von Q und wir erfahren auch noch die Oberklassen,
nämlich die ist klassisches Object und dann top.
Wir können zwei Klassen vergleichen, die voneinander geerbt haben und fragen, welches ist die Spezifischere?
Das hilft uns, uns im Klassenpräzedenzgrafen zu orientieren. Wir können jede Klasse fragen,
jedes Objekt einer Klasse fragen, jedes Objekt und jede Klasse selbst,
wie hier auf der Folie stehen, welche Slots hast du,
also nach welchen Attributen kann ich eigentlich fragen, ja?
Also wenn ich einfach frage, Print Klaas, Slots,
Fifacue, dann bekomme ich hier, aha,
es gibt den Slot Items und für den habe ich einen
Reader und ich habe einen Reiter und ich kann Initialisierungswert angeben,
der ist leider dummerweise leer, aber ich kann mich überzeugen,
bevor ich mit so mich an das Objekt dran traue,
wie ist es initialisiert?
Ich habe hier, ich weiß, sehe, aha,
ich habe einen Slot,
Tail und ich bekomme die ganzen Accessor-Funktionen zurück,
um da irgendwas mit troffen zu machen und den Documentation String
Wir können auch, wenn wir so eine Generic Function haben,
wie NQ, fragen, welche Implementationen gibt es.
Und dann sehen wir, ja,
wir bekommen einmal das NQ für die Random Ranked Cue,
für die Random Cue, für die Ranked Cue,
für Liefer Q und so weiter.
Wir können eine Funktion fragen, was ihre Stelligkeit ist,
bevor wir sie aufrufen.
Damit wir auch genügend Argumente angeben.
Nur für faule
Sie wissen ja selbst aus dem,
ihren bisherigen Erfahrungen mit Objektorientierten programmieren, dass es eigentlich Sinn macht,
zuerst die Schnittstelle zu dokumentieren und dann die Implementationen zu machen.
In Zelos können sie aber müssen nicht. Ich lege es
ihnen trotzdem nahe. Das ist eine gute Methode ist,
dass sie alles zuerst mit generischen Funktionen definieren und das dann
an die anderen im Team weitergeben und ihre Implementationen geheim halten zum Beispiel.
Also sie können Methoden direkt definieren und wenn es keine
generische Funktionen gibt,
wird sie automatisch erzeugt
Und aber wenn sie Klasse zunächst abstrakt definieren, wird es lesbarer.
Ja. So, wir kriegen jetzt Objekte einer Klasse.
Dafür gibt es einfach die schöne Funktion Make. Ja.
Und das ist eigentlich nichts Bemerkenswertes. Wir sagen Make,
Lefoccue und haben ein Objekt erzeugt, der Klasse Lefocue,
fertig. Ja. Was wichtig ist für den Programmierstil in
der funktionalen Welt ist, dass das Make
zwei Dinge tut
Also es ist ja eine Funktion, die wir aufrufen,
solange wir die Objekte erzeugen, können wir nicht objektorientiert arbeiten,
weil wir haben ja noch kein Objekt.
Was make macht, es erzeugt zunächst mal das Objekt mit
Allocate Instance, ja, und dann danach existiert ist.
Und in dem Moment, wo das Objekt erzeugt ist,
ruft es eine generische Funktion auf Initialize.
Und dies initialize sieht das erzeugte Objekt als Objekt. Und wenn wir Code für die Initialisierung schreiben,
dann ist es der gute Stil und überhaupt in der ganzen Welt der Ziele ist,
Programmierung, das, was man üblicherweise tut, ist,
dass man dann diese generische Funktion in Initialize spezialisiert mit der Methode,
die wir haben wollen.
Für dieses Klasse. Also, dass wir,
das Schöne in Zählers ist, sobald das Objekt erzeugt ist,
können wir mit Initialize es objektorientiert zugreifen.
Dieses Initialize wird aufgerufen, soll initialisieren. Und wenn wir
das Initialize spezialisiert haben, dann können wir damit machen, was wir wollen.
Wir können Also sobald ein Objekt mit Milk erzeugt wird,
können wir darauf zugreifen und es initialisieren, wie wir wollen.
Und wir müssen nicht 30 bis 40 verschiedene Konstrukturen schreiben,
für jede Art, wie wir es initialisieren wollen,
sondern wir schreiben einen Konstruktor und spezialisieren mit Initialize,
was geschehen soll, abhängig von allen möglichen Bedingungen.
Ein typisches Beispiel, wenn man so Objekterzeugung initialisieren kann,
das ist jetzt aus dem Buch von Peter Graham übernommen.
Wir versuchen mal Eisbecher zu erzeugen und zunächst mal die Billigausgabe.
Da gibt es nur Ein Eisbecher ist ein Objekt, erbt von nix.
Hat aber zwei Kugeln. Sorte eins ist Erdbeer und so
hatte zwei Schoko. Und wir sehen hier jetzt auch,
man kann beim Initialize zum Beispiel den Inite Value,
der ein Erdbeer oder der Schoko vorgeben.
Wir können auch verhindern, dass etwas verändert wird,
indem wir nur einen Rieder vorsehen, keinen Writer.
Und wir können noch sagen,
wenn ein Kunde was anderes haben will, initiak,
da haben wir bisher noch nicht drüber gesprochen,
da sagen wir,
Doppelpunkt SO-Wann
Wir haben an der Stelle, wenn man das so schreibt,
haben wir jetzt ein neues Schlüsselwort definiert.
Sorte 1, ja. Und wenn wir bei Milk diese Sorte angeben,
die Schlüsselwort, dann können wir beim Aufruf des Konstruktors sagen,
wie das Element initialisiert werden soll.
Sorte 2 haben wir Schoko und haben ein anderes Innet-Arc,
Sorte 2 kann also auch geändert werden.
Wenn wir nur Make-Eisbecher sagen, kriegen wir dieses Mini-Fürst-Bückler
nur mit Erdbeer und Schoko, ja.
Sorte 1 und Sorte 2. Wenn wir dagegen hier,
eins dieser Innet-Arc-Schlüsselworte verwenden,
dann können wir jetzt darauf bestehen,
dass wir als Sorte
zwei Zitrone kriegen
Also hier haben wir selbst ein solches Schlüsselwort definiert.
Da kommt der Eisbecher Zrücksorte eins, Erdbeer, Sorte zwei Zitrone.
Oder wenn wir so ein Zufallslotterie haben wollen,
können wir einfach Lorandom-Kugel als Initialisierung nehmen.
Die feinen Random-Kugel. Und das holt aus der Liste Vanille,
Erdbeer und so weiter. Irgendeines raus. Und dann könnten wir sagen,
initialisiere meinen Eisbecher zwei. Bei dieser Klasse ist die Sorte eins,
nicht mehr mit einem der initialen, mit der Variable Inite Value initialisiert,
sondern mit dem Aufruf einer Funktion, Random-Kugel, ja,
wir können direkt in die Klasse reinschreiben,
wenn wir die Slots initialisieren wollen, den Namen einer Funktion,
die ausgeführt werden soll, um das Feld zu initialisieren.
Das Schöne ist, diese Funktion kann sich eben alles anschauen,
was an anderen Objekten schon erzeugt wurde,
was immer wir am Kurt vorgeschrieben haben, das heißt,
das ist die Stelle,
an der wir ein Objekt ein bisschen raffinierter initialisieren können,
ja, also dieser Eisbecher hier würde immer Sorte 1 und Sorte 2 zufällig auswürfeln,
es sei denn, der Benutzer geht hin und sagt,
in der Ark 1,
aber für Sorte 1 völlig unbedingt meine Zitrone haben
So, jetzt können wir an unseren Warteschlangen weiter,
bauen jetzt auch noch die Ranked Cue bauen.
Und da können wir jetzt sagen, dass diese Klasse
als Element auch eine Funktion gespeichert bekommt. Wir hatten,
bei den Klassen hatten wir doch bisher einfach nur ein Feld Items und da hing die Liste drin mit allem,
was in die Schlange eingereiht wurde, für eine Schlange,
die jetzt nach einem Rank entscheiden soll, wer da vorne stehen,
Professoren immer vorne in der Mensa oder so, ja.
Da können wir dann hier ein Prädikat übergeben, Rank Pee,
dass sich das Objekt, was eingereiht werden soll,
anschaut, dessen Rang entscheidet und dann zurückgibt, eine Zahl,
an welcher Stelle diese Person in der Schlange reingereiht werden soll.
Ja. Okay. Und deshalb sagen,
damit das auch gut geht und wir es aufrufen können als Funktion,
sagen wir hier als Typ Function.
Ja. Der soll also wirklich als Read,
als immer nur eine Funktion übergeben werden sollten für Rang-OP.
Und jetzt können wir zwei Elemente einer Schlange,
einer solchen Schlange vergleichen,
indem wir einfach ihren Rang vergleichen in der Liste und dann anfangen,
beim Einreihen drauf zu achten, ob man davor oder dahinter gestellt werden soll.
Zum Beispiel Rangless hier für eine Q. Da wird geguckt für
zwei Items in dieser Schlange, Item-Wann-Item-2,
ob der Rang von Item 1 kleiner ist als Item 2.
Also das war dieses Srank-Pea, was wir hier übergeben haben.
Und dann können wir eine Schlange nach Rang sortieren.
Also wir sehen hier, ich habe hier eine solche Schlange erzeugt, Ranked Q.
Und habe als Rang einfach die Identitätsfunktion übergeben. Das heißt,
wenn Sie ein Element vom Wert 1 anstellt, ist ein Rang 1.
Und ich hänge hier als erstes in die Schlange ein,
NQ, in diese Schlange rankt, ein Element mit einer 3,
das steht am Anfang vorn.
Danach reicht das Element eins ein und das wandert sofort in der Schlange nach vorne,
dann kommt das Element zwei, das wird hinter eins eingerannt und vier,
was als letztes kommt, steht am Ende.
Und wenn wir uns dann am Ende anschauen,
wie die Schlange sortiert ist, indem ich einfach einen Deck Queue mache,
der Queue Deck Queue Deck Queue Deck Queue,
also aus der Schlange rausnehme, dann kriegen wir genau die Liste 1,
2, 3, 4. Weil die Elemente,
die werden hier durcheinander reingehängt, aber in dem Moment,
wo sie in die Schlange reingehangen werden,
wird geguckt,
an welche Stelle müssen sie und so ist die Schlange
also nach Rang geordnet
Ja, die mehreren Oberklassen hatte ich ja auch versprochen, von denen man erben könnte.
Wofür nehmen wir das? Speziell für Aggregate. Also wenn ich sowas habe wie,
jemand ist Student oder Studentin,
aber gleichzeitig hat die eigene Firma aufgemacht, ja,
in der einen Welt ist eine Firmenchef und Direktor und in der anderen sind sehr oder sie Studentin,
dann möchte man natürlich, dass dieses Objekt tatsächlich beide Klassen voll erfüllt,
gleichberechtigt und nicht irgendwie sagen, der Staat, der Student,
ist der Allerwichtigste und über ein Interface kriegen wir jetzt noch den Firmendirektor rein.
Sondern das Objekt will wirklich beide Eigenschaften erfüllen, gleichberechtigt, ja.
Und deshalb ist es ein Zelos so, dass eine Klasse von
den Oberklassen von vielen Oberklassenerben kann gleichberechtigt alle Methoden erbt.
Die Vereinigungsmenge der Attribute der Slots. Und wenn jetzt Oberklassenattribute Slots
aber nur einmal haben, werden die Attribute nur einmal vererbt.
Also der Klassiker schlechthin ist, wir haben einen Anzug,
Und wenn ich einen Anzug besitze oder ein Kostüm,
dann habe ich auf jeden Fall vollwertig eine Hose oder eine Jacke.
Und deshalb kann man, und das ist Journalistwelt so üblich,
einen Anzug modellieren, indem man sagt, ein Anzug ist etwas,
das als Jacke fungiert und als Hose fungiert.
Und es erbt deshalb von der Klasse Jackett und auch von der Klasse Hose.
Und wenn Menschen nicht symmetrisch gebaut sind, könnte es sein,
dass der Jackett eine andere Größe hat als die Hose,
damit es maskeschneidert passt.
Also wie wird dies in Zählers machen?
Dev Klaas Jackett
Und das, dann nehmen wir mal an,
Defaults und alle ein bisschen Schmollbrüste durch das, initialisieren wir mit Größe 40.
Und die Größe hat eben einen Akzessor Größe für die Hose,
habe ich ein Inite Value von 44,
weil alle einen Wunsch ins Bauch haben.
Und einen Akzessor Größe Hose, ja. Wir haben in beiden Fällen
einen Print davor gesehen und wir sagen jetzt einen Anzug,
der erbt von Jackett und Hose.
Wenn ich einen Anzug mache,
sehe ich als erstes nur das Feld Größe 40,
aber die zweite Größe ist immer noch da
Wenn ich die Klasse dort vom Anzug mir anzeige,
dann sehe ich tatsächlich,
dass ich hier das Feld Größe habe mit zwei verschiedenen Inits,
Init Values und zwei verschiedenen Akzessorfunktionen.
So, ist der Anzug eine Unterklasse von Hose?
Fragen wir mal. Glas Hose, Glas Object,
Glas Topbier. Ist es eine Instanz von Jackett?
Ja, sehen wir auch, ja.
Okay. Wie hält man jetzt die Übersicht über diese Mehrfachklassen,
von denen
wir haben
Das ist einfach strikt geregelt, in welcher Reihenfolge geerbt wird.
Jede Klasse hat Vorrang vor ihren Oberklassen. Und wenn wir
von vielen Klassen erben, dann müssen wir sie ja geordnet hinschreiben.
Es bleibt uns gar nichts anderes übrig.
Und in der Reihenfolge erben sie auch. Also in der
Liste der Oberklassen ist implizit die Präzedenz der Oberklassen.
Wenn es einen Erbschaftskonflikt geben sollte. So,
und wir dürfen überhaupt nur Klassen definieren,
bei denen es möglich ist, dass diese Ordnung existiert.
Wenn wir das nicht hinkriegen können,
ist es uns verboten,
es so zu definieren
Könnte zum Beispiel so aussehen, eine Klasse M-A-B-,
CD-Abt von einer Klasse M-A und die wiederum erbt von
M-A und M-B und M-C-D-Erbt von M-C und M-D.
Und wenn wir hier jetzt etwas erben und sagen selbst nicht,
was wir gern hätten wollen von dem vielen,
was wir geerbt hatten, sondern die Vorträge,
würden wir der Speziellste erben, wir das M ganz links.
Okay, wenn wir es nicht genau wissen, was wir
wie geerbt haben, dann können wir uns einfach die Klassenpräzedenzliste anschauen.
Und die zeigt uns jetzt, mit der Reihenfolge hier mit
den Pfeilen gezeichnet ist, wir von den Oberklassen geerbt haben.
Also Klaas, CIPL, Klaas, Presedents List.
Für unsere Klasse gibt uns die Liste der Oberklassen genau in
der Reihenfolge, wie die erbten Werte zugreifbar sind.
Okay. Es kann passieren, dass man auf verschiedenen Ebenen wegen
abt und dann gilt der linkeste Weg, auf dem wir geerbt haben.
Ja, das sagt uns auch der Klassenpräzedenzgraf.
Wo wir jetzt nach Weihnachten drüber reden werden,
Das ist eigentlich das mit das mächtigste Werkzeug beim Umgang mit der Art Methoden,
dass wir in dieser Welt haben.
Das ist, dass wir Methoden kombinieren können.
Wenn wir jetzt vom Anzug geerbt haben, die Größe.
Und wir kriegen zwei verschiedene Größen zurück. Der Kunde fragt,
welche Größe hat der Anzug? Dann ist es doch dumm,
wenn wir eben nur eine verraten. Entweder ist es beleidigt,
wenn er nur die zu große Größe für die Hose kriegt
oder die zu kleide für die Jacke.
Es ist viel sinnvoller, wenn das Ding zwei Werte hat,
dass man auch alle beide angibt
Und genau das können wir machen, indem wir in dem Fall,
wenn viele Methoden anwendbar wären und wir sie auch gerne alle anwenden würden,
dass wir sagen, wie sie angewendet werden sollen.
Und das sind eben die Methodenkombinationen, die möglich sind auf Methoden.
Jetzt für unser Anzugbeispiel. Wenn das Ding
einen Preis hat und wir wollen nicht arm werden,
wollen wir den Anzug nicht zum Preis für die Jacke
alleine oder die Hose allein verkaufen,
sondern wir wollen
die beiden Preise addieren
Die Farbliste wollen wir haben, ja. Also wir möchten,
wenn jemand nach dem Preis für einen Anzug fragt,
die Summe der Preise von Jacke und Hose kriegen und nicht nur einen von beiden.
Und bei der Farbe vielleicht die Liste der Farben, ja, für die alle Einzelteile.
Also wenn wir wieder jetzt bei unserer Kleidung sind,
Kleidungsklasse, wir haben ein Jackett,
wir haben Hose und die unten ist der Anzug und der
war vom Jackett den Preis und von der Hose dem Preis und die Farbe,
dann können wir sagen, für die Methode Preis, Entschuldigung, ich bin unpräzise.
Für die generische Funktionen preis. Für alle Preise,
die in Untergrund und Oberklassen definiert sind, sagen wir,
wenn jemand preis aufruft, wird nicht der nächste Preis genommen,
der eine Liste in der Klassenpräzedenz gefunden wird,
sondern die Summe aller Anwendungen der Methode,
der implementierten Methode preis.
Und das sagen wir, indem wir sagen,
Dev Generic soll kombiniert werden mit der Combination.
Generic Plus Combination. Bei den Farben dagegen,
wenn da verschiedene Methoden sind, die uns aus den Oberklassen
die Farben geben
Dann wollen wir die Farben alle als Liste kriegen. Deshalb sagen wir hier Generic Appent Combination, ja? Und wenn ich jetzt hier ein Jackett als Kleidung habe,
eine Hose als Kleidung und einen Anzug aus Jackett und Hose und implementiere,
den Preis für das Jackett mit 20 und für die Hose mit 40 und Methode,
Farbe,
Fischerkett mit droht und für die Hose mit blau und frage jetzt nach dem Preis vom Jackett,
ja, ich erzeuge ein Jackett ist 20,
aber wenn ich jetzt einen Milkanzug mache,
dann ist der Preis 60 eben die Summe aus 40
für die Hose und für 20 Fischerkett
Und hier, bin ich nach der Farbe fragt,
Fischjackett ist sie rot, für die Hose blau.
Wenn ich nach der Farbe vom Anzug frag, dann kriege ich
die Liste rot laut zurück. Das Schöne ist eben,
wenn man mehrfach Vererbung systematisch unterstützt,
indem man für die generischen Funktionen Hilfsfunktionen vorsieht, die sagen,
wie man das, was alles an Methoden da ist,
sinnvoll kombinieren kann, dann kann man damit sehr elegant programmieren.
Was sie an Methodenkombinationen haben,
das ist einmal das Plus oder List oder Minimum,
Maximum erpennt, ja,
Beginn end oder off
für logische Werte
Wenn sie übermütig werden, können sie sich selbst ihre eigenen
Methodenkombinationen definieren und damit das dann für ihr Klassensystem machen.
Ja, damit möchte ich mich für dieses Jahr von innen verabschieden.
Ich wünsche Ihnen frohe Weihnachten, ein glückliches neues Jahr
und wir sehen uns dann im nächsten Jahr wieder.