Was sind zu der Art, wie wir den Rechner sehen,
dann auch hingehen und uns passende Programmiersprachen ausdenken, die uns ermöglichen,
es dem Rechner in klaren, verständlichen Worten zu sagen,
die zu der Struktur des Verarbeitungsmodells passen.
Und wenn ich mich recht erinnere, haben wir damit geendet,
dass Sie gesagt haben, dass es wichtig ist,
in der Ausbildung mehrere Verarbeitungsmodelle kennenzulernen, damit man erkennt,
dass es nicht nur eine Sicht der Welt gibt.
Und wenn wir eben immer nur imperativ gelernt haben,
wenn auch in der objektorientierten Art,
dann wird für uns eben jedes Problem so aussehen,
als müsste man es imperativ lösen.
Und das eine Werkzeug, was wir kennen,
den Hammer, wenn er nicht da ist,
werden wir jedes neue Werkzeug vergewaltigen und wir einen haben ja benutzen.
So, jetzt wollte ich heute dazu übergehen,
dass wir uns einmal für das Funktionale Verarbeitungsmodell ein bisschen die Sprache recket vornehmen.
Heute vor allem die Syntax. Und dann werden wir vorbereiten,
dass wir jetzt nächstes über die Semantik reden.
Gebe ich nicht. Ich glaube,
ich hatte das letzte Mal noch nicht die Bücher angesprochen,
die wir die zurückgeht, empfehlen kann.
Das eine ist ganz klar von Martin Felleisen und seinem Team
das Buch How to Design Programs and Intraduction to Programming.
Das sind die beiden Personen, die das Recket-Team anführen und
den Entwurf der Sprache mitbestimmt haben. Also wenn überhaupt jemand weiß,
jemand über diese Sprache redet, dann die beiden,
also das ist ein Lehrbuch abgestimmt auf die Programmiersprache,
was einem die grundlegenden Konzepte ganz gut erklärt und es passt auch wunderbar zu den Beispielen,
die man in der Recket-Entwurfs Umgebung findet.
Das andere ist ein absoluter Klassiker, den man
in der Informatikausbildung einfach gelesen haben muss.
Das Buch von Abless und Sessment Incessment, Structure and Interpretation
of Computer Programs. Das war nämlich das Team,
was sich den Vorgänger Scream ausgedacht hat und erklärt hat,
was die essentiellen Berechnungsmodelle in einer funktionalen Programmiersprache sind.
Es gibt inzwischen viele neuere Bücher,
aber keiner hat es wirklich so schön gesagt wie das Team
und ist so gut und anschaulich und lebendig beschrieben
Also den Öbels Interestment verpasst zu haben,
Informatikstudium ist wie im Deutschunterricht nicht Goethe gelesen zu haben.
So als Vergleich etwa. Das ist eben die Literatur,
die dazugehört. Für diejenigen,
die den Theoretischen Hintergrund der Funktionalen Programmierung auskosten wollen,
kann ich das Buch von Word and Wodler empfehlen.
Das entstand etwa um dieselbe Zeit, wie der Ebels und Sussman,
aber nicht aus der Sicht des Software-Engineering und des Programmentwurfs geschrieben,
sondern aus der Sicht der formalen Grundlagen.
Wie beweise ich das, ein Programm korrekt ist?
Und ich habe aus diesem Buch
einige Beispiele übernommen
Ja, und sie zuerst nach Kommen löst, dann das Geben,
dann erreckelt übersetzt und sie ihn zusammengestellt in eine Bibliothek,
ein Modul, was sie in Rackett einbinden können,
dass diese Beispiele enthält. Der einzige Nachteil,
den ich über das Buch von Bord und Wattler sagen kann,
die sind in der Sprache, die sie benutzt haben,
voll auf die Miranda Häskel-Welt abgefahren.
Und das sind Beispiele, die besonders gut funktionieren,
wenn man Sprachen mit einem Typkalkül hat.
Ja, dazu passt es wunderbar. Also die gegenseitigsten E-Beziehung-Essessment. Ja,
und dann gibt es ein sehr gut verständliches deutsches Buch von Wolf,
Manfred Lippe, auf Deutsch geschrieben für diejenigen,
die ihre Lehrbücher gerne auf Deutsch haben.
Es ist richtig, es ist korrektes Stehen,
die wesentlichen Sachen drin, alles gute Punkte.
Ich finde es nur entsetzlich dröge, wie eigentlich die meisten
deutschen Lehrbücher sind. Es fehlt einfach die Lässigkeit,
Lockerheit, der Charme und so ein bisschen das Spielerische.
Der befindet selten von deutschen Autoren Lehrbücher,
die spielerisch sind und irgendwie die Freude an dem Stoff erwecken.
In der zweiten Semesterhälfte,
das hatte ich Ihnen ja versprochen oder angedroht oder angekündigt,
wie Sie es sehen wollen,
wollen wir über objektorientiertes Programmieren im Funktionalen Programmierstil reden
Und der kann ich zwei sehr gute Bücher empfehlen.
Die erklären die Essenz des funktionalen Objektorientierten Programm ja uns wunderbar an schönen Beispielen.
Ich habe aus diesen Büchern die Beispiele wieder übernommen,
aber sie sind eben geschrieben für die Sprache Common Lisp.
Beide. Einmal von Sonja Kini, die hat in dem Team mitgearbeitet,
durch diese Sprache Zehlers kommendes Object System ausgedacht hat.
Und das sind wirklich fantastische Beispiele. Ich werde sie
Ihnen eingebettet in Recket erklären, sodass sie das nachvollziehen können
Und die Kurzfassung von dem reduziert auf ein Kapitel,
also ungefähr das, dass man in zwei Stunden Vorlesung unterbringen kann,
steht im Buch von Graham.
Sie kommen, da ist dieser Objekt Standard auch sehr gut erklärt.
Ja, der letzte Teil. Aber wir werden ja auch
über den relationalen Programmierstil reden und die Bücher, die sich dafür eignen,
ist einmal der Klocksinn und Malish Programming in Prolog.
Dann wird wirklich gut erklärt, wie man relational entwirft und eben
auch die Erweiterung der Sprache pro Log, sodass man es effizient machen kann.
The Art of Prolock von Sterling and Shapiro, ist auch sehr schön.
Aber der erste Teil passt deutlich besser zu dem Vorlesungsteil,
dem Wolfgang Menzel macht. Also wenn jemand beide Teile hört,
würde ich sagen, wenn sie hiermit mit dem,
was sie über Wolfgang lernen, ohnehin vollkommen bedient und gut versorgt.
Ich selbst werde den Teil, der sich auf Prolock und das relationale Programmieren bezieht,
an einem anderen Buch erklären, nämlich von Peter Norweg,
der hat in diesen wunderbaren Buch.
Viele, viele Beispiele zusammengestellt, Fallstudien. Wie mache ich,
wie löse ich typische Entwurfsprobleme im funktionalen Programmierstil? Und die Beispiele,
die sich für Drittsemestervorlesungen eignen,
habe ich rausgenommen und neue geschrieben nach seinen Vorlagen in Reckett und unter anderem eben auch seinen Prolog in Turbritter,
den er entkommen lässt, beschrieben hat in dem Buch,
habe ich neu geschrieben, erst in Skim,
dann in Reckett und wir werden dann in unserer eigenen eingebetteten Programmiersprache Ruhlock Racket,
das ausprobieren können.
Aber die Beispiele mit allen schönen Erklärungen stehen in diesem Buch.
Also wenn sie nachlesen wollen, wie sie ausgedacht wurden,
wie es funktioniert und vor allem neugierig sind,
wie die Implementation funktioniert, schauen sie sich das um. So,
und als Notfall, wenn hier irgendjemand nach zwei Semestern Jahr waren,
vielleicht auch Imperativen programmieren in der Schule,
solche Knoten im Gehirn hat,
dass man einfach keinen Zugang zu funktionalen Denkweise findet,
dann gibt es hier noch eine sehr sanfte Einführung,
mit wirklich mit den allersimpelsten Beispielen
The Little Skimer,
das habe ich hier gar nicht auf der Folie stehen,
aber das erklärt wunderbar, wie man überhaupt den Einstieg findet.
Wenn man das gepackt hat, klappt alles.
Und dies hier ist ein weiteres Buch zum relationalen Programmieren,
so Rlysonskrim. Okay. Dann, ja, hier haben,
ach so, haben wir Friedmann Felleisen, The Little Skrimer.
Also viele, viele kleine Beispiele, einfach so zum Üben.
Und damit sollte es einfach klappen. Ja. Gut.
Dann findet man natürlich alles Material auf der Racket-Langorg-Homepage.
Da sind Verweise auf die Lehrbücher, da können sie interaktiv
die dazugehörigen Lehrbücher lesen
Finden sie die Handbücher und so weiter. Und können sich für andere Plattformen herunterladen.
Racket für PC, gar kein Problem. Hatte ich das letzte Mal schon gesagt,
wenn sie auf einem Mac arbeiten,
verwenden sie bitte direkte Version 601 und nicht 6-1. 6-1 läuft nicht,
wenn sie ihren, wenn sie zu denen gehören,
die sofort auf jedem Bandwagon samten.
Und das neueste System installieren mit Your Semity funktioniert 601 noch nicht.
Also Mac-User bitte nur bis 6-01 gehen.
Jan. Meine Webpage haben die meistens schon gefunden und haben auch entdeckt,
dass die ziemlich langsam reagiert im Moment,
dank der Account, die da drauf sind.
Ich habe heute nachts sämtliche Count da runtergeschmissen,
also meine Webpage sollte wieder etwas schneller sein.
Aber ich werde trotzdem ab der nächsten Woche alle Übungsaufgaben schlichtweg
auch in Stine bei der Vorlesung einhängen, dass sie solche Sachen dort herunterbekommen.
Nur eben mein Sript bitte direkt von meiner Homepage runterladen,
weil das ist so groß, dass Max Gine nicht.
Okay, und ich hoffe, ihre Übungsleiter haben ihnen alle verraten,
unter welcher E-Mail sie zu erreichen sind,
nochmal für meine Gruppe
Bit zu erreichen und der Dreschler-Informatik und die Hamburg.de.
Bitte bis Montagmittag, die Übungsaufgaben abgeschickt haben per E-Mail.
Wenn Sie es in Record öffnen,
Ihr Programm bitte nicht die Kommentarboxen verwenden, wenn Sie das tun,
wird kompilierter Record-Code raus und es kann sein,
dass ich es dann nicht öffnen kann.
Oder wenn Sie es weiterschicken. Also schlichtweg,
Kommentarboxen vermeiden, so schick, wie Sie auch sind,
damit Ihr Bracket-Programm
eine simple Textdatei bleibt
Okay. Diese Tabelle ist noch vor dem letzten Jahr,
ist aber nicht so wichtig, worauf es mir ankommt, ist diese Spalte hier.
Wir haben für die Übungsaufgaben die Strategie, je später das Semester,
desto mehr Punkte gibt es für die Aufgaben, soll dazu führen,
dass sie sich motiviert fühlen gegen Ende des Semesters,
auch noch Aufgaben zu bearbeiten, ja.
Weil der Stoff in der zweiten Hälfte ist einfach der Wichtigere.
Also im Moment machen wir die Grundlagen,
Klingerübungen, wie schreibt man ein Programm und so weiter.
Das zeigt man nicht, ob sie das Wesentliche verstanden haben.
Wenn sie hiervon ein paar Aufgaben gelöst haben,
dann haben sie kapiert,
um was es in diesem Semester geht und deshalb gibt es
mehr Punkte für die Aufgaben weiterhin
Okay. 175 Punkte sollten sie bekommen für die Klausurzulassung.
Und man regelmäßige aktive Teilnahme, Anwesenheit 85 Prozent,
also nicht bei jeder Übung, nur zu 85 Prozent Dasein,
sondern Termine gemittelt, ja.
Und ich hatte ja schon gesagt, wenn Sie gute Gründe haben,
dass Sie nicht kommen können, die erklären Sie es mir,
dann werden wir einen Weg finden, wenn es studienbedingt ist oder so.
Ja, jeder sollte, jeder und jede sollte zweimal
eine Lösung vorgestellt haben
Das ist wichtig, weil wir wünschen,
dass sie im Team arbeiten und wenn wir die Teamlösungen kriegen,
ist es schlecht,
wenn eine Person im Team immer der Sprachführer für die Gruppe
ist und von den anderen bis zum Ende des Semesters nicht mal die Stimme einmal gehört hat.
Also jeder, jede Bitte einmal zweimal vortragen und sie können auf ihre Zettel auch draufschreiben,
wenn sie finden, sie haben das richtig gut gemacht,
dass sie das Blatt vorstellen wollen.
Also ich habe die Übungshelferinnen und Übungshelfer gebeten,
dass sie darauf Rücksicht nehmen und wenn sie sich auf irgendwas richtig gut vorbereitet haben,
sie dann auch vorzugsweise für diese Aufgabe aufrufen.
Ja, also Übung macht den Meister. Die Übungsaufgaben sind nicht als Pflichtübung da,
sondern ich versuche, die Übungsaufgaben so oft zu setzen,
dass wir in den Übungen genau das üben,
was hinterher in der Klausur drankommt.
Zum einen, ja. Und dass sie die Dinge üben,
die jeweils das, was in der Vorlesung dran war,
gut erhellen, sodass sie es fremd nacharbeiten können.
Also so sind die Übungen gedacht. Nun werden sie merken,
es sind nicht immer simple Aufgaben, schreiben sie ein Programm,
was irgendwie auf der Ebene der Programmierung,
den er zusammenzählt,
sondern ich versuche mir Anwendungen
Auszudenken. Also haben wir im täglichen Leben irgendwas begegnet und denken,
das könnte man mal ausrechnen, dann mache ich daraus eine Übungsaufgabe,
sodass es in der Textaufgabe verkleidet ist.
Da ich gerne Sirgle werden, also recht viele Aufgaben,
sich aus dem maritimen Bereich finden, wie man sie so,
wenn man über Atlantik segelt, eben mal machen muss.
Aber egal, was es ist,
wichtig ist für sie, dass sie lernen,
es gibt da ein Problem aus der realen Welt beschrieben,
was ist die Aufgabe, die dahinter steckt,
die ich programmieren soll und das Problem erstmal aus der Aufgabe rauszunehmen.
Und üben, üben, üben. Also sie werden durch die Klausur nicht durchkommen,
wenn sie nicht wirklich Selbst programmiert haben während des Semesters.
Also, wenn sie im Team die Sachen erarbeiten und sich hinterher erklären lassen,
was andere gemacht haben, das wird absolut nichts in der Klausur.
Das kann ich Ihnen so schön sagen, ja.
Sie müssen sie selbst gemacht haben, weil bedenken Sie bitte
in der Klausur, haben Sie keinen Computer dabei?
Sie haben keine Umgebung, die Ihnen die Syntagsprüfung macht.
Sie müssen in der Lage einfach mit einem leeren Blatt Papier
einen Stift in der Hand nehmen, müssen in der Lage sein,
ein Programm zu schreiben.
Aber wir lernen es halt nicht nur,
damit sie die Klausur bestehen können,
sondern dass sie später interessantere Sachen im Masterstudium oder in
späteren Vorlesungen darauf aufbauend machen können
Okay. Peter Norwegg hat es sehr schön gesagt, das ist das Buch,
was ich als Muster für die Fallstudie mir genommen habe.
You were never become profisioned in a further and language,
by studying the capulary lists. Rather, you must year
and speak or read and right, the language to gen profisions.
The same is two for learning computer landuages. Klar,
also wenn wir einfach immer nur die Syntax auswendig lernen und
die Regeln kennen, mit denen man zusammenbaut,
aber nie sehen, wie man typische Probleme damit löst,
dann haben wir die Sprache nicht verstanden
Okay, das haben wir alle schon. Mit Klausur reden
wir das nächste Mal. So auf meiner Webpage finden Sie
dieses Modul hier. Asset ribe, bip, sip. Ja,
das ist ein komprimierter Pfeil, in dem die Beispiele,
die ich hier im Skript habe,
als Recket Code drin sind, wo die Module drin sind,
die man verwenden kann und so weiter.
Also installieren Sie sich das Ding. Ja, hier kommen
wir mal zur versprochenen Sprache Recket. Wir wollen ja schließlich
auch mal benutzen. Das Wichtige ist, dass wir hier
ein System vor uns haben, das zwei Kernbausteine hat.
Das eine ist der Evaluator, wo der Evaluator,
wenn das lateinisch sagen wollen. Das ist ein Baustein,
der im Hintergrund läuft und läuft und läuft und darauf wartet,
dass wir einen Ausdruck reinschreiben.
Das Programmieren in Recket besteht da drin,
dass wir einen Ausdruck formulieren, einen funktionalen Ausdruck.
Und die Auswerteumgebung nimmt in sich vor, macht ein Parsing,
analysiert die Syntax, ermittelt die Bedeutung und führt das Ding aus.
Und dann haben wir eben die Programmierumgebung, wo wir Programme laden,
übersetzen, ändern, wo wir Hilfesysteme haben und so weiter.
Fehleranalyse, also Recket ist von einem Team entwickelt worden,
was für die Lehre da ist. Und die haben sich
große Mühe gegeben, die Syntagsanalyse so zu machen,
dass wenn immer möglich sinnreiche Fehlermeldungen gegeben werden können.
Grundidee beim Funktionalen Programmieren. Wir haben hier einen Auswärter,
der kann funktionale Ausdrücke verstehen. Wir geben Werte einsetzen,
bauen, zusammengesetzte Ausdrücke und wenden auf unsere Ausdrücke weitere Funktionen an weitere Funktionen an und so weiter.
Das ist wie ein Taschenrechner, Ausdruck rein, Wert raus.
Der Wert, der uns gegeben wird,
ist das Ergebnis der Berechnung
So, wir starten Dr. Reckett, indem wir entweder Reckett oder Dr.
Reckett eintippen hängen von dem System ab, in dem sie sind.
Am Macintosh klicke ich einfach auf das Recket-Icon im Doc.
Und dann sehen wir so ein Fenster in der oberen Hälfte können wir Programme editieren.
In der unteren sehen wir, was beim Auswerten geschieht.
Die unsere Version sagt uns immer, welche Version das ist.
Aber wenn ich die Beispiele im Skript habe, habe ich mich bemüht,
im Skript immer auch noch die Versionsnummer dazu zu geben,
mit denen es gerechnet ist.
Also wenn sie trotz mehrfachen Programmierens feststellen,
ihr Recket sagt ihnen
was anderes
Und sie sind sich sicher, ihr Programm ist richtig,
vergleichen, sind mal die Versionsnummern, es kann sein,
dass die neueste Version, die ich noch nicht getestet habe,
wieder was anderes draus macht, ja, nur so mal als Tipp.
Gut, ein Recket-Programm sollte damit beginnen, dass wir am ersten,
als erstes reinschreiben, welche der vielen Recket-Sprachen wir meinen.
Das System hat einen großen Vorrat entsprachen, unter anderem Lehrsprachen.
Und wenn wir in den Quelltext reinschreiben,
in welcher Sprache das gelten soll, ja,
also bitte, das ist Französisch, das ist Englisch,
das ist Latein, ja, dann weiß der Rechner,
in welcher Sprache er es auswerten soll.
Und hier, Kommentar beginnen wir mit allem Simikolern oder mehreren.
Es hat sich in der Listwelt eingebürgert,
dass man die Bedeutung eines Kommentars, die Wichtigkeit damit unterstreicht,
mit einer zunehmenden Zahl von Simikolerns am Anfang.
Also ein Hauptkommentar, der das Programm erklärt,
da würde man gleich Reisemikolerns machen, ja. Ein Kommentar,
der so am Ende der Zeile ist und nur sagt,
Achtung, ein Bugfix, hier habe ich etwas gemacht,
was nicht zu verstehen ist, aber das ist eine kleine Anmerkung.
Wichtige Kommentare zwischen Funktionen würde man zwei Simikolerns machen.
Aber eins reicht der Mützensemikolern ist
Ja, und dann besteht ein funktionaler Ausdruck,
dass wir darin hier entweder ein Schlüsselwort am Anfang
sagen oder den Namen einer Funktion und dann die Argumente.
Hier habe ich die Funktion und das Argument, ein String,
Hello Recket World und wenn wir das ausführen,
wir klicken hier auf den Start, knopft,
dann sehen wir hier unten Hello Recket World.
Das ist relativ einfach. Also im Top-Level haben wir
im Hintergrund immer diesen Evalue-Itator laufen,
der die funktionalen Ausdrücke aus dem Fenster unten übernimmt und
oben können wir die Programme vorbereiten
Gucken wir nochmal auf die Sprachen. Also ich sagte schon,
es sind viele Sprachen angebaut und das Zweite,
was sie checken sollten, wenn sie merken,
dass ihr Programm total andere Ergebnisse gibt als das,
was sie im Skript finden, vergleichen sie,
ob sie dieselbe Sprache benutzen.
Die Lehre sprachen, sind gestaffelt nach Anfänger, Anfänger mit Vorkenntnissen,
Fortgeschrittene oder ganz allgemeine Sprache. Und wenn ihnen,
egal was sie schreiben, eine Fehlanmeldung kommt,
das ist falsch, dann könnte es sein,
dass sie aus Versehen sich geoutet haben,
als Beginning Student und eine Anfängersprache genommen haben,
in der
alles verboten ist
Also die Anfängersprachen sind so behütend wie der Kindergarten.
Man darf kein Messer in die Hand nehmen und nicht Auto fahren und nichts.
Also alles, was Spaß macht, ist abgestellt.
Und deshalb werden also ab der dritten oder vierten Vorlesung
die Beispiele in diesen Beginnersprachen überhaupt nicht mehr funktionieren.
Also stellen Sie es so ein, dass Sie eine,
dass Sie die Sprache haben, in der steht,
im Quelltext angegebene Sprache.
Dann sind Sie auf der sicheren Seite. Aber das Einschränken
auf Anfängersprachen hat den entscheidenden Vorteil, dass die Syntax-Analyse einfacher ist.
Denn wenn alles komplizierte verboten ist, dann werden Sie eben
sinnvolle Fehlermeldungen kriegen. Wenn da irgendetwas passiert, Ja,
und später werden wir die Sprache Zählers kommen,
das Abschüttsystem-System verwenden und so weiter.
Und die finden sich unter Legacy-Languages, ja. Auf Deutsch heißt das
total unscharmant Altlastsprachen. Also ich empfinde sie keineswegs als Altlast.
Gut, also am Ende des Semesters nehmen wir dies jetzt.
Swindle. Ja, Fullswindel. Gut,
das Einstellen der Sprache,
wir nehmen aus dem Hauptmenü hier oben Sprache einstellen und dann
wählen sie bitte hier das erste Häkchen im Quertext
angegebene Sprache benutzen,
Zeile mit lang
Weiter unten finden sie die Sprachen, die genau zu den einzelnen Lehrbüchern gehört.
Also wenn sie nach einem der Lehrbücher üben wollen,
dann gehen sie in den Bereich. Okay, ja,
jetzt gucken wir mal in das unterste Fenster und geben unsere
ersten Wissausdrücke ein. Letztendlich die erste Übung ist tatsächlich,
wir nehmen es wie einen Taschenrechner, das haben sie,
glaube ich, allesamt jetzt während der Woche schon in ihren Übungen ausprobiert.
Machen wir es nur noch mal im Zusammenhang für alle,
dass wir auf demselben Stand sind. Also wenn wir Konstanten haben,
die wird der Evaluator zu sich selbst evaluieren, da kommt derselbe Wert zurück.
Eine Zahl 4 eingeben wird mich plötzlich zu 3,9 berechnet,
ja, sondern der Wert von 4 ist 4. Wenn wir,
Bestandenheit, Bibliotheksfunktionen nehmen, dann wird gerechnet,
wie man es erwartet, Exponent, das hier steht,
also nehme Basis 2, Exponent 4, kommt 16 raus,
ein Sinus von 1,5 und ein bisschen kriegen wir eins raus,
ja, ich habe ja versucht,
hier Pi halbe einzugeben.
Zusammengesetzt, Ausdrücke können wir auch machen, wir können Ausdrücke
beliebig für Tiefschachteln und sie sollten sie auch schachteln.
Da ist ein Teil des Spaßes,
das möglich ist
Man sieht hier jetzt schon, wir haben Prefix-Notationen,
auch für Operatoren, die sonst binden.
Binär sind, ja, links, rechts,
ein Argument wie Plus oder Minus. Wir schreiben das,
ob den Apparator brav und den Anfang und dann dahinter die Argumente.
So, Fehlermeldung, früher sahen sie niedlicher aus,
also in den ersten Recket-Versionen kriegte man,
damit die Fehlermeldung eigentlich so hart trifft, immer noch einen freundlichen Glückskäfer dazu.
Das haben sie jetzt abgestellt. Ich habe den immer noch drin,
einfach, um zu zeigen, okay,
hier ist die Fehlermeldung.
Weshalb ist ich jetzt unten, steht leider schon die Lösung.
Weshalb ist denn die ein Unknown Identifier? Das kann ihnen
ziemlich leicht passieren, wenn die Blenktaste klemmt oder so.
Sie wollen mal zwei schreiben und dann übersehen, dass hier das Leerzeichen fehlt.
Dann haben sie hier den Namen einer Funktion eingegeben mal zwei.
Und wenn die undefiniert ist, eine Verdoppelfunktion, haben sie
Pech gehabt. Dann gibt es die Fehlermeldung. Ja,
also Reference to undefined Identifier, dann das sollte für sie
das Glöckchen klingeln lassen, hoppla.
Ich habe hier wahrscheinlich ein Leerzeichen vergessen oder ich habe mich
irgendwie in dem Namen vertippt.
Oder? Wir bekommen die Fehlermeldung, Reference to Ungefind Identifier,
wenn die Variante nicht definiert ist. Je nachdem,
in welcher Sprache wir sind, ist die konstante Pi nicht vordefiniert.
Also können wir dann Pi mal Daumen nicht rechnen.
Und Sie sehen schon, vermutlich ist Daumen auch unbekannt,
aber die Fehlermeldung kriegen wir schon, wenn das Pi nicht bekannt ist.
Okay, wenn wir jetzt versuchen, Modulot zu rechnen,
zwei Modulot 2.3. Ja, denn sie bekommen wir typbezogen,
eine Fehlermeldung.
Also das sind Sachen, die sind in jeder anständigen Programmiersprache
erwarten,
die Datentypen kennt
Okay. Wie dürfen wir symbolische Ausdrücke schreiben?
Also entweder atomar Reformen zahlen, Zeichen, Symbole,
Wahrheitswerte, die werden zu sich selbst ausgewertet.
Die haben einen konstanten Wert. Die Form besteht immer darin,
Klammer auf, Name der Funktion und dann dahinter eine Liste
von weiteren Ausdrücken und die Zahl der Ausdrücke,
die da stehen, sollte zur Ständigkeit der Funktion gefahrene passen.
Also wir können schreiben,
kleiner ist Quadratwurzel aus vier
Kleiner als Quadratwurzel aus 5 und dann kriegen wir einen Wahrheitswerk zurück
und wir sehen ja auch schon, wie Wahrheitswert in Record aussehen.
Das ist die Session-Zeichen und dann ein Tee dahinter.
Und Wahrheitswert falsch ist mit dem F dahinter.
Kleine Vorschau auf die Klausur. Wenn Sie da so
ein Beispiel finden, was ist der Wert dieses Ausdrucks?
Und Sie sollen das damit beantworten, indem Sie erstens erkennen,
dass es ein Wahrheitswert ist und dann zweitens richtig True oder False angeben.
Es gibt Spezies, die dann immer einen Kompromiss zwischen T
und F hinschreiben. Und also ich würde sie bitten,
sehr deutlich zu machen durch Häkchen
unten oder oben
Ob das ein True oder ein False sein soll, ja?
Wenn es uneindeutig ist, nämlich immer an, dass der Wert falsch war.
Nicht, dass er das jetzt Richtige gemeint haben.
Jedenfalls in der Klausur. Also deutlich schreiben. Ich fand
es Anfang an angewöhnen, ordentliche Häkchen beim T&F,
damit wir sehen, welcher der beiden gemeint ist.
Nicht einfach nur ein Kreuzchen. Nur die Werte,
die für so einen Ausdruck zurückkommen, die können jetzt beliebige Datenstrukturen sein, ja?
Zu Anfang werden wir es im Wesentlichen mit Symbolen,
Buchstaben und so zu tun haben.
Aber ziemlich bald übergehend zu listen. Unser Hauptarbeitspferd für die
meisten Beispiele werden Listen sein
Seltenes Trinks. Damit haben sie Java genug geübt. Trinks
werden wir ziemlich vernachlässigen, aber im Wesentlichen mit Listen arbeiten.
Und vor allem Funktionen. Also unsere Hauptaufgabe wird drin bestehen,
Funktionen zu schreiben, die Funktionen erzeugen und weitergeben und organisieren.
Tabellen von Funktionen aufstellen, um irgendwie Actionhändler oder sowas in Tabellen zu organisieren.
Also für solche Sachen werden wir Datenstrukturen verwenden. Nun,
Sie haben schon gesehen, es kommen ziemlich viele Klammern vor
Hatte einen schönen Vorteil dann mit der Klammerung,
ist immer klar, wenn ein Ausdruck beendet ist.
Und wir können eben typische Infix-Operatoren so verwenden, dass sie viele Argumente bekommen.
Das ist in, ja, war ein bisschen schlecht,
aber im Recket können wir schreiben, plus eins,
plus eins, zwei, plus eins, zwei,
vier, so bis zu 200 habe ich es mal ausgereizt,
das geht locker.
Genauso bei der Multiplikation. Und wir können sogar das letzte Argument auch noch weglassen,
wenn es Sinn macht und einen sinnvollen Default gibt.
Wenn sie einfach nur das Plus klammern,
ist der Wert null
Wenn sie einfach nur das Mahlzeichen klammern, ist der Wert eins.
Warum diese Unsymmetrie ist doch verwirrend? Warum kommt nicht immer null raus?
Ja, bitte. Genau. Also diese Operatoren sind so ausgelegt,
dass wenn gar nichts als Argument angegeben ist, das neutrale Element genommen wird.
Und bei der einen ist es eben so,
dass man sich still und heimlich denken kann,
das steht als nächstes Argument.
Die Null als neutrales Element. Und hier wäre es
neutrale Elemente eins
Und wir haben keine Operatorpräzedenzen zu lernen. Ja, das ist auch
ganz praktisch. Ich weiß, als ich angefangen habe,
in Seed zu programmieren, das war wirklich eine Qual,
die ganzen Operatorpräzedenzen, wo die ganzen Apparatoren auswendig zu lernen.
Und dann hatte das Lehrbuch noch so hilfreich gesagt,
also was jeder C-Programmierer macht, ist,
sich an den Spiegel einen Zettel kleben, mit der Tabelle der Operatorpräzedenz,
dass man morgens beim Rasieren eben im Spiegel sieht und die Präzedenzen auswendig,
Lernkart-Z sinnvoll nutzt.
Also rasieren wir bei mir nicht so gegeben,
morgens am Spiegel,
mussten einen anderen Weg finden
Also in der Listwelt haben wir damit überhaupt kein Problem.
Es gibt keine Opparate der Präzedenz. So. Okay. Jetzt
für die Notation von Beispielen. Also wenn ich hier irgendwo
so etwas im Skript stehen habe, heißt das,
hier ist der Eingabefront von Dr. Racket und hier steht,
was ich reingegeben habe. Und wenn es ausgewertet wird,
habe ich so einen Pfeil gemacht und dann kommt hier das Ergebnis.
Das Fall soll bedeuten, evaluiert zu.
Ja. Okay. Hier nochmal einfach für die simpelsten Ausdrücke,
die sie jetzt wahrscheinlich während der Übung auch schon geübt haben,
also im Plus mit zunehmend eskalierender Zahl an Argumenten,
plus eins, gibt eins, plus ohne irgendetwas gibt uns die Null.
Und dann haben wir hier jetzt mal eine Vergleichsoperation.
In den meisten anderen Programmiersprachen mit Innenfix-Notationen ist das auch ein
Operator, der von links und rechts bindet.
Normalerweise, in Recket können wir bei den relationalen Operatoren
hier auch gleich die ganze Liste der Argumente hinterschreiben.
Und das hier heißt, es ist eins, gleich eins,
über vermutlich ja, gleich zwei, minus eins.
Oder ist eins kleiner, dreit, kleiner, fünft,
kleiner, sieben, Das heißt,
wir können auf diese Weise ganz locker und lässig für eine lange Liste von Werten überprüfen,
ob sie aufsteigend oder absteigend sortiert ist,
indem wir das so schreiben.
Gut. Jetzt haben wir hier einmal umgeschaltet auf die Sprache
Anfänger. Und da passiert Ihnen genau das.
Also wenn Sie bei diesen Babysprachen geblieben sind,
dann kriegen Sie hier schon die freundlichen Fehlermeldungen.
Happla, eine Addition erwartet, ein zweites Argument.
Deshalb immer auf die Zeile Sprache achten,
wenn Sie hier Beispiele im Skript sehen
Und dann möchte ich sie bitten, dass sie frühzeitig beginnen,
sich ein Thema zu überlegen, wie sie ordentlich einrücken.
Damit man bei geschachteten Ausdrücken sofort sieht, was wie geklammert sein soll.
Es hilft Ihnen, auch wenn sie es so einrücken,
wie sie meinen, dass es eingerückt sein sollte,
wenn Fehlermeldungen wegen der Klammer kommen, dass irgendwo eine Klammer fehlt,
dann sehen Sie auf einen Blick, wo sie fehlt.
Wenn Reckett da eine andere Klammerstruktur hinter vermutet.
Also Ding Argumente, die auf gleicher Stufe stehen,
schreibt man am besten direkt untereinander Operatoren,
die auf der gleichen Stufe stehen, direkt untereinander.
Es macht es
leichter zu programmieren und hinterher auch wieder zu lesen
Also zum Beispiel, wenn wir hier einen Ausdruck schreiben wollen,
ist denn Wurzel aus fünf größer Wurzel 4 oder Wurzel sechs Größe oder Wurzel 7,
ja, dann würden wir es eben so schreiben, oh,
dann der erste Ausdruck hier eingerichtet und die eingerückt und der zweite Ausdruck,
der auf derselben Eindruck, ja,
Schachtelungstiefe im Ausdruck ist genauso weit eingerückt.
Wenn Sie sowas abgeben, dann kann es auch sein,
dass Sie Ihre Übungshelfer, die die Aufgaben korrigieren müssen
in eine unfreundliche Stimmung versetzen und also im Interesse aller,
die Ihr Programm lesen sollen,
benutzen Sie die automatische Eindruckfunktion
In Reckett. Die hat das im Sprachemenü steht drin.
Gibt es einen Thermen, wo sie alles einrücken können?
Und dann macht Reckett es für sie. So. Kommentare,
ganz wichtig. Denn Anfang ihres Programms beginnen Sie bitte mit
einem solchen Kommentarblock. Hash, senkrecht, der Strich,
senkrecht, der Strich, was dazwischen steht,
über viele Zeilen weg wird, als ein einzelner Kommentarblock gelesen.
Und damit können wir zu Anfang eben den Textteil der Aufgabe beschreiben,
nicht viele unserer Aufgaben beginnen, damit entwerfen Sie ein Programm.
Begründen Sie Ihre Datenstrukturen und so weiter.
Da schreiben Sie bitte einfach alles am Anfang Ihres Programms
zwischen diese Kommentare
Tatsache, entsteht es direkt beim Code.
Ja? Das müssen wir nicht unbedingt toll formatierte Wortdokumente abgeben.
Das Wichtigste ist, dass im Kommentar vorne drin steht,
wer hat es programmiert, warum, zu welcher Aufgabe gehört das?
Und dann eben den Entwurfsteil, ne? Sie können im
Special-Menü Kommentarboxen einfügen, aber das hat sich nicht bewährte,
man das per E-Mail weiterschickt und der Nächste es auf einen anderen Rechner öffnen muss.
Ja, es kann sein, dass die Binär-Version inkompatibel sind.
Gut, ja, Sie haben auch schon, denke ich,
diese Woche geübt, wie wir denn Funktionen definieren können.
Solange wir nur die vordefinierten Funktionen verwenden können, haben wir
keine allgemeine Programmiersprache. Es wird zu einer allgemeinen Programmiersprache,
in dem wir beliebige eigene rekursive Funktionen definieren können.
Und die einfachste Art, eine Funktion zu definieren,
besteht darin, dass wir sagen, die fein.
Und jetzt definiere ich, was meine Funktion angewendet auf Argumente
tun soll. Also hier schreibe ich hin,
denn meine Funktion, die ich gerade definiere,
ein Argument Exit, was soll es bedeuten und das,
was es bedeuten soll, steht hier drunter,
es soll gerechnet werden,
dieser Ausdruck
Und es wirkt eben so,
dass was immer wir hier für X übergeben,
ausgewertet wird, vorher berechnet wird und dann eingesetzt wird,
wo überall hier ein X vorkommt.
So ist diese Art, eine Funktion zu definieren, zu lesen.
Recket hat eine zweite, über die reden wir noch.
Sieht eleganter aus, aber macht vielen Schwierigkeiten. Und das werden wir
jetzt uns anschauen, wenn wir über funktionale Abstraktionen ganz allgemein sprechen. Okay,
also bei Funktionen denkt man bei der Mathematik vor allem erstmal
an Funktionen in Zahlen und die sehen dann eben 1,
2, 3, 4 dimensional so aus,
dass wir einen Raum haben,
über dem Werte berechnet werden oder so.
Solche Funktionen können wir in der Tat auch in Recket definieren und zeichnen und schreiben.
Ja, das ist gar kein Problem. Aber viel wichtiger sind Funktionen,
die andere Datenstrukturen errechnen, mit denen wir andere Funktionen errechnen,
mit denen wir Programme erzeugen können.
Und der Weg dahin ist die Funktionale Abstraktion und das erste besteht daran,
dass wir Berechnungsschritte verbergen,
indem wir Teilen der Berechnung einen Namen geben und dann
nur noch abstrakt den Namen dafür verwenden.
Da gehen wir zuerst mal drauf ein
Wenn wir uns jetzt anschauen, wie wir überhaupt arbeiten in diesem mathematischen,
im Verarbeitungsmodell, das auf dem mathematischen Funktionsbegriff basiert.
Also zum einen haben wir Grundfunktionen, da haben wir schon
ein paar gesehen, wie eben die argnetischen Funktionen,
die immer da sind, größer, kleiner Vergleiche.
Dann brauchen wir aber auch Mittel, um Therme zu ausdrücken, zu kombinieren.
Das werden in dem Fall wieder Funktionen leihen. Aus der Java-Welt kennen Sie,
dass man Dinge kombiniert, indem man Ja,
Methoden schreibt oder indem man Blöcke hat mit Beginn entgeschachtelt, ja.
Hier wird die Kombination vor allem durch Funktionen geschehen.
Dann Funktionen, gegebene Funktionen zu weiteren Funktionen zusammenzusetzen.
Und das habe ich eingeklammert. Man sollte in der Lage
sein, Definitions- und Wertebereich von Funktionen zu beschreiben.
Das können wir wunderbar machen in Reckett, müssen es aber nicht.
Deshalb bin ich es angeklammert. Wir werden es aber lernen,
wie es geht und ich möchte sie ermutigen,
es zu tun
Für jede Funktion, die sie Knatur definieren. Und zu sagen,
diese Funktion, die ich hier eingeführt habe,
bildet Zahlen ab auf Symbole oder etwas, so etwas, ja?
Wir haben zwei Arten, wo wir abstrahieren, einmal funktionale Abstraktion,
Berechnungsschritte zu neuen Funktionen zusammenfassen und Datenabstraktion, eigene Datentypen bauen.
In diesem Semester werden wir uns vor allem auf die funktionale Abstraktion konzentrieren,
weil Datenabstraktionen haben sie ja schon in den beiden Semestern
davor gelernt,
wie man
größere Datenstrukturen baut
Okay, was immer die Art der Abstraktion ist,
sie abstrahiert vom zugrunde linken Verarbeitungsmodell und wir können neue Schichten und neue Verarbeitungsmodelle drüber setzen.
Also, die simpelste Abstraktion überhaupt, aber die bestimmt unsere ganze Kultur,
wir abstrahieren, indem wir Dingen einen Namen geben.
Und dann nennen wir nur noch den Namen und jeder weiß,
dass damit gemeint ist.
Der Name einer Funktion steht dann als Blackbox für ein Berechnungsschema
und wir brauchen es nicht im Einzelnen zu kennen. So,
man sagt es ziemlich kompliziert, aber es ist eigentlich einfach,
ein Name identifiziert ein Symbol und dieses Symbol hat einen Wert und dieses Wert ist die Funktion.
Also wenn wir Eine Funktion definieren. Meine Quadratwurzel, ja
, dann haben wir den Namen eingeführt, meine Quadratwurzel.
Und wenn ich den im Programm verwende, guckt Racket nach
in seiner Symboltabelle. Was ist der Wert dieses Symbols?
Und holt diesen Wert? Der Wert dieses Symbols ist ein
Funktionsobjekt und das wird angewendet, wenn wir meine Quadratwurzel sagen.
Letztendlich brauchen wir es beim Programmieren gar nicht so genau zu wissen.
Wir müssen es nur dann wissen,
wenn wir anfangen,
Meta-Programmierung zu machen
Und beginnen Symboltabellen hin und her zu schieben zwischen Funktionen.
Ja, da müssen wir wissen, was so eine Symboltabelle bedeutet.
Und da kümmern wir uns aber erst in der Mitte des Semesters drum.
Okay. Und kannst alles hier zusammengefasst salopp sagen,
wenn wir einen Wert im Programm haben,
sieht man ihm nicht mehr an, wie er entstanden ist.
Ja, wir verwenden ihn einfach. So,
wir definieren Symbole, indem wir einfach die Fein schreiben.
Die Fein ist jetzt keine Funktion, das ist sehr wichtig
zu wissen, was eine Funktion ist und was nicht.
Man sitzt dem nicht so ohne weiteres an.
Es gibt vordefinierte Namen, das sind taktische Schlüsselworte,
genauso wie sie Den anderen Programmiersprachen Beginn und End haben, ja.
Die Feinde ist ein solches syntaktisches Schlüsselwort, das sagt dem Entferbretter Hoppler, aufgepasst.
An dieser Stelle habe ich etwas vor, was keine funktionale Auswertung ist.
Ich möchte einen WTK definieren, beklagt dich bitte nicht,
dass der noch nicht definiert ist, weil ich definiere ihn noch gerade.
Deshalb ist das so ein taktischer Schlüsselwort,
denn wie sie gesagt hat,
die normale funktionale Auswertung wäre so, hier steht Sinus,
Sinus will jetzt erstmal wissen, wovon will ich es berechnen,
nimm den nächsten Wert und sagt, oh, Hoppler,
das Symbol hat noch keinen Wert,
ich kann es nicht rechnen,
Fehler,
steigt alle Viere von sich
Deshalb beim Define ist es ein syntaktisches Schlüsselwort, das sagt,
bitte nicht überrascht sein, wir kommen jetzt erstmal undefinierte Sachen,
weil ich sie erstmal definieren will.
So, und steht jetzt also der Name,
den wir einführen, und hier steht der Wert,
der an diesen Namen geründen werden soll, und der wird dann ausgerechnet.
Das heißt, so ein taktischer Schlüsselworte führen dazu,
dass wir Kontrolle drüber haben, in welcher Reihenfolge hier ausgewertet wird.
Er ist das zweite Argument ausfährten und dann den Wert hier
vorne dran binden. Und wir haben hier jetzt,
ich habe jetzt dreimal die feinen K hingeschrieben,
und Ob es auf drei verschiedene Arten gemacht,
in jedem Fall würde ich den Wert sechs bekommen.
Und wenn ich hier jetzt K mal K schreibe,
ist völlig unerheblich, auf welchem dieser Wege der Wert je berechnet würde.
Nicht überrascht sein, wenn sie genau das hier in Recket
eingeben, kriegen sie eine Fehlermeldung.
Warum? Es ist eine funktionale Sprache und in einer funktionalen
Sprache wird jeder Wert genau einmal eingeführt.
Sie können im Programm den Wert nicht durch eine neue Definition ändern.
Also das, was hier steht, ist verboten, durchgestrichen.
Wenn sie einen Wert definieren wollen, überlegen sie sich sehr gut,
wie er sein soll,
sie können ihn
nicht wieder ändern
Einmal hinschreiben und dann gilt er, ja?
So. In diesem Fall ist der Abstraktor die Berechnungsschritte,
Abstraktion besteht darin, dass wir Äquivalente Probleme,
die bezüglich einer Relation ineinander Äquivalent sind, auf einen gemeinsamen Ausdruck zusammenführen.
Und in diesem Fall ist die Äquivalenzrelation,
die das tut, die Wertgleichheit der Ausdrücke.
Ich habe den ganzen Teil über Abstraktion über Äquivalenzrelationen aus der Vorlesung rausgeschmissen,
aber wer will, kann sich es im Anhang noch durchlesen,
ja?
Es kostet ein
bisschen viel Zeit,
das zu vertiefen
Möchten wir den Hinweis hier geben, Abstraktionen bedeutet eigentlich,
dass wir Dinge, die bezüglich einer gegebenen Äquivalenzrelation,
die sich gleich verhalten, verwenden.
So, das Resultat unserer Abstraktion ist jetzt die konstante Sechs
und die hat einen Namen K und dann können wir sie verwenden.
Also Name wird definiert, indem wir ihn an die Feinausdruck einführen.
Das ist das Praktische für die Programmierung. Es muss ein Ausdruck angegeben werden,
der den Wert bezeichnet, an den der Name gebunden wird.
Das kann also ein beliebiger Ausdruck sein. Und das Interessante ist,
wir merken es daran, dass die Fein Keine Funktion ist,
sie gibt keinen Wert zurück. Oder genauer gesagt,
der Wert, der zurückkommt, ist der undefinierte Wert.
Wenn wir irgendwie einen, die Feinden dahin schreiben,
wo ein Wert erwartet wird, kommt der undefinierte Wert zurück.
Und das zeige ich immer an durch das Spottom-Symbol.
So, Namen müssen eindeutig sein. Wir dürfen denselben Namen
nicht zweimal definieren, schon gesagt. Wir können versuchen,
Standardfunktionen überzudefinieren, indem wir sie verbergen,
in lokalen Blöcken
Das gilt. Also, wenn wir geschachtelte Blöcke haben,
können im Inneren eines Blockes schon vordefinierte Namen verbergen, die alt,
der alte Name mit seinem alten Wert bleibt erhalten,
der gilt außerhalb des Blockes und innerhalb Bild der neue Name.
Ich möchte aber davon abraten, dass sie vordefinierte Funktionen wie
Plus und Minus oder syntaktische Schlüsselworte da so versuchen zu überzudefinieren, das führt zu Problemen.
Weil sie sind nicht mehr verwenden können. Gut,
schreiben wir mal ein kleines Racket-Programm, was wir jetzt mit Definitionen arbeiten.
Da steckt noch nicht viel hinter. Wir erinnern uns,
Anfänge, Geometrie und der Recht sagt es Pithagoras,
ne, a Quadrat plus Big, Quadrat,
vielleicht c Quadrat und damit kann man die Hypote nur so eines Dreiecks ausrechnen, ja.
Ja, jetzt rechnen wir mal,
das als wirklich als allererstes Babyprogrammchen, schreiben hin,
wir meinen, es ist die Sprache Recket, langen Recket,
mein erstes Recket-Programm berechnet die Hypothenuse eines Dreiecks als Kommentar,
als Hauptkommentar hier mit Reisemikolans.
Jetzt definieren wir die Argumente A für die Seite A des Dreiecks B
für die Seite Betis Dreiecks und dann können wir C berechnen,
als Quadratwurzel aus A Quadrat und B-Quadrat,
Plus Bierquadrat. Wenn wir jetzt die Randtaste drücken,
wird das Programm gelesen und dann können wir abfragen.
Im Value, aber was haben denn nur unsere globalen Variablen
A, B, C für Werte?
A, ist das A, was für eingegeben haben.
B, ist das Bier, was wir eingegeben haben.
Und C ist ein ganz schön großer Wert.
Können wir im Evaluator abfragen? So,
in der funktionalen Programmiersprache ist es eben in der Renzo
des Variablen feste Größen sind und nicht mehr verändert werden dürfen
Lehrsprachen verbieten es explizit. Wenn wir in der Sprache sind,
allgemeines Fracket, dann gibt es imperative Sprachelemente,
mit denen wir es ändern können, aus Effizienzgründen.
Aber ich sage Ihnen gleich, wenn Sie auf die Idee kommen,
dass in Ihren Übungsaufgaben zu versuchen, außer Sie werden explizit aufgefordert,
mal diese emperativen Sprachelemente zu verwenden,
werten wir die auf arbeitsfalsch gelöst.
Also einmal wertbünden, er bleibt so zumindest für die Dauer
dieses Semesters. Bei der Namensgebung können Sie
ziemlich kreativ sein
Da die Syntax nicht sehr reich ist.
Im Wesentlichen, Klammer auf, Klammer zu.
Komm mal und Synbikola und haben noch bestimmte Bedeutungen,
aber im Wesentlichen ist es ihnen freigestellt,
die anderen Zeichen aus dem Aski-Zeichensatz alle zu verwenden.
Also wir können Variablen nehmen, namen Dollar nach Euro oder so
, ja, das geht alles.
Oder mit Sternen beginnen, lassen Sternen enden. Und können
auch mal mit einem Punkt anfangen oder und so weiter.
Das ist also zulässig, ja. Unzulässige Namen sind,
wenn die Klammer mit zum Namen gehört, Oder Dinge,
die als eine Zahl gelesen werden könnten.
Die dürfen wir nicht als Variablen Namen nehmen. Also wir dürfen
keine Zahlkonstanten überdefinieren. Also das sind alles in taktische Schlüsselworte,
die auf keinen Fall durch neue Namen per Set überschrieben werden dürfen.
Sind praktische Schlüsselworte, die mit einem Ausrufezeichen beginnen, sind imperative Sprachelemente. Also wenn,
es ist Konvention in der Recket-Welt,
wenn sie Funktionen mit Seiteneffekten definieren, was sie nicht tun sollen,
aber wenn sie es tun,
dann seien sie wenigstens so nett und geben dem einen Namen mit einem Ausrufezeichen dahinter als Warnung,
dass das Ding Seiteneffekte hat.
Interfunktionszeichen dürfen nicht im Namen vorkommen, öffnende und schließende runde
geschweifte eckige Klammern. Unsere Gänsefüßchen, Quote und Backquote,
ja, Leerzeichen darf nicht im Namen vorkommen, Zeilen,
Ende, Semikolon und Komma.
Ja. Okay. Kleine Komplikation. In der Anfangszeit von
Liz Brackett, Skim war die Welt einfach
Da wurde schlichtweg Groß- und Kleinschreibung ignoriert.
Dasselbe Groß geschrieben, wie klein geschrieben, war derselbe Name.
Selbst wenn man im Namen wechselte, ja,
hier so in den frühen Versionen war ABC klein geschrieben,
AB, Groß klein geschrieben und so weiter, war alles dieselbe Variablen.
In der nächsten Record-Version, ich erzähle das jetzt,
weil man manchmal nicht genau weiß, welche Versionen sie installiert haben.
Und dann kann sowas zu Komplikationen führen.
In der nächsten Version wurde gesagt, was soll der Quatsch?
Jede andere Programmiersprache unterscheidet Groß- und Kleinschreibung, machen wir auch.
So, danach waren Würde hier False rauskommen oder eine Fehlanmeldung,
weil die anderen Sachen gar nicht definiert waren.
Das gab genauso einen Sturm der Entrüstung. Und der Kompromiss ist jetzt,
dass sie eine Voranstellung in Reckett haben, wo sie sagen,
ob sie groß und kleinschreibung unterscheiden wollen.
Ich möchte sie bitten,
damit wir in diesem Semester nicht mit wechselseitigem Ausprobieren Schwierigkeiten kriegen,
dass sie als Konvention beim Testen die Voreinstellung neben Groß- und Kleinstreibung könnten nicht unterschieden.
Damit sind sie auf der sicheren Seite,
weil ihnen jeder Fehler angezeigt wird, wo sie denselben Namen mal groß,
mal klein geschrieben haben.
Und der Übungshelfer, der Übungshelferin wird
auch keine Probleme haben
Also auf der sicheren Seite sind wir,
wenn Sie die Voreinstellung so ändern, als würden Sie
den Unterschied zwischen Groß- und kleinen Schreibern nicht nutzen wollen.
Gut, jetzt kommen wir nochmal dazu, was jetzt das Wesen der Funktionalen Abstraktion ist.
Wir haben jetzt bis jetzt erstmal nur drüber sinniert, was den Namen sind.
Also wir wollen Klassen von Äquivalenten, komplexen Operationen als Einheit auffassen.
Wenn wir sinngemäß immer, immer wieder dasselbe tun,
es gibt nur einen Aspekt, sich ändert,
wollen wir darüber eine Klasse definieren von Dingen,
die immer wieder dasselbe sind und nur etwas ändert sich und
dieses Ende,
etwas machen wir explizit
Und dann geben wir dieser Klasse einen Namen. Und das
ist jetzt klasse im mathematischen Sinne, nicht klasse im Java-Sinn.
Und dann beziehen wir uns über diesen Namen auf dieses Schema zum Berechnen.
Ein Beispiel, wir hatten beim Satz des Pythagorassion
lauter variten Namen angeführt und die dann addiert,
so würde man es als fortgeschrittener Programmierer nicht machen.
Jetzt wollen wir mal allgemein schreiben, wie berechnen wir das Volumen einer Kugel.
Und dann wissen wir, wenn die Kugeln Radius 4 hat,
müssen wir für Drittel mal 4, mal 4,
mal 4, mal 4 rechnen.
Memsen Radius 5 hat, müssen vier Drittel mal Team mal
für 5x 5x 5 und so weiter rechnen. Ja,
und nach guter Schularzt sagen wir dann, okay,
also hier kommt dreimal dasselbe und da setzen wir dreimal ein
Kästchen hin und für dieses Kästchen könnt ihr was einsetzen.
Damit haben wir ein Schema, wir haben berechnet das Volumen einer Kugel,
indem man den Radius immer wieder mit sich selbst mal nimmt,
mit vier Drittel und mit Pi.
Ja. Wir könnten es machen, indem wir,
also erstmal die konstante Pi ausrechnen,
wenn wir eine Sprache gewählt haben, in der sie nicht vorkommt,
indem wir sagen,
Pi ist zweimal der Akustinus von 1.
Damit sind wir bei Pi Heime
Aggustinus von 1 wären wir bei Pi halbe und
dann kommen wir das Ganze mit zweimal nehmen. So,
und dann können wir, wenn ein gegebener Radius darf,
definiert, es könnten wir sagen, okay,
wir rechnen vier Drittel mal Pi und dann Radius, mit Radius, mit Radius.
Und daraus hat jetzt, I lonce the chudge,
eingeführt den Begriff einer Funktion, indem er gesagt hat,
wir brauchen immer wieder dieses R und das abstrahiere ich aus
dem Ausdruck als gebundene Variable in diesem Ausdruck und Ich gebe das an über die Lamnder-Notation.
Lamnder mit der gebundenen Variable R und einem Ausdruck dahinter,
soll bedeuten, dass was immer wir für diesen Wert R hier einsetzen,
soll da verwendet werden.
Ja, das ist die Basis des Lamder-Kalküls.
In solchen Ausdrücken zu abstrahieren, die Werte zu finden,
die verändert werden sollen, in systematischer Weise.
Und die Tammstruktur bleibt aber gleich. Lamder, Klein R und
dahinter dieser Ausdruck. Und das ist genau die Basis für Funktionen,
wie sie in der Programmiersprache Liz seit Anbeginn verwendet wurden.
Und auch in Recket immer noch zu finden sind
Rackett ist nämlich ein Funktionsobjekt,
ein Wert vom Typ Funktionsobjekt ist eine Struktur,
die darin besteht, dass wir hier explizit Landa schreiben als Schlüsselwort.
Dann eine Liste von gebundenen Variablen und dahinter der Ausdruck,
der mit diesen Variablen berechnet werden soll.
Also was wir hier haben, ist ein zusammengesetzter Wert vom Typ Funktionen.
Eins zu eins, Churchs Notationen aus dem Landerkalkalkül,
nur die Klammern sind ein bisschen verrutscht.
Aber ansonsten kann man da eigentlich nicht meckern,
es ist treffend
Gefunden. Und sie können in Reckett sogar über Special-Menü,
wenn sie es mögen und ihr Programm schick aussehen soll,
statt hier Lander zu schreiben, den griechischen Buchstaben Lamm da einsetzen.
Okay, also, das hiermit haben wir ein Objekt erzeugt
vom Typ Funktion. Was kann diese Funktion? Wir geben
ihr ein Argument er und dann rechnet sie damit los.
Wie geben wir eine Funktion einen Wert, damit sie losrechnet?
Wir machen eine Klammer auf, dann kommt hier der Name,
desto der Funktion und diese Funktion heißt Lamm da,
Klammer auf, Klammer zu und so weiter.
Ja, hier steht der Name dieser Funktion,
bis zu dieser erschließenden Klammer und hier kriegt sie
ihren Wert vier
Also hier steht, wann, wann,
wenn denn diese Funktion an, auf den Wert 4. Ehrlich gesagt,
sieht ein bisschen kompliziert aus, warum nicht einfach stattdessen schreiben,
P4, 4, 4. Weil wir dann die vier,
viermal hätten wir schreiben müssen,
so schreiben wir sie nur einmal.
Und wenn das hier ein Ausdruck wäre, der ziemlich komplex ist,
also berechnete Life the Universal and Every Single, es dauert Millionen Jahre,
möchte man es nur einmal berechnen und nicht dreimal.
Also er spart, wenn wir es hier einmal hinschreiben,
wird es einmal ausgewertet und nicht dreimal,
wenn es hier stehen würde,
müsste es
dreimal gerechnet werden
Ja, also so können wir eine Funktion schreiben.
Wir haben einen Funktionswert. Wenn wir dieselbe Funktion jetzt
wieder aufrufen wollen, wir haben jetzt ein kleines Problem.
Die hat keinen Namen, dafür können sie nicht rufen.
Sie steht einfach so da. Wir könnten sie jetzt
mit Copy und Paste an anderer Stelle hinsetzen.
Auch ein bisschen dumm. Weil man macht so gern Copy-and-Paste-Fest-Fehler.
Okay, aber erst mal, um zu zeigen,
über Special-Menü in Dr. Recket könnten sie es auch so schreiben.
Spartplatz. Und sieht eleganter aus.
Ist dasselbe
Und wir können jetzt, okay,
ich erzähle Ihnen lieber erst mal das, bevor ich erzähle,
wie wir denn das Kind mit einem Namen geben und es aufrufen.
Also die Rassel entweitet hatten, als erste versucht,
die Slamderkalkül von Church zu übernehmen und das tatsächlich berechenbar zu machen,
indem sie das in Texten geschrieben haben und so weiter,
stellen sich damals vor, die einzige Eingabe waren sofernschreiberartige Dinge,
wo man tippen musste.
Und da kam schon mal das griechische Land dann nicht vor
Ursprungsnotationen von Shorge war ja dies hier. Handschriftlich gar kein
Problem. Man ist ein Setzer, gibt es den Bleigießen
auch kein Problem. Aber wenn man jetzt anfängt,
dass auch Fernschreibern oder Schreibmaschinen zu schreiben, dann ist es dumm.
Und Russell and White Head hätten das Landerzeichen dann zuerst ersetzt durch so ein Hütchen.
Wir haben hier die gebundene Variable X und dann kommt das dahin, nein.
Aber das ging immer noch nicht gut auf dem sequenziellen Text,
eine Schreibmaschine. Und dann hat man es davor gesetzt.
Ja. So, das Ding war so klein,
dass da im gedruckten Manuskript die Fliegen Dreck aus
Machte sich auch nicht gut, dieses kleine Dach direkt davor.
Und dann haben wir gesagt, na gut,
wenn das Kleine nicht sieht, machen wir das Große draus.
Und das war noch problematischer im Zusammenhang mit anderen mathematischen Formeln,
weil das ist schließlich das Große Logische und ja, oder das für alle.
Und wegen der Verwechslungsgefahr hat man dann gesagt, na gut,
dann setzen wir da jetzt doch wieder das Lamm da rein.
Ja, weil das ist mir viel ein griechisches Land da aussieht.
Da kamen dann die Slam da rein.
Und das kam aber auf den Kartenlochern nicht vor.
Und als die Programmiersprache Denn von Marcassi eingeführt wurde,
am MIT, er hatte diese Sprache erfunden,
direkt eins zu eins aus dem Lamderkalkühler,
der dann statt dieses Lamm der Zeichens einfach in Lamde geschrieben hat.
Und seitdem heißt das eben so, Lamda R.
Und wir haben es so. Ja,
und wenn wir es jetzt das Volumen aufrufen wollen,
dann schreibt, nehmen wir doch einfach unser Defeind von Ebenen,
das haben sicherlich auch alle vermutet.
Und über Jahrzehnte hat man im Wiss-Funktionen genauso definiert,
die Feind oder Jeff oder die Fun,
nahm mit der Funktion und dann kam dahinter Lamda
Das Funktionsobjekt, das ausgewertet werden soll. Und so können Sie
es heute immer noch in Recket schreiben und Puristen schreiben,
mal Funktionen wirklich in dieser Art, die fein, nahe mit der Funktion.
Und dann kommt der Wert des Funktionsobjektes, das ausgeführt werden soll.
Und der beginnt eben mit der Special Form Lambda oder dem Lambdazeichen.
Ja? Okay. Das war, ja,
also hiermit können wir jetzt Funktionen einen Namen geben.
Ins bitteren Teil dieses Semesters werden Sie merken,
Dass sie ziemlich viel mit Funktionen arbeiten,
muss sich nicht die Mühe geben, dem Kind einen Namen zu geben.
Genauso wie sie in Java, wenn sie Actionhändler definieren und sowas,
ziemlich viel mit anonymen Klassen arbeiten und nicht jede Klasse auch einen Namen hat.
Sie haben oft eine Klasse,
die nur einmal verwendet wird und genau da,
wo sie steht und wenn sie Daten nur einmal gebraucht wird und
nie wieder gibt man dem Kind nicht ersten Namen, das verwirrt nur.
Ist ein bisschen so, Wie wenn sie, sagen wir mal,
Mittagessen kochen und haben eine Tüte mit Nudeln, da sind jetzt 200 Baghetti drin.
Sie brauchen diese Spaghetti nur einmal in jeder Instanz und sie geben nicht jeder Spaghetti,
wenn sie ins kochende Wasser schmeißen, den ersten Namen,
du bist Peter, du bist Paul, du bist Anton,
ja.
Sie müssen keine der Einzelnen wieder beim Namen rufen.
Das Objekt allein reicht und das wird nur einmal gebraucht.
Genauso ist es bei den Funktionen. Wir werden viele Situationen haben,
wo sie eine Funktion einfach so dahin schreiben.
Sie wird nur da gebraucht an keiner anderen Stelle und steht
da genau richtig und dann kriegt sie
keinen Namen
Nur, wenn wir eine Bibliothek erstellen wollen mit Funktionen,
die mehrfach aufgerufen werden sollen oder in Programmen strukturieren wollen,
indem wir sagen wollen, dies ist der erste Schritt,
der tut das, dann geben wir den treffenden Namen.
Ja? Gut. Die Landernotation ist bei Liz-Puristen immer noch
beliebt. In Racket ist sie nach wie vor drin.
Erstens brauchen wir ohne Handy anonymen Funktionen immer wieder,
ohne dass wir einfach so einen Funktionswert konstruieren müssen.
Also brauchen was und wir können sie weiterhin verwenden,
um dann mit Funktionen zu definieren.
Sie ist da
Also, so können wir die Quadrierfunktion definieren. Berechne das
Quadrat vom X. Die Äquivalente Definition haben wir den Übungen schon eingeführt.
Aus funktionaler Sicht kann man auch sagen, ich definiere,
wenn jemand hinschreibt, Klammer auf Quadrat X, was soll gerechnet werden?
Und schreibe da drunter, was dieser Ausdruck hier bedeuten soll,
dieser gesamte Ausdruck mit seinen Parametern.
Und dann steht er hier. Ich möchte ihn freistellen,
welche Notationen sie verwenden, ob sie sich der Liga anschließen,
die es gern in der alten klassischen Landerkalkülnotation,
die Funktionen definiert
Bitte sehr, tun Sie es oder ob Sie
diese funktionale Sicht verwenden wollen, die äquivalente Definition.
Beides kann man gut lesen. Das ist eine Geschmackssache,
ja. Und seit mindestens zehn Jahren ist es erlaubt,
Funktionen so zu definieren. Okay, die zweite Form,
müssen wir aber festhalten, ist wirklich nur ein syntaktischer Zucker.
Ja, der Pre-Prozessor ersetzt das intern sofort durch die andere Art.
Gut, was müssen wir über Variablen noch wissen?
Variablenskopus, das sind freie und gebundene Variablen.
Das verhält sich in Recket ziemlich so,
wie Sie es aus Java gewöhnt sind,
Einfach nur im Hinnomenklaturplatz zu kriegen. Also wenn wir das hier schreiben,
Lander, dann ist das ja eben eine gebundene Variable bezüglich des Landerausdrucks hier unten drin.
Pi ist eine freie Variable, weil der Wert von Pi
wird nicht eingeführt im Variablensgruppes dieser Funktion, das ist global definiert.
Wenn wir eine Funktion haben, dann sind die Namen der
gebundenen Variablen austauschbar. Die Funktion würde dasselbe tun,
wenn wir hier statt R-Rat oder Radius oder sowas schreiben würden.
Die Struktur ist das Gleiche, die Funktion Berechnet dasselbe?
In einem Korrektheitsbeweis können wir sagen, die Funktionen sind identisch.
Was allerdings nicht funktioniert, ist, wenn sie fragen,
Äquival ist diese Funktion Äquival mit der.
Das wird Falls geben, weil wenn Recke das könnte,
gegeben, zwei Funktionsdefinitionen, die auf Identität vergleichen,
könnten wir damit das Halteproblem lösen.
Es ist berechnungs... Es ist nicht erlaubt, Varianten,
Funktionen selbst zu vergleichen
Gut. Die Namen der gebundenen Variablen sind nur im Kontext
der Funktion, im Body, der lokalen Umgebung definiert.
Okay. Zu den Argumente, das sind die in der
Funktionsdefinition gebundenen Variable, die nennen wir Parameter oder Argumente.
Wir nennen sie formale Parameter. Wie sie in der Definition
stehen und aktuelle Parameter, das, was wir beim Aufruf übergeben,
ist ähnlich vielen anderen Programmiersprachen.
Und darüber reden wir ein andermal. Müssen wir uns
nochmal angucken, wie kriegen wir in Funktionsdefinitionen es hin
Dass wir Fallunterscheidungen haben. Also mathematische Funktionen müssen wir ja
oft so was machen. Also die Funktion Max 2,
Maximum 2er Zahlen soll uns X zurückgeben,
wenn X größer gleich Y ist und andernfalls Y. Oder
wir wollen durch etwas teilen, X durch Y,
falls Y größer Null ist.
Andernfalls sollen unendlich zurückkommen. Also müssen wir abfragen können,
die Werte. Und das geht wie in jeder anderen Programmiersprache
auch. Gibt es das syntaktische Schlüsselwort If? If,
dann kommt ein Ausdruck, der zu einem Wahrheitswert evaluieren soll
Und dann schreiben wir die beiden Varianten hin, was der Wert sein soll,
wenn der Wahrheitsausdruck wahr ist und wenn er falsch ist.
Also einfach das große If hierhin und fertig.
Ja, hm. Gucken wir uns mal dieses Beispiel an.
Ich habe hier eine Funktion definiert, Teile durch Y, X-Deuch
Y. Und hier geschrieben, wenn, ab es von Y
größer Null ist, Dann soll tatsächlich X durch Y geteilt werden.
Und andernfalls wollen wir eine Fehlermeldung haben.
Und sie sehen hier, was die Special Form Error macht.
Die gibt hier einfach eine Fehlermeldung zurück. Und wir können
eben hier vorgeben, was die Fehlermeldung sein soll.
Okay. Das sind alle bedingte Ausdrücke. Der Übersichtlichkeit halber
, oh, wow. Der Übersichtlichkeit halber gibt es noch
eine zweite Form, wie wir abfragen können.
Das ist einmal das Wenn und einmal das anlässt. Das sind bedingte Ausdrücke,
die überhaupt nur in einem Fall einen Wert haben,
in anderen Fällen, den undefinierten Wert zurückgeben.
Also wir können sagen, wenn X größer 3 ist oder so
, dann soll das gemacht werden.
Und andernfalls geschieht gar nichts. Wir können das Gegenteil testen,
wenn es nicht wahr ist, dann würden wir hier ein Ness schreiben.
Aber wir können Variable in einer lokalen Umgebung einführen,
möchte ich sie darum bitten, das auch zu tun,
mit Hilfe von Lett. Wir schreiben Lett,
dann kommt eine Klammer auf und hier in eine Klammer zu
und Tier rein kann jetzt eine beliebig lange Liste von namens Wertpaaren kommen.
Also hier wird die Variable X angeführt mit dem Wert 1 Y eingeführt,
mit dem WR2 und so weiter hier. Und im Kontext dieses Let,
also von dieser Klammer auf bis hier am Ende zu,
können wir jetzt Bezug nehmen auf die Variablen X und Y. Was wir nicht tun können,
wenn wir das hier so schreiben, ich könnte hier nicht schreiben,
Y ist zweimal X. Warum nicht?
Weil alle Wertpaardefinitionen hier als parallel definiert eingeführt werden.
Also erst, wenn diese Klammer hier zu ist,
die die schließende Klammer zu für die Namens-Wertliste,
dann sind XYZ und so weiter definiert.
Also wenn ich hier Y definiere, ist X noch unbekannt.
Und wenn ich hier X verwenden würde, müsste eins in
der globalen Umgebung definiertes X vorhanden sein und dessen Wert würde genommen.
Weitere spezielle Funktionen Void, die gibt uns den undefinierten Wert zurück.
Also wenn wir wollen, dass ein Ausdruck keinen Wert hat,
dann können wir einfach Void aufrufen und bekommen den Wert zurück
Okay. Wenn wir einen If haben oder If schreiben,
dann müssen wir wirklich beide Fälle vorgeben. Für den Fall,
wo es wahr ist und für den Fall, wo es falsch ist.
Also in einem If darf die Alternative nicht fehlen.
Dafür gibt es eben Wenn und Anläss.
Also wenn wir ein einseitiges If haben wollen,
müssen wir es deutlich machen, indem wir sagen, wenn.
Ja. Und wenn wir viele unterschiedliche Abfragen haben,
gibt es noch einen schönen Ausdruck für einen Mehrwegverzweigung und das
können wir hier mal am Beispiel der Steuerreform ausprobieren,
können Sie eigentlich die grüne Schrift da sehen oder ahnen?
Ich könnte sonst das ein bisschen dunkler machen,
aber also da steht in Grün steht die Variable Einkommen, ja.
Also mein Vorschlag für die Steuerreform, um es einfacher zu machen.
Wir definieren eine Funktion Steuersatz und der Steuersatz ist abhängig vom Einkommen,
es wird nicht lang gefackelt mit Abschreibungen und so weiter.
Hängt nur am Einkommen unseren Snacks, ja.
So und jetzt verwenden wir die Mehrwegverzweigung konditional.
Die sitzt dann taktisch so aus,
wie er schreiben konnte
Und dann kommt eine Liste von Bedingungen und einem Resultat dahinter.
Die Bedingungen können beliebiger Art sein.
Ich habe hier laut der Bedingungen über Vergleiche gemacht,
aber der kann wirklich alles
Und wie wird das Ost gewertet? Reckelt wird der Reihe nach,
diese Fallunterschiede, diese Tests machen und beim ersten Test,
der zuschlägt, wird die Auswertung abgebrochen und der Wert zurückgegeben.
Wenn keiner dieser Bedingungen zu treffend war,
dann wird das letzte Erz hier genommen.
Dieser Default und dann kommt dieser Wert zurück.
Also auf diese Weise können wir eine Vielzahl von Abfragen
sehr übersichtlich zusammenfassen
Des Erz ist optional, es muss nicht sein.
Wenn sie es weglassen, dann müssten sie aber zur Sicherheit beweisen,
dass ihre Abfragen hier erschöpfend sind und keinen Fall ungetestet bleibt.
Sonst haben sie vermutlich eine Quelle für Fehler.
Also formal können wir es in Bakus Nauer Form so schreiben,
ein konditional besteht aus dem Schlüsselwort Cont.
Und dann eine Folge von Bedingungen,
Aktionswertpaaren und die sind in eckigen Klammern,
auf diese Weise sieht man eher,
welche Klammern zueinander gehören
So. Und ja, diese Bedingungen hier, diese Ausdrücke,
die heißen Wächter oder Garz auf Englisch, ne?
Also die Garz werden der Reihe nach ausgewertet, während der ersten Bedingung,
wenn er erfüllt ist, wird als wertes Konditionalgeiz genommen,
wenn die Bedingungen nicht des Jugends sind,
ist dann die Reihenfolge sehr wichtig, ja?
Die Konstellation von Argumenten, die auftreten können,
sollte durch Wächter abgefangen werden, sonst haben wir eventuell Fehler.
Wenn man keinen Erz vorgesehen hat und keinen Wächter zugeschlagen hat
, kriegen wir einen Laufzeitfehler
Dies Ärzte ist so ein Catch-All, was man gefälligst ans Ende
tut und wird dann genommen in keiner der Bedingungen zugetroffen, zutrifft.
Jetzt gibt es denkfaule Menschen, die das Erz auf
jeden Fall immerhin schreiben, um irgendwie sicher zu sein.
Man sollte es nicht tun. Also wenn man das Erz dahin schreibt,
deutet man damit an, dass die Guards die Fälle nicht erschöpfend abdenken.
Und das erfordert dann, dass die Leser des Programms nachdenken
müssen und sehen, wer ist erschöpfend gewesen oder nicht.
Also ein überflüssiges Erz ist verwirrend. Das sollte man
nur dann tun, wenn man dabei,
ist das Programm
zu debatten
Und sicher sein will, dass man eine Fehlermeldung kriegt,
wenn der eigene Beweis nicht geklappt hat. Also aber nicht denkfaul sein,
sich immer überlegen, brauche ich es oder nicht.
Es gibt in Recket auch Schleißen, ja? Also keine Sorge,
es ist eine allgemeine Programmiersprache, Universal, Universal Programming Language,
General Purpose. Nur wir werden, weil Dooles,
Doot Times und all diese schönen Schleifen, die ich finde,
viel schöner gelöst finde als in Java, hier nicht verwenden.
Weil wir eben mit Funktionen arbeiten wollen. Ja,
also wenn immer, was wir ziemlich früh tun werden,
Immer sie in Java zu einer Waldschleife oder Vorschleife oder so gegriffen hätten,
dann werden wir stattdessen eine passende treffende Funktion nehmen.
Oder Rekursion. Gut, hier nochmal das Let, wir hatten es schon eingeführt,
um lokale Variable zu haben, Klammer auf, Let.
Runde Klammer auf, Namenswertpaare, ja, Klammer zu. In früheren Liz-Pok-Programmiersprachen,
was gang und gäbe, dass man gar keinen Body brauchte,
in Recket ist es seit Recket,
5-1 Pflicht,
da muss im Rumpf eines solchen Körpers wenigstens eine einzige Variante,
ein einziger Ausdruck stehen
Sonst kriegt man eine Fehlermeldung. Ob Beispiele für Let können
sich in Ruhe später angucken. Schauen wir mal hier jetzt,
um das zusammenfassen, uns noch mal anzuschauen, zwei Funktionsdefinitionen an.
Ich habe hier eine Funktion. Erst, ja?
Ich habe das auch schon mal gemacht mit dem Feind,
der lokale Variable definiert. Was ist denn da der Unterschied?
Es ist beides zulässig und erlaubt. Also mit dem Let
kriegt man zusätzlich einfach durch diese Klammer auf und diese Klammer
zu den Skopus dokumentiert,
wo die Variable gilt
Sonst gilt sie eben in dem höheren Skrupus.
Also es geht mit die feinen, sie haben diese Blockstruktur.
Es ist systematisch schöner, wenn man an einer Stelle geschlossen einfach sagt,
und hier fühle ich all meine lokalen Variablen ein.
Das ist eine Frage der Dokumentation. Noch eine Frage.
Also ruhig melden. Und wenn ich es nicht bemerke,
wenn sich jemand meldet laut geben, das war sehr gut.
Also hier führen wir jetzt Variablen A und B ein,
geben ihnen Werte, greifen dabei zurück auf die Variablen X und Y,
die wir hier oben eingeführt haben,
und schreiben wie einen Ausdruck,
der berechnet wird
Hier habe ich jetzt einmal mit Lett versucht, eine Funktion zu schreiben.
Und diese Funktion soll Quadrat heißen. Also in diesem Fall
brauchen wir tatsächlich die Landerform, wenn ich das im Lett machen will.
Ich muss ja erst den Namen nennen und dann den Wert
und der Wert ist hier jetzt eben dieser Lamdeausdruck.
Also wir haben ja eine Funktion namens quer eingeführt.
Und jetzt möchte ich hier eine zweite Variable A berechnen und
dabei meine Funktionsquere schon verwenden. Ja, ich hatte ja vorher gesagt,
es geht aber im Lett nicht, weil Was ich hier einführe,
alles erst definiert ist, wenn die Klammer hinten zu ist.
Also ist quer eigentlich noch undefiniert. Da hatten aber
die Recket Designer der Sprache doch eine Einsicht und haben gesagt,
wenn man es denn unbedingt braucht, ist es erlaubt,
man muss es aber vorher beantragen.
Und das machen wir mit diesem Stern hier. Letztes Stern,
garantiert, dass alle Variablen dir sequenziell ausgewertet werden und gebunden werden.
Und die Namen sofort definiert sind, wenn die Klammer zugeht. Das heißt,
durch das Letztstern hier habe ich erreicht, in der nächsten Zeile,
die Funktions quer schon definiert ist und ich sie verwenden kann.
Also Stern hier ist eine Warnung, dass die Auswertereihenfolge geändert ist.
Also wir sind damit schon einen Tick imperativ geworden,
damit einmal eine Programmierung haben, bei der die Auswertungsreihenfolge bestimmterweise erzwungen wurde.
Okay. So, der Wert eines, ist der letzte Ausdruck,
der kommt. Ich kann hier unten einen Ausdruck reinschreiben oder
ganz viele. Der Wert des letzten Ausdrucks ist das,
was zurückkommt als Resultat der Berechnung
Ja. Hat jemand eine Idee, warum es überhaupt Sinn macht,
wenn doch nur der Wert des letzten Ausdrucks zurückgegeben wird?
Warum soll ich Rechenzeit damit verschwenden, vorher noch ein paar andere Ausdrücke zu berechnen?
So eine Beschäftigungstherapie für den Computer, ne? Naja,
gut, was man vorher hier zwischenschreiben könnte, sind solche Ausdrücke wie Display.
Wenn ich Werte zur Anzeige bringen will und so etwas, ja,
dann kann ich Zeit mit einem Display und dann einen Wert dahinter Dinge ausgeben.
Ich kann versuchen, Variabien einzulesen über Benutzereingabe und all solche Dinge.
Aber wie gesagt, Das, was als letztes hier gerechnet wird,
das Gleiche gilt für eine Funktion, ist der Wert dieses funktionalen Ausdrucks hier.
Ja? So, in den allerersten Lustfassungen gab es sowas Philetten nicht.
Und gesagt, was brauche ich ein Let?
Ich kann Variablen mithilfe von Lamda in Werte binden.
Da war Lamda wirklich das Einzige, um Variable zu binden.
Neben dem die Fein für einfache Werte. Und wir können
uns mal angucken, wie wir ein Let ersetzen können,
durch einen Lamda-Ausdruck. Letztendlich ist ich nichts anderes als ein Makro,
was genau auf diesem Landerausdruck hier abgebildet wird. Ich hoffe,
das ist jetzt nicht zu theoretisch für die späte Zeit,
so kurz vor der Männerpause, aber versuchen wir es mal hin.
Was macht denn ein Lett? Wir haben wir bestellt,
wir möchten einen Ausdruck Xplus Y berechnen und X soll vorher
den Wert 40 kriegen und Y soll an den Wert 1 plus 1 gebunden werden.
Ich kann exakt das Gleiche erreichen, indem ich schreibe,
ich habe zwei Variablen X und Y und mit denen soll gerechnet werden Xplus
Und er schreibt ja als ein Lamdeausdrücken. Dieser Lamdeausdruck erzeugt
mir eine Variable. X. Und er erzeugt mir eine Variable
Y und rechnet mit den beiden X plus Y aus.
Und wenn ich diese anonymen Funktionen gehe,
für X den Wert 40 übergebe und für Y den Wert 1 plus 1,
dann habe ich genau das erreicht.
X hat den Wert 40, Y den Wert 1 plus an.
Und es wird damit X plus Y gerechnet. Es ist
dasselbe in Grün. Lett ist ein syntaktischer Zucker für Lamnders
. Der einzige Unterschied hier ist, Also ehrlich gesagt,
ich finde das besser lesbar, weil wir gehen nämlich sofort sehen,
welche Variable an welchem Wert gebunden wird.
Wenn wir den Weg hier gehen über ein Lamm dann mit den Variablen,
lokalen Variablen X und Y eingeführt und der Bindung über die Argumentliste,
dann müsste man hier einfach Pfeile ranmachen oder so, um zu sehen,
aha, X wird hier rangebunden, Y wird hier rangebunden.
Also das Leck ist einfach eine Frage der besseren Lesbarkeit,
dafür ist es da.
Es tut aber exakt genau das,
was eine anonyme Funktion mit einem Lamm
da machen würde
Wir haben globale Namensbindungen, wir haben lokale Namensbindungen,
es funktioniert eigentlich, wie erwartet, es ist eine Blockstruktur,
wie sie ganz klassisch auch in imperativen Programmiersprachen da ist.
Wir haben in Reckett die Standardnamen, die schon mit dem System kommen,
dann haben wir das, was wir global einfach einführt im Programm,
ohne es in Funktionen zu definieren.
Und dann wird jede Funktion, die wir definieren,
ihre eigenen Argumente als Namen haben, plus das,
was wir mit Lettinnen drin einführen, Und so ist das Ganze geschachtelt.
Was wir jeweils in der lokalen Umgebung haben,
das nennt sich auf Englisch Environment und ist das, was zur Funktionsdefinition dazugehört.
Also was wir später beim Programmieren stets und ständig ausnutzen,
ist, wenn wir eine Funktion definiert haben,
dann gehört dazu Huckepack, diese ganze Umgebung mit Namen,
die bekannt sind, wenn wir die Funktion definiert haben.
Wenn wir jetzt quer definieren, wir einen Namenswerttabelle als Umgebung,
in der gibt es F, da gibt es X,
da gibt es Z, da gibt es die globalen Dinge.
Und das hängt an der Funktionsdefinition dran. Und wenn wir
Funktionen als Argumente weitergeben, dann gehört die Umgebung dazu,
die Symboltabelle, in der drinsteht, welchen Wert hat X,
welcher hat Y und so weiter.
Im Moment, wo diese Funktion definiert wurde.
Das klingt jetzt etwas umständlich, ist aber die Basis dafür,
dass wir mithilfe von Umgebung genauso programmieren können,
wie wenn wir Objekte in Java weitergeben
Art wie in der Funktion, funktionalen Programmierung. Ein Objekt geschaffen wird,
in dem wir Attribute haben, die an Werte gebunden sind,
ist genau die, dass wir eine Funktion definieren mit Argumenten
und die Belegung der Argumente und lokalen Variablen in dieser Funktion,
in diesen Tabellen stecken.
Eine Funktion wird sich für alle unsere Zwecke so verhalten,
wie ein Objekt mit Attributen und wir können Funktionen weitergeben wie Objekte.
Also das ist eigentlich das, was meisterlich gemacht wird,
wenn wir mit höheren Funktionen höherer Ordnung programmieren
Und deshalb müssen wir Umgebungen gut unterscheiden können und wissen,
was die globale Umgebung ist und was die lokale Umgebung von Funktionen ist,
damit wir über Funktionen, objektorientiert programmieren können.
Also jede Funktionsdefinition gesteht im Kontext der aktuellen Umgebung.
Und diese Einheit aus dieser textuellen Definition und Bindungsumgebung
heißt auf deutsch funktionale Abschluss oder auf Englischs Closure.
Eine Funktion ist eine Closure. Und wenn Sie in irgendwelchen Programmiersprachen Beschreibungen finden,
dass da steht, diese Sprache kann Closures,
Dann wissen Sie, dass Sie in dieser Programmiersprache funktional programmieren können.
Programmiersprachen, die nur Funktionen haben, aber keine Closures oder funktionalen Abschlüsse,
die können sich für die Zwecke des funktionalen Programmierens in die Haare rein.
Also damit können wir echt nichts anfangen.
Closure ist ein Muster, da müsste etwas funktionale Puppe,
Programmiersprache fürs funktionale Programmieren nennen darf.
Okay, den metaphysischen Abschluss machen wir das nächste Mal.
Danke für die Aufmerksamkeit