Ja, dann herzlich willkommen. Machen wir mal weiter über
das letzte Mal, aufgehört haben.
Sie haben ja in der vergangenen Woche in den Übungen geübt,
wenn man mit dem Recket-System umgeht.
Und das ist erst der Recket-Ausdrücke geschrieben. Da müssen wir
uns nicht lange mit aufhalten. Ich werde da versuchen,
das nochmal ganz kurz zusammenfassen, darzustellen, worauf man achten muss.
Und weil ich nicht sicher bin, ob wirklich in allen
Übungen das Gleiche gesagt wurde.
Ich glaube, ich habe es nicht mal hingekriegt,
wie meinen beiden Übungsgruppen. Genau das Gleiche zu verhandeln,
weil wir immer wieder abgelenkt wird durch andere Probleme,
die so auftauchen
Aber dann wird das Hauptthema diese Woche sein.
Wie definierende Funktionen in Recket? Was ist eigentlich
so die Quintessenz der Funktionalen Abstraktionen und was sind Symbole?
Und das Aufgabenblatt, was oft heute verteilt wird,
das behandelt auch genau diesen Stoff, Symbole und Definitionen von Funktionen.
Okay. Wenn wir unser Recket-System angucken,
so wie Sie es jetzt in den Übungen schon ausprobiert haben,
dann sehen Sie, dass Sie da zwei Dinge haben.
Der Baustein, mit dem wir uns im Moment hier
in der Vorlesung am meisten befassen.
Das ist der Evaluative
Teil des Programms, des Recket-Programms, was Sie geschrieben haben,
die funktionalen Ausdrücke auswertet und dann als Resultat der Berechnung Werte zurückgibt.
Und um solche funktionalen Ausdrücke gut schreiben zu können,
haben wir als zweites eben die Programmierumgebung.
Da können wir Programme laden, da können wir sagen,
mit welcher der vielen Recket-Sprachen sie überhaupt interpretiert werden sollen und editieren und so weiter.
So waren es eigentlich von einer anständigen Arbeitsumgebung erwartet.
Letztendlich ist die ganze Bedeutung eines Recket-Programms, dass wir einen Ausdruck schreiben.
Dieser Ausdruck sagt etwas und die Bedeutung dieses Ausdrucks
ist der Wert, zu dem er reduziert wird.
Das Record-System reduziert diesen Ausdruck und gibt uns den Wert zurück.
Es ist nicht wirklich der Prozess der Berechnung,
der wichtig ist, so die Folge von Schritten,
wie wir es in der imperativen Programmierung haben,
sondern nur einen Ostdruck rein, Wert raus.
Also man kann diese Taschenrechner-Metapher dafür verwenden. Ja,
wir haben die Arbeitsumgebung mit diesen beiden Fenstern im oberen Fenster, da kommt das Programm rein.
Das haben wir den Übungen gesprochen und die erste Zeile ist wichtig,
die sagt nämlich, in welcher Programmiersprache dieser Programmtext eigentlich gilt.
Und hier unten können wir das Programm aufrufen,
auswerten lassen oder selbst kleine Ausdrücke reinschreiben,
mit denen wir erst mal testen wollen,
ob das Ganze Sinn macht, was wir uns so gedacht haben.
Wenn Sie mit dem Programm fertig sind,
dass Sie oben geschrieben haben, dann drücken Sie den Startknopf,
dann wird es gelesen, ausgewertet und danach ist alles,
was Sie hier oben definiert haben, wie unten verwendet war.
Achten Sie bitte darauf, auf die hilfreichen Meldungen, die Recketür unten gibt.
Also ich bin im Moment beim Installieren von Recket bei mir,
dem, was bitte nicht die Dinge teste,
Record-Version 7-0. Quatsch, sechs, sieben.
Wenn sie irgendetwas im Skript sehen, was ich dort geschrieben habe,
experimentiert habe und ihm ein Beispiel gegeben habe,
ich habe mich bemüht, immer diese Zeile der augenblicklichen Versionen mitzunehmen.
Also wenn sie sich sicher sind, sie haben hundertprozentig dasselbe geschrieben,
was im Skript steht, kommt trotzdem was anderes raus,
dann würde ich als Erstes die Programmversionen vergleichen in dieser Zeile.
Damit sie sehen, ob sie mit derselben Version der Sprache reden.
Das Frakti-Team ist Doppel-Record-Team, ist unglaublich kreativ und ist von
allen Programmiersprachen die schnellste Änderungsrate.
Gut, also das haben wir eben besprochen. Wenn Sie
in die Spaßanstellungen gehen, machen wir noch mal ein Racket-Fenster auf hier.
Hier gibt es ein Menü, Sprache. Ja,
und in der können Sie sagen, in welcher Sprache Ihr
Programm beschrieben sein soll, da sind ziemlich viele drin.
Ich rufe es noch mal kurz auf.
Und da sind zum einen die Lehrsprachen für didaktische Zwecke.
Bei diesen Sprachen an ist der Wortschatz des Programms abgestimmt,
auf die Erfahrungen der Teilnehmer, die in dieser Sprache des Programmieren lernen.
Sie sind Drittsemester und wir springen kopfüber Wasser entfangen mit einem vollen Sprachumfang an.
Ja, also nichts da, diese kleinen Schritte,
Anfänger, Anfänger mit Vorkenntnissen und so weiter.
Sie haben schon ein Jahr lang mindestens Informatik studiert und kennen sehr viel.
Das heißt, die Beispiele, die wir behandeln,
die gehen weit über das hinaus,
was Sie in diesem Bereich finden und was diese Sprachen bereit sind, zu akzeptieren.
Sie sind so beschränkt aus dem guten Grunde, dass man sagt,
ja Mensch, ich möchte vom Racket-System sehr hilfreiche Fehlermeldungen geben können.
Und das kann ich am besten,
wenn ich genau weiß, was ich erwarte,
was die Leute zurzeit schreiben
Deshalb in den Sprachen für Anfängern, ist verboten,
dass sie alle Funktionen definieren, ohne Parameter,
damit sie eine Fehlermeldung kriegen können, wenn die Parameter fehlen.
Im normalen Recket-Sprachschatz ist es stets und ständig der Fall,
dass man Funktionen ohne Parameter schreibt. Das ist eine Hauptart,
das zu benutzen. Deshalb verwenden sie diese Sprachen vielleicht,
wenn sie absolut keine Chance haben,
Fehler in ihrem Programm zu finden, aber sie müssen damit rechnen,
dass ihnen fehlt von dem, was sie wissen,
was Recket verstehen sollte, als Fehler angekreidet wird.
Also das Beste, was ich empfehle, ist,
dass sie hier hingehen, Sprache rekettiert.
Und dann steht am Anfang, welche Record-Versionen es ausführen soll.
Und ja, default, also als Voreinstellung,
wird da immer lange Recket reingeschrieben. Und diese Einstellung wird
uns bis Weihnachten bringen. Danach werden wir andere Sprachen verwenden.
Lesy Recket und auch vor allem das Kommende des Objekts ist dem Zählers.
Okay, gut. Also da sind wir, hier ist der Startknopf.
Wichtig ist auch noch der Stoppknopf für den Fall,
dass sie, wenn wir mit der rekursiven Programme anfangen,
kleine Ungenauigkeiten gemacht haben bei der Rekursion,
dann hauen sie den Stoppknopf und das Programm dort auf.
Also bis Weihnachten, da werden wir, etwa der Standard-Tracket verwenden
und danach möchte ich Ihnen andere ein Drecket eingebettete Sprachen beibringen.
Und dann sind wir hier bei den Sachen,
die unter Legacy oder Altlastsprachen in der deutschen Übersetzung geführt werden.
Wir werden auch über Lesirecic, Spreckchen, über Lesi
Eine Variante von Reckett ist, die denselben Programmcode,
den sie schreiben, komplett anders auswertet, als das Standard-Tracket.
Und diesen Unterschied in der Semantik, wie kann ich es haben,
dass zwei Sachen, die wir schreiben,
nicht dasselbe bedeuten, das wollen wir eben auch kennenlernen.
Die Bedeutung einer Sprache ist hier ein wichtiger Punkt. Gut. Also,
wenn wir jetzt mit Reckett einfach mal loslesen,
im Fenster, wo wir Ausdrücke reinschreiben können, ja,
wenn wir der Rechtsfall steht, größer Zeichen,
du sollst immer heißen, wir schreiben da jetzt mal einen Ausdruck hin,
da können wir jetzt eben Reckett-Ausdrücke reinschreiben.
Und als Ausdrücke zum Beispiel einfach eine Zahl,
die Zahl hat von definierten Werten, der wird ausgewertet,
kommt dieselbe Zahl wieder raus. Oder wir rufen eine Funktion auf,
wenden sie auf die Argumente 2 und 4 und hier die Exponentialfunktion,
die rechnet jetzt 2 hoch 4 und wir kriegen 6,
16 raus oder den Sinus von einer bestimmten Zahl und da bringen wir eins raus.
Und wir können die Ausdrücke Schachteln nach belieben,
solange wir die Klammern ordentlich abstimmen. Wenn wir Fehler machen,
dann kriegen wir im Interprit ja sofort eine Fehlermeldung in der Regel.
Ja, diese Fehlermeldungen sollten sie auch lesen und damit sie
eine Idee haben, was es ist.
Meistens sind sie recht treffend. In den ersten Recket-Versionen,
also von daher habe ich es noch gelassen,
wenn nicht Recket, sondern in den Skimpen-Versionen,
gab es immer ein freundliches Marienkäferchen zum Trost,
wenn eine Fehlermeldung kam, dass sie eigentlich so erschreckt hat.
Ich habe einfach, weil ich das so süß fand,
diese Art der Fehlermeldung auf den Folien gelassen.
Also hier kriegen wir die Fehlermeldung. Ich wollte hier rechnen
, zweimal fünf, ja? Prüfungsnotation, erster Apparater,
dann die zwei, die fünf. Und jetzt kriegen wir
die Fehlermeldung, dass die Variable halt zwei Unbekanntes.
Was ist passiert? Hier fehlt das Leerzeichen zwischen dem Mal und der Zwei.
Und das heißt, es wurde gelesen als eine Variable am Anfang.
Und für diese wurde keine Funktionsbindung gefunden. Was Brackett nämlich macht,
ist, Klammer auf, dann kommt der Name einer Funktion,
dann wird versucht, für diese Funktion den Wert zu finden,
die Funktion, die man anwenden soll und die Funktion mal zwei haben wir nicht definiert.
Also ist die Fehlermeldung durchaus in Ordnung. Wir hätten
es so schreiben sollen. Also bei Angyfined Identifier,
wenn sie solche Fehlermeldungen kriegen, schauen sie mal als erstes,
ob sie irgendwo Leerzeichen vergessen haben
Hier ist es ganz berechtigt, Pima Daumen kann er auch
nicht rechnen. Er beklagte die Tessa Daumen nicht kennt,
sondern die streikt schon bei Pi. Und nächste Art von Fehlermeldung,
die wir kriegen können, hier die Modulo-Funktionen,
die eins werden, nach einem anderen berechnet kann,
das ist etwas, was sie aus ihrer Java-Programmierwelt,
die sie bisher benutzt haben, auch kennen, Typkonflikt.
Die zweite Argument für Modulo sollte bitteschön eine ganze Zahl sein.
Und das ist es nicht. Eine Inschizerzahl. Symbolische Ausdrücke,
sind, haben wir ja schon gesehen,
auch in den Übungen in Pritiksmutationen und beginnen damit,
dass wir in der ersten Variante, die wir kennenlernen,
hier den Namen einer Funktion hinschreiben und dann kommen optional beliebig viele.
Weitere Symbolik Expressions. Also das hier werden gelungene,
funktionale Ausdruck, kleiner, wir wollen vergleichen,
ob es Querrot von vier, kleiner als als Querrot von fünf.
Zur Sonntags, also dieser Rechtsfall, das ist,
der Eingabe kommt im Interpritter, ja.
Das Symbikolan leitet einen Endekommentar,
ein von da bis zum Ende der Zeile wird alles
als Kommentar gelesen
Und ein Wahrheitswert beginnt mit diesem Gartenzaun. True and false
. Und ich habe es in meinen Übungen schon gesagt,
ich möchte Sie sehr bitten, deutlich zu schreiben.
Zumindest wenn es darum geht, dass sie handschriftlich irgendwo
das Resultat mit einem Wahrheitswert angeben müssen. Ja,
es gibt immer wieder Spezies, die werden sich nicht ganz entscheiden können,
wenn sie mir so auf Hassiglotschik machen wollen,
dass sie da einen senkrechten Strich mit einem Quersprüchen machen.
Und wir sollen uns entscheiden, ob wir das als Truhe der False werten.
Also in der Klausur sind wir ziemlich gemeint und nehmen immer dann
Von zwei möglichen Deutungen, die, die falsch ist.
Das heißt also immer sehr deutlich, wenn es zu tru
sein soll, so rumschreiben und beim Episodes.
Und wenn sie immer noch nicht sicher sind,
ob wir mit unserem Auffassungs- und Begriff Vermöge in der Lage sind,
ihr Truhe der Falls zu erkennen,
dann schreiben sie es auch noch in Klammern dahinter,
was sie gemeint haben, dass gar keine Zweifel da sind.
Also kleiner, gleich und so, das sind Operatoren,
spezielle Funktionen, die zahlen, abbilden und die uns dann,
die eben nur auf Zahlen angewertet werden können.
Also verwenden Sie bitte nicht dieses Gleichheitsprädikat mit dem Gleichheitszeichen,
wenn sie Wahrheitswerte vergleichen wollen oder so, dann brauchen sie typspezifische Gleichheitsprädikate.
Also das hier gilt auf, das hier gilt auf Zahlen,
ja. Okay, Ausdrücke können geschachtelt sein, ja.
Und in der Prefix-Situation haben wir immer die Klammerung. Und deshalb haben wir keine Operatorpräzedenzen,
wie sie sie aus der, besprachen wir Java,
C und so weiter kennen, wo wir in Fix-Notationen verwenden.
In den meisten Programmiersprachen oder sagen wir mal so,
ich kenne keine, die es anders macht, Wenn Sie Infix-Notationen haben,
dann gibt es Operatorpräzedenz, dass Sie Klammern vermeiden können.
Funktrechnung vor Strichrechnung und so etwas hier. Das entfällt,
aber das bietet uns die Chance, dass eine Funktion wie Plus
mehr als zwei Operatoren nehmen kann. Also wir können schreiben,
Plus eins, das wird wunderbar gerechnet,
wird eben 1 plus 0 gerechnet oder plus 1,
2 oder plus 1, 2,
4. Also soweit ich es getestet habe,
können die 100 zahlen und mehr stehen.
Es hängt von der Implementation ab,
wie lang sie das machen können,
ohne dass sie mit dem Plus eben
nur zwei Werte binden können
Genauso bei der Multiplikation. Auch da ist es möglich,
auch für größer und kleiner. Okay,
wenn ich es auf den Folien so schreibe,
heißt das evaluiert zu, also hier steht die Symbolik Expression,
die ausgewertet werden sollen und hier rechts steht,
was rauskommt oder zwischen so ein Pfeil.
Ja, das ist also keine Recket-Syntac, sondern einfach Notation auf den Folien.
Ein paar Versuche mit Variablerzahl von Argumenten für Operatoren.
Also selbst ein geklammertes Plus ist nicht etwa die Plusfunktion,
sondern die Plusfunktion angewendet auf ihr neutrales Element.
Null und da kommt null raus
Auch wenn wir vergleichen, können wir mehrere Dinge auf einmal vergleichen.
Wir können auch die Sortierordnung hier testen für viele Argumente,
also kleiner und größer, brauchen nicht viel im Java
zwischen den beiden Argumenten stehen und genau zwei brauchen,
sondern wir können hier eine Sortierfolge feststellen.
Okay. Ja. Geschachtete Ausdrücke sollten wir bitte ordentlich schreiben.
Also diejenigen, die jetzt,
wenn sie das Programm eine Woche später weiterentwickeln müssen,
werden sich freuen,
wenn sie
es gemacht haben
Und wir, die wir ihre Aufgaben korrigieren sollen,
freuen uns auch, wenn sie ordentlich formatiert sind.
Das Recket-System hat auch eine Formatieroption, also sie können
das Einrücken, alles Einrücken von Recket machen lassen.
Also so ist es deutlich besser zu sehen,
was hier geschieht und was verglichen wird,
als wenn sie das alles in eine Zeile schreiben würden.
Also das ist hier ein Horror und ganz schlecht zu lesen,
aber Recket würde das so zurechtdrücken, wenn sie es verlangen.
Kommentare, also sie haben einmal diesen Zeilen-Ende-Kommentar,
der ist ganz praktisch, wenn sie an irgendeiner Stelle sagen wollen,
Grill, das steht hier nur,
weil diese Bug im Compiler ist
Können Sie die Bedeutung des Programms, was es lösen soll,
in diese Zeichen reinsetzen am Anfang?
Man kann auch eine Kommentarvox einfügen im Mym-Menü-Special. Gibt es
die Möglichkeit, ins Third-Box? Bitte verwenden Sie das nicht für Dinge,
die zwischen Reckett verschiedenen Recket-Versionen hin und her gehen müssen. Also zum Beispiel,
wenn Sie jetzt Ihre Aufgaben gelöst haben und wollen Sie an die Tutoren,
in den Übungsgruppen schicken,
damit Sie das korrigieren und in die Punkte gut schreiben,
dann ist es immer ein Graus,
wenn diese Kommentarboxen drin sind
Es gibt zwei Möglichkeiten, wie Shift gehen kann.
Zum einen kann der Mähler diese Kommentarboxen zersemmeln und nicht vernünftig übertragen.
Und wir können es am anderen Ende ihr Programm dann nicht lesen.
Oder aber eine frühere Racket-Version können die Kommentarbox auf der Neuen
nicht lesen. Also das sind einfach Systemabhängigkeiten,
weil diese Kommentarboxen und Binärkot in den Pfeil reinbringen und es
ist kein reiner Ast gefallener ist.
Versuchen Sie Ihre Racket-Dateien als reine Asky-Datei zu halten.
Dann haben wir es einfacher,
wenn die Daten hin und her
gehen sollen
Gut, wir können zum einen natürlich, das ist das,
was Sie aus anderen Programmiersprachen auch kennen,
vordefinierte Funktionen verwenden, vordefinierte, sind taktische Schlüsselworte.
Ja, so wie es quer rot, Sinus,
Cousinus, das ist alles da.
Aber der Spaß beginnt ja erst, wenn wir die eigenen Funktionen schreiben.
Und die eigenen Funktionen definieren wir während der Sitzung oben im Editor-Fenster.
So, und da kommen wir jetzt zum Punkt Funktionale Abstraktion
. Was ist mit Funktionen eigentlich gemeint? In den Übungen
haben Sie schon kennengelernt, wenn man mit die Feinfunktionen definieren kann.
Ja, und so sollten Sie es eigentlich auch machen
Wir sollten uns bei der Gelegenheit den Landeabstraktor anschauen und überhaupt
das Sprachelement Lamda versuchen zu verstehen, weil wir das später brauchen.
Also wenn wir applikativ programmieren, haben wir, wie eben schon gesagt,
die Grundfunktion. Wir haben Mittel zur Kombination von Therm.
Ja, wir können zusammengesetzte Funktionen definieren und wir können den
Definitions- und Wertebereich einer Funktion beschreiben. Das ist,
der Punkt hier ist viel wichtiger in den emperativen Sprachen als in den Funktionalen,
weil in den Funktionalen wird es Haben wir keine Verpflichtung zur Typ-Definition,
habe ich schon gesagt.
Wir sollten es aber zumindest im Kommentar für diejenigen,
die unsere Funktionen anwenden sollen, deutlich machen,
was der Wertebereich der Funktionen ist, für die Argumente und fürs Resultat.
Okay. Und wenn man als erstes auf die Namensgebung als Mittel zur Abstraktion.
Wenn wir in einem Programm mit irgendetwas hantieren wollen,
dann müssen wir es der Funktion übergeben können und dazu müssen wir es referenzieren können.
Und dazu verwendet man in der Regel einen Namen.
Ja, man gibt dem Kind einen Namen, hey,
du bist Peter und es soll verarbeitet werden.
Dann sagen wir Peter, der Funktion so und so,
nimm dieses Argument und verarbeite es.
Sie kennen aus der Welt der objektorientierten Programmierung in Java auch,
dass wir Dinge verarbeiten können, die nicht benamst wurden.
Anonyme Klassen und so weiter, Dinge, die wir nur einmal brauchen.
Die taufen wir nicht unbedingt gleich. Aber wenn wir etwas mehrfach brauchen und in der späteren Verbindung Das,
was wir brauchen, nicht mehr im Detail bekannt sein muss,
sondern wir wollen immer nur sagen,
wir nehmen das Haus, wir nehmen das Auto,
wir nehmen die Straße und interessiert dich,
wie die Straße ausgebaut ist,
ob sie gepflastert ist oder aus Kopfsteinpflastern oder Kies und so weiter.
Sondern wir brauchen jetzt nur die Straße und dann bezeichnen wir
sie und verwenden sie und Feinheiten und Details sind verborgen.
Dafür benennen wir Dinge und geben ihnen einen Namen. Und dieser Name,
der steht dann in der Berechnung später für eine Blackbox,
für können Sinus aufrufen und brauchen nicht zu wissen,
welcher Algorithmus in dieser Sinusfunktion
jetzt konkret implementiert ist
Und wir haben einen Wert, der durch den Namen identifiziert wird.
Und das ist ein abstraktes Symbol, das weiter konkretisiert werden kann.
Man sieht einen Wert nicht mehr an, der entstanden ist.
Gucken wir uns das mal am Beispiel an. Bin ich hier unten,
wenn ich irgendeinen K brauche, konstante Zahl, sonst was.
Ich kann, wenn ich es benannt habe,
hier kam mal K schreiben. Und es ist mir jetzt
völlig egal, auf welche Weise das K berechnet wurde.
Hauptsache, ist es der richtige Wert?
Und ich gehe davon aus, er ist richtig.
Aber diese Berechnungsschritte im Einzelnen, die sind verborgen.
Und das ist das, was wir bei der Benennung machen
Okay. Im Regnet führen wir Namen ein, indem wir die Feinden schreiben,
uns einen Namen ausdenken und dann hier einen konkreten Wert hinschreiben
oder einen symbolischen Ausdruck, der einen Wert berechnet.
So, wenn dieser symbolische Ausdruck, die Fein ist auch ein Ausdruck,
der einen Wert hat und in diesem Fall,
wenn immer wir die Feinden verwenden, ist der Wert,
aber der undefinierte Wert.
Das heißt, in Regnet gibt alles einen Wert zurück,
wenn der Wert undefiniert ist,
kriegen wir
den undefinierten Wert zurück
Alles, was einen Wert hat, können wir in Ausdrücke reinsetzen.
Einen Defeinden können wir in Ausdrücke nur reinsetzen,
wenn dort kein Wert erwartet wird. Das ist Absicht,
also das Recket-Entwickler-Team möchte verhindern,
dass wir Definitionen einfach so kreuz und quer zwischen lange Listen von Werten,
von Ausdrücken schreiben, weil in Recket es nicht immer garantiert ist,
dass die Reihenfolge der Berechnung eingehalten wird.
Im Moment ist es eine lange Kaskade von symbolischen Ausdrücken haben, die abgearbeitet werden sollen.
Geht man normalerweise davon aus, dass diese parallel ausgewertet werden.
Oder zumindest eine undefinierte Reihenfolge. Deshalb ist es,
sollte es nicht vorkommen, dass wir Definitionen so schreiben,
dass wir erwarten, dass die Definition einen Wert zurückgibt.
Deshalb, die feinen Ausdruck selbst hat den Unifi,
hat einen Wert, aber es ist der undefinierte Wert.
Wenn wir uns Namen ausdenken, das sollte aufgrund ihrer
bisherigen Programmiererfahrung auch klar sein, die müssen eindeutig sein.
Und es ist praktisch, wenn wir damit nicht andere Dinge,
die wir brauchen, verschatten.
Also eine eigene Funktion Sinus würde ich nicht Sinus taufen,
sondern eher in meinen Sinus, damit das System Sinus noch erhalten bleibt.
Wir sollten diesen taktischen Schlüsselwörter, wie die Feinde und Beginn nicht zu variieren,
den Namen machen, sonst kommen wir auch in Teufelsküche.
Und konstanten wie True and Falls besser auch nicht überschatten.
Okay. Schreiben wir mal unser erstes Record-Programm an.
Beginnen mit langem Racket, zur Konvention. Es hat sich
in der gesamten Lispel, zu der Racket auch gehört,
eingebürgert, dass man entweder hier diese Notation für einen
langen Blog-Konmentar macht oder einfach je nach Level zahlt
Der Semikolons erhöht, um zu sagen, wie wichtig dieser Kommentar ist.
Zum Anfang des Programms würde man hier gleich preisen,
wie Kohle uns machen, damit man sieht, okay,
das ist der Hauptkommentar für das Modul.
Und wenn es wichtige Abschnitte sind,
nehmen wir zwei und innern einer Funktion dann noch eins.
Also hier wollen wir mal den Satz des Bitabinas nachrechnen.
Sie erinnern sich, akquadrat plus Bierquadrat, gleich zig Quadrat.
Und wir schreiben jetzt ein Programm, das uns das C ausrechnet,
wenn A und B bekannt sind. Wir definieren ein A,
wir definieren ein B und dann sagen wir zählt,
na klar, das ist in Amal A plus B mal B.
Und daraus die Quadratwurzel, ne? Dann haben wir jetzt C definiert.
So, sie würden jetzt im Programmmenü Ablage hingehen und ihr Programm sichern.
Und dann können sie es auch wieder laden oder sie können
es gleich durch Tabrücken der Randtaste laden, ohne es zu sichern.
Ja, und jetzt sind im Interaktionsfenster all die Variablen definiert,
nachdem wir herangedrückt haben.
Wir können C abfragen, wir können A abfragen,
wir können B abfragen.
Und das ist die Fein
Ist etwas anderes als Sinus, Cosinus, was wir gesehen haben.
Die Fein ist eine Special-Form X. Und wenn wir etwas schreiben,
was mit einer Special-Form beginnt, dann bei einer Special-Form expression.
Die Fein bindet den Wert der Variablen an ein Symbol.
Und Recket führt alle Symbole, die wir so definiert haben, in einer Symboltabelle.
Und das Geniale ist, dass diese Symboltabellen für uns zugreifbare Datenstrukturen sind.
Wir können solche Symboltabellen weitergeben an andere, damit die dieselben Symbole kennen.
Damit werden wir später noch jonglieren, aber erstmal sind wir zufrieden,
damit das Recked uns das übernimmt, dass eine Funktion,
die definiert wird, immer Zugriff auf ihre Symboltabelle hat.
Denn Tyberkräfte nicht mehr erklären, was dürfen wir als Namen verwenden,
so ziemlich alles, was uns einfällt, im Namen vorkommen dürfen,
aber nicht die Zeichen, die ein Whitespace sind vorkommen.
Also das Leerzeichen, Tabulator, Zeilenvorschub und so.
Wenn die im variablen Namen auftauchen sollten,
dann wird der Name in zwei Hälften gespalten und ist die Definition geht schief.
Aber wir können sowas schreiben, wie doller nach Euro oder Euro
nach Dollar oder ABC. Es hat sich eingebürgert,
dass man in der gesamten Lizwelt als Zeichen dafür etwas,
eine globale Variable ist, den Variablennamen mit dem Stern beginnen lässt und einen Stern enden lässt,
weil globale Variablen etwas sind, das in der funktionalen Programmierung nicht so gern gesehen wird.
Sie sind nützlich, man braucht sie auch,
aber man sollte, wenn man versucht,
ein Programm zu lesen, immer sofort sehen,
dass es gar keinen Zweck macht in der Funktion,
wo wir gerade sind,
nach der Definition dieser Variablen zu suchen,
wenn es eine globale Variable ist,
sollten wir es auf einen ersten Blick sehen können
Dürfen drin vorkommen. Selbst eine Zahl darf ein Variable,
das darf auch mit einer Zahl beginnen.
Aber eben nicht geklammert sein. Oder etwas,
was Benzen geschrieben ist, als Zahl gelesen werden könnte.
Das ist unzulässig. Das ist ein faktischer Schlüsselworte,
die sie auf jeden Fall nicht verwenden können als Funktionsnamen,
die fine and if Lamda lädt quasi quo do.
Okay, gucken Sie da mal einfach mal in die Liste
rein. Gut, ja, bei der Folie,
da bin ich mir jetzt total unsicher,
was im Moment gilt.
Groß und Kleinschreibung
Aus der Java-Welt wissen sie Variablennamen, Klassennamen und so werden nach Groß-Kleinschreibung unterschieden.
Und indirekt und lispelt ist seit der Einführung von der Programmiersprache es geben.
Es ist wie Kraut und Rüben, alle halbe Jahr ändert es sich.
Wir hatten eine lange Zeit eine friedvolle Phase,
in der Autoren, also gesagt haben,
wir sind es leichter ständig über Groß- und Kleinschreibung debattiert wird.
Sie hatten eine Option eingeführt, jeder konnte für sich selbst
einstellen. Groß- und Kleinschreibung unterschieden haben will oder nicht.
Das ging gut bis zum letzten Projekt
Kurs, den wir mit Dreck ertappen. Ich habe jetzt
in den Ferien verzweifelt gesucht, diese Voreinstellung scheint weg zu sein.
Jedenfalls in der Version 6, 6 und 6, 7.
Und in der Version, die ich hier zurzeit installiert habe,
kann ich diese Voreinstellung nicht finden.
Also zehn extra Punkte für die Übung, wenn jemand es schafft,
diese Voreinstellung wieder zu finden und mir sagen kann, wo sie ist.
Wer sie zurzeit versteckt ist. Wir haben, im Moment
ist es so, dass Racket Groß und Kleinstreibung unterscheidet.
Also da würde in der augenblicklichen Version, wenn wir A,
B, C kleingeschrieben definieren auf drei,
diese Zeile uns eine Fehlermeldung geben, dass A,
Großb, C und definiert ist und A, B,
C auch.
Und es würde kein Tool rauskommen. Im Jahr davor würde es
an ihrer Voreinstellung gehangen haben, wird Groß- und Kleinschreibung unterschieden oder nicht.
Also ehrlich gesagt, die Idee Groß- und Kleinschreibung einstellbar zu
machen im System und nicht im Programm war eine Schnapsidee.
Weil sämtliche Übungsteilnehmer, das ging quer durch die Bank,
die Hälfte hätte sich entschieden, Großkleinschreibung zu unterscheiden,
die anderen nicht.
Ich musste bei jedem korrigieren und ausprobieren
Rauskriegen oder erraten, wie sie ihren Intörper da eingestellt hatten.
Also, das Sicherste ist eigentlich,
um über alle Versionen konsistent zu bleiben, ist,
dass sie Variablennamen so vergeben, als würde große Kleinschreibung nicht unterschieden,
aber dann strikt bei einer Schreibweise bleiben.
Dann kann ihr Programm in verschiedenen Recket-Versionen übersetzt werden und hält
ein paar Jahre lang.
Okay. Gut
Jetzt gucken wir mal, wie kommen wir zu eigenen Definitionen?
Also in den Übungen haben wir gesehen,
wir schreiben einfach die Feinden Abnahme, Argumentliste,
das Ganze in Klammern und schreiben, was es tun soll.
Das ist einfach. Und dazu könnten wir auch gleich loslegen.
Aber ich würde gerne ein bisschen was über das Wesen der Funktionalen Abstraktionen sagen,
was eigentlich dahinter steckt oder was die Idee war.
Wir wollen einfach eine Klasse von Äquivalenten, komplexen Operationen einführen.
Und diese Klasse hat eben verschiedene Objekte,
die alle sich gleich verhalten,
dasselbe tun
Dieselben Werte zurückgeben. Und wenn sie dieselben Werte für die
gleichen Argumente erzeugen, dann wollen wir sagen, das ist,
wird abstrahiert zu einer Funktion, die dies für uns macht.
Und dann geben wir dieser Klasse einen Namen und können dann
diesen Namen verwenden, um unsere Berechnungen durchzuführen.
Sagen wir mal, wir haben im Matheunterricht gelernt,
wie man das Volumen einer Kugel berechnet, indem man eine Formel hat.
Und die sagt uns, ja,
wenn ich den Radius habe, kann ich das Volumen ausrechnen,
indem ich vier Dritteln mal Pi mal Radius,
mal Radius,
mal Radius rechnen
Und das muss, wenn ich es für den Radius 4 habe,
muss ich es so schreiben, für den Radius 5 so,
für den Radius 6. Und dann sagen wir, Mensch,
das sieht doch immer gleich aus,
wir machen dir mal ein kleines Kästchen hin,
da wo der Radius hinkommt.
Wir haben dieselbe Thermstruktur und müssen nur,
da wo die Kästchen sind, eben unterschiedliche Werte reinpflanzen.
Und das kann man einerseits machen,
indem man eine Variable R einführt für den Radius.
Und dann dem Radius einen Wert gibt und dann loslegt,
mit Radius 2 zum Beispiel, die feine R2 ist,
hat dem BR3 und dann rechnen wir vier Drittel mal Pi
und dann schreiben wir A2 hierhin hier
Dass diese Strukturgleichheit als Abstraktionsmittel rauszuholen, das hat Alonso Church
in seinem Lamderkalkül getan. Der hat gesagt, okay,
wir brauchen hier jetzt einen Platzzahl, diese Kästchen für Werte.
Die nennen wir gebundene Variable. Und wir führen jetzt einen Abstraktor ein,
der sagt, es soll dieser Ausdruck hier gerechnet werden.
Vier Drittel, mal Pi und dann wird ein R
genommen und am Anfang sagen wir, die gebundene Variable,
damit er das Ganze gerechnet werden soll,
notieren wir hier mit einem Lamda davor.
Also wenn wir das lesen, dann sehen wir,
das ist ein Ausdruck und das nimmt ein Argument.
Das müssen wir uns noch einen Weg finden, das zu übergeben.
Und dann können wir das ausrechnen. Und das ist
die Basis des Lamdakalkürz. Solche Objekte sind Werte, die
wir weitergeben können. Slamm der Kalbkühl kann andere Funktionen,
die nach dieser Art eingeführt sind,
auch verarbeiten und weitergeben und als Argumente nehmen.
Und die Wurzel allen Liz-Programmierens liegt genau an dieser Stelle.
Als McCasty Liz als Programmiersprache eingeführt hat,
hat gesehen mit,
was wir hier haben
Das ist doch eine wirklich tolle Programmiersprache für Mathematiker.
Wir haben das hier stehen. Wir können unsere Programme schreiben,
indem wir wesentlich in solche Länderausdrücke schreiben.
Wir brauchen jetzt nur noch einen Computer,
wir müssen eben programmieren, dass der Lamda-Ausdrücke lesen kann.
Und wir haben die beste Programmiersprache der Welt.
Das ist universell berechenbar, Äquivalenz zu Thüringen-Maschinen.
Und wir brauchen nicht groß beweisen, was es tut.
Dafür haben wir die ganze Zunft der Mathematiker,
die das sowieso schon können.
Also da sind wir fein raus. Wir haben hier wohl
definierte Semantik. Und im Radkitsch sehen diese Lamda-Ausdruck jetzt einfach
so aus
Weil dann zu George hat es so geschrieben,
den Buchstaben Blamda R. Das ist also mein Argument.
Und hier haben wir, der soll gerechnet werden mit einem R.
Und das müssen wir noch übergeben. In Racket sieht so
ein Lamder-Ausdruck so aus, damit man das auf Textsystemen gut schreiben kann.
Dürfen sie einfach Klammer aufmachen und dann im Klartext Lamnder schreiben.
Aber alle Versionen von Racket haben einen Menüeintrag,
wo sie auch dem Buchstaben Lamda ins Programm reinsetzen können.
Die können also Lamda reinschreiben für um mir nicht so einen langen Text stehen zu haben.
Also hier steht Landard, die gebundene Variable ist.
Und damit soll berechnet werden, der folgende Programmtext, vier Drittel,
mal Pi, mal R, mal R, mal R.
Was wir hier haben, ist jetzt eine anonyme Funktion.
Wir können eine solche Funktion anwenden auf Argumente, indem wir sie dahin schreiben,
wo man sonst Sinus, Cosinus oder die vordefinierten Funktionen schreibt.
Also Klammer auf. Und jetzt kommt, würde sonst Sinus
kommen von drei oder Klammer zu, würde Sinus berechnen.
Wenn wir das Das hier ist der Name einer anonymen Funktion.
Da können wir genau dahin schreiben, wo ein Funktionsnamen bestehen kann.
Also machen wir Klammer auf und dann schreiben wir Klammer,
Lamdai A. mit dem, was es tun soll,
Klammer zu und dann übergeben wir den Wert für A und
machen die letzte Klammer zu und haben die Funktion aufgerufen und angewendet.
Genauso wie es hier unten steht. Da,
wo hier das zweite Klammer aufkommt, würde so ein Sinus so
das Querroot oder irgendwas anderes stehst und hier unten steht das Argument.
Nur ist es ein bisschen unpraktisch, wenn man die Funktionen ganz oft braucht,
wenn man sie jedes Mal in voller Form dahin schreibt.
Also damit haben wir das Programm nicht gerade lesbar gemacht,
sondern eher unleserlicher. Was wir machen können, ist,
dass wir einfach die Feind nehmen und dem Kind an einen
Namen geben, kommen wir gleich drauf.
Aber sie können im Ractice anstelle des Wortes des Lamnders
eben auch noch das Lamderzeichen einsetzen.
Und wenn wir unsere Ractice-Programme so schreiben,
dann sieht es praktisch aus wie das Lamder-Kalkül.
Lamder, ja, und der Ausdruck hier. So,
und hier wird sie angewendet. Wir schreiben da,
wo sonst sie noch stehen würde,
diese anonyme Funktion hin und den Wert übergebenen Wert als Argument
Lambda-Ausdruck hat eben die allgemeine Form Lambda, dann kommen die Parameter
und dann kommt der Rumpf und so können wir sie aufrufen.
Okay. Wo kommt das Wort Lambda her im Lambda-Kalkül?
Also in der Notation von Rassel und Weithead,
als sie diese Kalkül vorbereitet hatten und entwickelt haben,
da wurden gebundene Zeichen einfach durch so Dach,
die gebundenen Variablen durch ein Dach markiert.
X Dach und damit wird X Plus X gerechnet
Aber damals, da gab es zwar die ersten Schreibmaschinen,
aber als sequenzieller Text, was ziemlich mühsam auf den ersten Maschinen,
da so ein Dach drauf zu machen.
Und als George das eingeführt hat,
um das dann eben auch in Büchern gut schreiben zu können,
hat er gesagt, ach Quatsch,
warum das Dach über das X,
ich schreibe das Dach einfach davor.
Bloß, aber das sah ziemlich komisch aus vor den variablen Namen.
Und die haben ja, also so richtig elegant ist es nicht.
Also hatte jetzt ein großes Zeichen davor gemacht, so ein großes Hütchen.
Und In der Mathematik wird dieses große Hütchen hier
aber ziemlich oft gebraucht als für alle und so weiter.
Also das passt nicht gut in die anderen Formeln rein.
Und dann hat er gesagt, na gut, du Mensch,
das sieht doch aus wie ein großes griechisches Lamda,
also nennen wir es Lamda.
Und dann hat das kleine griechische Lamda dafür genommen.
So das kleine Lamda, so. Und als McCarthy jetzt angefangen hat,
das zu erfinden, auf der Basis vom Lamda-Kalkül,
hat der Lamda einfach groß ausgeschrieben.
Ja, und so ist es geblieben. In Recket wird es
inzwischen klein geschrieben, aber ansonsten ist es genau das.
Ja, jetzt nehmen wir unsere anonymen Lamda-Objekte hier
Also anonyme Funktionen und geben denen einen Namen, definieren sie mit Voldem.
Und wir haben hier jetzt die Art, wie Funktionen definiert werden,
wie sie seit der Einführung der Programmierspraches geben,
als uns geben wir die Lehrsprache, die entwickelt wurde,
um das Liz-Programmieren, Studenten und Schülern leichter zu vermitteln.
In den ersten Lehrbüchern zu Skim gab es keine andere Art
Funktionen zu definieren als diese.
Das war die vorgesehene Art und so sollte man es machen
und man hatte den Vorteil, alle verstanden von Anfang an,
was denn Lamm der Ausdrücke sind
Okay, also das ist die rein rassige, feine Art,
wenn sie die Beziehung zur Mathematik klar machen wollen,
wie sie Funktionen definieren sollten.
Die feinen Voldem, dann kommt der Lambda-Ausdruck hin,
der es ausrechnet und man sieht hier genau,
welche Argumente übergeben werden können.
Geht. Und zum Beispiel Quadrierfunktionen würden wir dann so schreiben,
die feinen Square, Lambda, Ausdruck hier und wir haben es.
Die Äquivalente Definition, die wir in den Übungen geübt haben,
diese hier. Ja, wir können auch
einfach schreiben,
die fein
Square von X und dann da drunter, oh Gott,
es gibt kaum einen Platz hier, wo ich sicher stehen kann,
wo wir den Wert hier rein schreiben können.
Noch ein bisschen weiter weg. Gut. Okay. Sind
feine Nuancen drin, beide tun eigentlich dasselbe,
dies hier unten ist im Wesentlichen, sind taktischer Zucker,
um das Programm nicht ständig durch das Wort Lander redundant voll zu kleistern.
Aber es hat auch eine andere Bedeutung,
also diese Art ist zu schreiben, ist eingeführt worden,
in den funktionalen Programmiersprachen, die eine Normalform der Auswertung machen,
wo wir nämlich einfach schreiben, ich möchte in meinem Programm sagen,
was es bedeutet, wenn jemand Klammer aufs Quer X schreibt.
Das soll nämlich heißen,
Klammer aufs Quer X soll überall im Programmcode ersetzt werden,
durch den Ausdruck, der da drunter steht.
Also das hier ist eine denotationelle Definition, was quer von
X bedeutet. Und wenn man das so liest,
macht es auch Sinn und diese Art Funktionen zu schreiben,
führt zu kürzeren Funktionsdefinitionen,
also verwenden Sie sie ruhig
Landeausdrücke werden wir aber sehr oft noch brauchen,
wenn wir wirklich anonyme Funktionen weitergeben müssen.
Okay. Also die zweite Form ist,
rettet wirklich rein, das ist ein taktischer Zucker.
Es wird sofort in die Landerform übersetzt, aber wir sehen
es nicht. Gucken wir jetzt nochmal auf die Umgebung.
Wenn wir eine lokale Variable einführen,
ich versuche nochmal
Okay. Also wir nennen das,
was hier im Rumpf steht und ersetzt werden muss,
eine gebundene Variable, die gilt nur in der lokalen Umgebung,
das ist für sie nichts Überraschendes,
so ist es ein Jahr war in den Klassen auch,
ne?
Wir führen, wer einem Aufruf der Funktion, werden diese
gebundenen Variablen an Werte gebunden Und diese Bindung geschieht nur einmal,
sind eigentlich im Body, im Rumpf der Funktion.
Sind es eigentlich Konstante? Trotzdem bezeichnet man das in der Programmierung als Variable.
Weil bei jedem Aufruf andere Werte dastehen können, ja.
Aber wenn eine Funktion läuft und abgearbeitet wird,
dann sollen diese Werte nicht mehr verändert werden.
Im Kontext einer augenblicklichen Berechnung werden sie nur einmal gefunden und sind dann konstant.
Ja. Okay, auch das können wir auch.
Also ich glaube,
wir müssen umziehen
Vielleicht könnt ihr das Kamerateam mal helfen,
dass wir sicher die Kabel an den Tisch kriegen.
Das geht. Ich bin einfach leiser drehen. Versuchen Sie mal.
Gut. Versuchen wir es nochmal. Also bei allen Texten,
die wir jetzt geschrieben haben, haben wir noch keine Chance,
irgendwie das Programm mal abhängig von Werten, andere Werte geben zu lassen.
Also das Mindeste, was wir noch brauchen, sind Fallunterscheidungen.
Können Sie mich jetzt hinten noch hören in der Einstellung?
Gut, okay. Also wenn wir hier einfach haben wollen,
wenn irgendeine Bedingung gilt, soll das eine gemacht werden, andernfalls das andere.
In Rekic haben wir dafür mehrere Sprachelemente und die führen dazu
das Programm auch ein bisschen strukturierter aussehen kann.
Also zum einen haben wir das SIF,
ist auch eine Special Four, ja,
es wird eine Bedingung getestet und abhängig von der Bedingung wird entschieden,
ob man A oder B macht.
Dann Können wir das zum Beispiel verwenden,
um Fehlermeldungen zu geben, wenn etwas nicht erfüllt ist?
Ja, sagen wir, hier der Absolutbetrag ist größer, null.
Wenn ja, dann können wir durch Y-Teilen andernfalls geben, wenn eine Fehlermeldung.
Wenn der diese Ära-Anweisung ist ganz praktisch, wenn sie die,
mit der können sie im Fall einer Situation nicht mehr weiterrechnen können,
dann sagen, okay, Programm soll abgebrochen werden.
Ein IF muss in Rected immer beide Varianten definiert haben.
Es ist nicht so, dass man hier den Arztzweig
leer lässt
Es nicht erlaubt, es muss immer für beide Fälle was vorgesehen sein.
Für den Fall, dass der Elzzweig nicht gebraucht wird,
dann sollten von eben anderes syntaktisches Schlüsselwort nehmen, wenn,
wenn ein Test, also das, was hier steht,
wird nur ausgeführt,
wenn der Test erfüllt ist und im anderen Fall passiert gar nichts.
Wir brauchen noch lokale Variable, zusätzlich zu dem,
was wir als Funktionsargumente kommen.
In der Urform von Skim waren die auch nicht drin.
Ja, da wurde gesagt, wozu
Lokale Variable, können wir einführen,
indem wir eine Prostite, eine Funktion definieren.
Und die hat ihre Argumente und damit werden die Namen eingeführt.
So ein Lett ist, so ein taktischer Zucker für einen verkappten Lamdeeindruck.
Aber es macht es uns leichter, leichter lesbar.
Also wir können lokale Variable X einführen, Y einführen,
wie auch immer, indem wir hier eine Klammer aufmachen und zwischen diesem,
in diesem Klammernpark eine Folge von Namenswertpaaren schreiben.
Und das ist ihnen freigestellt, welche Art von Klammern sie hier verwenden wollen.
Ich nehme gern in einem solchen Lett für die Namenswertpaare,
eckige Klammern. Denn auf diese Weise sieht man besser,
welche Klammern geschlossen werden. Also hier haben wir jetzt zwei
Variablen X und Y definiert, in dieser Liste von Namenswertepaaren.
Und dann können wir hier im Rumpf dieses Letzts,
können wir X und Y verwenden, um irgendwas auszurechnen.
Das Gegenstück zum Wenn. Wir nehmen das, wenn,
wenn wir eine einseitige Verzweigung haben, wo nur im Wahrfall was geschehen soll.
Wenn wir nur den Ernstzweig haben wollen und nicht den Barfall,
dann nehmen wir das Anlass.
Außer wenn x-größer Null ist, gibt den Wert eins zurück.
Und wir haben ja noch mal einige Beispiele verletzt.
Man braucht nur eine Variable zu definieren, aber sie müssen mindestens eine definieren.
Und der Rumpf hier vom Letzt darf nicht leer sein,
da muss etwas stehen. Andere, ein Fall für,
dass ich sehr praktisch finde, sind Verzweigungen, die von vielen Bedingungen abhängen.
Da können wir die Bedingungen alle einzeln untereinander schreiben.
Und die werden sequenziell getestet. Meine persönliche Steuerreform,
immer wenn ich über den Steuerwogen sitze, denke ich,
mein Gott,
ist das kompliziert
Führen wir es mal auf diesen einfachen Fall zurück,
abhängig vom Einkommen, setzen wir ins Steuersatz fest, kein Absetzen,
kein Nichts, sondern wir haben das Ding in zehn Minuten ausgefüllt.
Und es wird auch leicht berechnet werden. Also die Funktion
Steuersatz hat einen Parametereinkommen und alle, die an einen kommen,
kleiner als 10.000 Euro haben, sollen null Prozent Steuern zahlen,
wenn das Einkommen zwischen 10.000 und 20.000 liegt,
dann haben wir 10 Prozent bei kleiner 40.000, 30 Prozent.
Und bei allem, wo das Einkommen kleiner als 180 ist,
sehen wir 45 und alle anderen,
die sollen bitteschön für den Unterhalt des Staates aufkommen.
Und da nehmen wir dann die vollen 80. Also das Konditionale ist so aufgebaut,
dass sie hier beliebige Ausdrücke hinschreiben können, die zu Wahrheitswerten evaluieren.
Die werden sequenziell getestet. Bei dem ersten,
wo die Bedingungen Zuschrift, wird das, was dahinter steht,
ausgeführt und der wird zurückgegeben, der dort errechnet wird?
Das Erz kann, muss nicht sein. Wenn sie sicher sind,
dass alles, was sie hier geschrieben haben,
erschöpfend abdeckt und es kein anderer Fall vorkommen kann,
dann können sie das erkennen und sollten sie
das Erz weglassen
Also ein Ärzt zu schreiben,
wenn es nicht nötig ist, verwirrt die Leser,
weil die alle dran dann versuchen zu grübeln, oh,
welcher Fall kann denn damit noch abgedeckt sein?
Und den gibt es gar nicht. Also,
das konditional besteht einfach darin, wir machen eine Klammer auf,
dann machen wir in eckigen Klammern oder Runden,
wenn sie es vorziehen, aber ich bin für Eckige.
Schreiben Sie eine Bedingung und dann können Sie eine Folge von
Ausdrücken schreiben. Der letzte Ausdruck, der genannt wird,
mindestens einer muss dastehen, der wird das Resultat sein.
Ja, also das, was hier zwischen steht,
vor dem letzten Ausdruck des Resultats zurückgibt,
das ist Beschäftigungstherapie für Ihren Computer
Also alles, was da geschieht, gibt keinen Wert zurückführt,
nur dazu, dass es berechnet wird, sequenziell.
Und sie können damit Sachen machen, wie das in der Ausgabe
schreiben oder einfach mal ein bisschen Rechenzeit verschwenden oder was immer.
Der Wert des letzten Ausdrucks gilt, alle anderen Resultate werden vergessen.
Außer sie modifizieren globale Variable, was sie nicht sollten.
Gut. Und die Folge der Bedingungen, es muss mindestens eine da sein.
Hier haben wir noch das Erlz, was ausgeführt wird.
Okay. Dann dieses Erlz ist eben dieser Catch all und
wir sollten ihn nur mit Sinn und Verstand gebrauchen
Also wenn sie sicher sind und beweisen können,
dass alle Bedingungen vorher die möglichen Situationen erschöpfend abdecken,
dann lassen sie das Arzt weg.
Die sollten es dann nur verwenden,
wenn ihr Programm abstürzt aus unklären Gründen und sie wollen testen.
Und dann führen sie es ein. Ja,
und vielleicht warten sie ungeduldig darauf,
dass ihr auch sowas wie mit dem Vorschleifen und so kriegen.
Die sind in Recke drin, aber es sind imperative Sprachelemente
und wir werden sie vorher erstmal nicht verwenden.
Sondern wir werden nur mit Funktionen und Rekursion rechnen
Und sehen, was da drin steckt. Also Brackett hat
ganz tolle Vorschleifen, weil Schleifen und all das ist da.
Aber das führt ja dazu, dass Dinge sequenziell ausgeführt werden und
nicht quasi parallel und dass wir wirklich eine zustandsorientierte Programmierung haben.
Und die lassen wir erstmal außen vor. Also was wir tun werden,
ist, sind Mapping-Funktionen, Filterfunktionen, eine ganze Werkzeugkastenvollfunktionen,
höhere Ordnung, denen wir Funktionen übergeben, zu verwenden,
wo man sonst zu Schleifen greifen würde.
Und da beginnt eigentlich so der richtige Spaß mit dem,
was wir in dieser Sprache
möglich ist
Gut, also das Lab verwenden wir, wenn wir Wertefunktionen
nur lokal definieren wollen. Es hat eben das Schema,
wir schreiben Lett, lüste von Namenswertpaaren und dann kommen
die Namenswertpaare und dann kommt hier ein Body.
Ich sehe gerade, ich habe hier einen Fehler im Skript.
Ich habe hier geschweifte Klamana genommen, was bedeutet,
der Body kann leer sein? Also spätestens seit der dritten
Version von Recket ist das nicht mehr zulässig.
Der Body muss irgendetwas enthalten, er darf nicht leer sein.
Im Zweifelsfall, wenn ihn wirklich nichts mehr zu tun anfällt,
was der Body tun soll,
dann schreiben sie da ein Tor rein
Damit irgendwas zurückkommt. Okay. Ein Problem,
was häufig bei den ersten Programmierübungen zu blimmen führt,
ist, wie werden die Namenswertfahrer ausgewertet?
Normalerweise werden die Argumente einer Funktion in beliebiger Reihenfolge ausgewertet.
Wir können uns nicht darauf verlassen, dass die Argumentliste in
der Reihenfolge, wie sie da steht, abgearbeitet wird.
Dasselbe gilt beim Lett. Wir müssen sich vorstellen,
wenn Sie hier schreiben, Lett X und Lett Y,
in undefinierter Reihenfolge geschieht und diese Wertbindung.
Das heißt, wenn Sie den Wert Y berechnen wollen,
dürfen Sie nicht darauf vertrauen, dass es ich schon gebunden wurde.
Es gilt als undefiniert so lange, bis die namens Wertpaarliste abgearbeitet ist.
Und dann können wir beide verwenden, X und Y.
Wenn Sie bei der Definition von Y X verwenden wollen,
haben Sie zwei Möglichkeiten. Entweder machen Sie ein geschachtetes Let,
dann ist klar, im äußersten Letwood X eingeführt,
dann führen Sie ein weiteres ein, was Y einführt.
Sie kriegen ein großes Klammergebirge, sieht nicht schön aus,
haben die Leute eingesehen und haben na gut,
dann verwenden wir hier ein zweites Lett mit einem Sternchen dahinter.
Und dies letzt Stern, das signalisiert aufgepasst.
Jetzt ist die Reihenfolge der Wertbindungen wichtig. Ich habe
die reine Lehre verlassen. Und das heißt Letztstern,
da wird das X definiert und schon in der nächsten Zeile
ist das X definiert, weil die Reihenfolge hier erzwungen wird.
Und jetzt können wir X auf das definierte X zurückgreifen und
das Y in Abhängigkeit von X definieren.
Wir können das Let auch verwenden, um Variablen,
um Funktionen zu definieren, ja.
Zum Beispiel. Können wir hier unsere Funktionen quer,
also die lokale Funktionen definieren, indem wir schreiben, es quer,
jetzt wollen wir den Namen quer definieren und als Wert übergeben wir ein Land da, ja.
Damit haben wir eine lokale Funktionsquer eingeführt. Und wenn wir
das quer jetzt im nächsten Moment auch gleich aufrufen wollen,
dann müssen wir Lettsterne sagen.
Ja, sonst wäre auch diese Funktionsquer hier
nicht definiert
Also, der Special-Form-Operator let, lokale Variable werden direkt bei
der Definition an Werte gebunden. Reihenfolge der Bindung ist undefiniert,
der so eingeführte Name ist, nur innerhalb des Let sichtbar.
Und die Variablenbindung werden dann sequenziell im Body ausgewertet.
Also die quatschen nicht die Ausdrücke, die werden im Body
schreiben, danach, die werden sequenziell ausgeführt, ja.
Der letzte Ausdruck, der ausgeführt wird im Body eines Let,
das ist mit dem Body gemeint, das,
was hier unten steht,
dies Öff zum Beispiel
Letzte Ausdruck, der ausgeführt wird,
dessen Wert kommt zurück als Wert der Berechnung des Let.
Wir können Let Express und Schachteln,
mache ich stets und ständig, führt zu guter Lesbarkeit.
So, und das Let Stern sorgt dafür,
dass wir Variablen in Abhängigkeit voneinander definieren können.
Im selben Let. Kommen wir mal zum Begriff Umgebung.
Wenn wir Namen einführen,
dann führen diese Namen auch Blöcke ein und Wertebereiche,
in denen
die Namen sichtbar sind
Wir haben die globale Umgebung, das ist das,
was das Recked-System zur Verfügung stellt. Und wenn wir direkt anfangen,
Variablennamen zu definieren, bevor wir überhaupt eine Funktion anführen,
werden die zur globalen Umgebung dazugenommen in unser Modul.
Dann haben wir lokale Umgebungen, die in Lettausdrücken eingeführt werden und
die wir in Funktionen in der Dip innerhalb einer Funktion einführen.
Und da sind die Variablen eben immer nur sichtbar innerhalb dieses lokalen Blockes.
Also jede Funktionsdefinition, die gilt auch nur in dem Kontext,
wo wir sie eingeführt haben
Und jetzt eine ganz wichtige Vokabel, also das ist die wichtigste Vokabel,
die wir eigentlich hier in der funktionalen Programmierung lernen müssen.
Funktionaler Abschluss oder auf Englisch heißt es Closure.
Wir sagen eigentlich auch im Deutschen immer das Fremdwort Closure,
aber ich habe funktionale Abschluss mal eingeführt,
weil es ein deutsches Wort gibt, das sollten wir den auch kennen.
Also wenn wir eine Funktion definieren,
dann gilt diese Funktionsdefinition im Kontext all der Variablen,
Wertbindungen, die zu dem Zeitpunkt der Definition existieren.
Das gehört zur Funktion
mit dazu
Wenn wir denselben Funktionstext in einem anderen Kontext definieren,
ist es eine andere Funktion, die auch etwas anderes tun könnte.
Also die Einheit aus unserer textuellen Definition, die wir schreiben,
die fallen Sinus so und so und all den globalen Variablen,
die in dem Moment bekannt sind,
die in der lokalen Umgebung sind,
wo wir die Funktionen definieren.
Das gehört mit zur Funktion dazu. Diese Einheit aus dem
Funktionstext und der Symboltabelle, die bekannt war zum Zeitpunkt der Definition.
Das ist der funktionale Abschluss oder die Closure
Dieser Punkt, Closure ist dann wichtig, wenn wir Funktionen
als Werte eine Berechnung erzeugen und sie an andere Funktionen übergeben.
Die nehmen eben nicht nur ihren Programmtext mit, sondern kennen
alle Werte, die zum Zeitpunkt der Definition definiert waren.
Den augenblicklichen Zustand der Berechnung in dem Moment,
wo die Funktionen definiert wurde. Und damit können wir,
wenn wir dieselbe Funktion immer wieder lokal definieren lassen,
jedes Mal ein neues Objekt bekommen, was ganz was anderes tut.
Das werden wir an vielen Beispielen sehen und das werden wir dann im Hinterkopf behalten müssen,
wenn wir Lambda-Ausdrücke als Wert nehmen und weitergeben an andere Funktionen.
Die Closures hängen natürlich davon ab, was ist wo sichtbar?
Wir gucken mal auf einen englischen Begriff Scope, Sichtbarkeit,
Sichtbarkeit ist der Programmbereich, in dem Variable textuell referenziert werden kann.
Das heißt, wir haben Bereiche,
in denen wir auf eine Variable X zugreifen können,
wo sie sichtbar ist und andere, wo sie eben verschattet ist,
weil sie zurzeit weil zurzeit ein anderes X gibt,
der uns näher ist, dass sie für uns verdeckt.
Oder weil sie in diesem Bereich überhaupt nicht definiert ist.
Wenn wir lokale Variable einführen, die denselben Namen,
haben wir eine globale Variable, verschattet sie die globale Variable.
Und wir haben, damit die es verschatten.
Dann haben wir die Lebensdauer oder den Extent von Variablen.
Also wie lange bleibt uns der Wert erhalten und können wir
mit ihrem Wert rechnen?
Auch das ist wichtig,
genau im Zusammenhang mit Closures
Closures. Dadurch,
dass wir eine Funktion definieren können und die kriegt die augenblicklich definierten Variablen mit,
ja, die kann dafür sorgen, dass Variablen,
die wir woanders längst gelöscht und verändert haben,
dass die Mund da weiterleben, in dieser Closure und weitergegeben werden.
Also prinzipiell ist es so,
Variablen in der globalen Umgebung leben unbegrenzt,
aber sie können in vielen Ausprägungen und zuständigen Zuständen in unterschiedlichen Closures präsent sein.
Also wir haben praktisch ein Fenster in die Vergangenheit,
wenn irgendeine Funktion in ihrer Vergangenheit sich gemerkt hat,
aha,
dieses A,
Hat es eben den Wert gehabt. Und normalerweise leben Variablen
nur so lange wie der Block existiert.
Aber wenn wir in diesem Block Closures definieren,
dann können Variablen über das Leben des Blockes,
in dem sie definiert wurden, hinaus weiterleben.
Das ist anders als in den Blockorientierten Sprachen,
wo nach dem Aufruf einer Funktion oder einer Methode,
wenn der Stack wieder abgebaut wird, alles weg ist.
In den Closures kann es erhalten bleiben und weitergegeben werden.
Und das werden wir dann sehen,
wenn es gebraucht wird
Okay. Das nächste Aufgabenblatt wird sich vor allem mit Zeichen
und Symbolen befassen. Und deshalb möchte ich die letzten Minuten
doch nutzen, dass wir das Thema schon mal ansprechen.
Wir werden es dann am nächsten Freitag zum Abschluss bringen.
Nochmal zurück. Wir werden also über Zeichen reden,
über Symbole und vor allem das,
was man in Recket richtig gut können muss, das quotieren,
um zu unterscheiden, ob wir ein Symbol oder seinen Werk meinen.
Ich habe hier die kleine Alice in Wanderland dahingestellt,
weil ich in den Büchern über Alice in Wanderland viele Beispiele gefunden habe,
die eigentlich mit der Bedeutung von Zeichen zu tun haben und Symbole einführen.
Okay. Zunächst mal kennen Sie aus den formalen Grundlagen
der Informatik natürlich Zeichen und Alphabetin.
Zeichen ist etwas, was mit dem beeindeutigt etwas hinschreiben könnt.
Und ein Alphabet ist ein Grundvorrat an Zeichen,
mit denen wir dann Worte aufbauen können.
Alphabet sollte immer endlich sein. Und wir können mithilfe
von Worten über einem Alphabet formale Sprachen definieren.
Racket ist eine formale Sprache über dem AlphaD-Beter-Aske-Zeichen,
das wir hier eigentlich verbinden
So, ein Zeichen ist zunächst ganz neutral, hat keine Bedeutung. Wir müssen,
wenn wir mit Hilfe von Zeichen und Worten kommunizieren wollen,
eine Vereinbarung haben, dass jeder dasselbe drunter versteht.
Und das ist eben auch der springende Punkt bei Programmiersprachen.
Wenn wir ein Programm schreiben in den Worten einer Sprache,
dann muss es etwas geben, das eindeutig diesen,
eine Bedeutung zuordnet. Also der Rechner muss das tun,
was wir von ihm erwarten und dasselbe drunter verstehen,
was wir gemeint haben.
Für die Nachrichtenübertragung muss man den Zeichen eben per Vereinbarung
eine Bedeutung zuordnen
Wie maschinelle Informationsverarbeitung, dass wir diese Bedeutung,
wenn sie denn existiert, auch noch effizient und in endlicher Zeit,
solange es einen interessiert, errechnen können.
Das heißt, das Ausrechnen der Bedeutung eines Programms muss in
endlicher Zeit möglich sein und nicht nur in endlicher Zeit,
sondern in der Zeit, die ein Benutzer bereit ist, zu warten.
In der muss das Programm ja auch noch ausgeführt werden.
Ein Symbol, das Wort kommt aus der Symbiotik, der Bedeutungslehre für Zeichen.
Da werden Symbole als ein Paar aus einem Zeichen und einer Bedeutung aufgefasst.
Ja, an die Bedeutung des Symbols hängt von der Verwendung
ab und wird frei vereinbart und diese Vereinbarung ist eben das, was berechenbar sein muss.
In Lizb und allen Sprachen, die danach kommen,
muss Lizb abgeleitet sind, arbeiten wir im Wesentlichen mit solchen Symbolen.
Also Beispiele aus dem täglichen Leben, die Sie kennen,
dass die Bedeutung vereinbart sein muss.
Wenn wir in einem Land sind, wo Kopf nicken Nein bedeutet,
sollten wir nicht mit dem Kopf nicken, mit Kopfschütteln,
ein heftiges Ja ist, sollten wir eben nicht im Kopf schütteln, wenn wir Nein meinen.
Das heißt, man muss über eine Vereinbarung haben, was damit jeweils gemeint ist. Oder wir haben hier,
wollen mal den Buchstaben L angeben, wir haben Flackenalphabet,
würde man diese Flasche hier nehmen,
aber wenn sie mit ihrem Boot auf See sind und haben gerade ein anderes gerammt und es kommt ein Boot an,
das die Flacke L zeigt, würde ich in dem Fall erwarten,
dass es jetzt durch der Buchstabe L sein soll,
sondern es ist das Zeichen, dass die Wasserschutzpolizei ihnen signalisiert,
anhalten,
wir wollen an Bord kommen.
Also das hat bestimmte Zeichen, haben in bestimmten Situationen eine andere Bedeutung.
Okay, wir können Viele Symbole haben, die alle dasselbe bedeuten.
Das finden wir auch schon in den Zeichensätzen hier offen.
Rechner, ja. Okay, das ist nicht so.
Ja, ein erstes kleines Beispiel aus Alice in Wanderland,
über die Bedeutung von Zeichen. Alice diskutiert hier mit dem
Hamdidamji. Haben die damit die? Hat Glory gesagt.
Und Alice sagt, I don't know what you mean by Glory.
Alice said, Hamdidamji smiled contemptusly. Of course,
you don't to like tell you. I mean,
does a nice not down
argument for you. But Glory, doesn't mean,
a nice not
down argument alice objected
I use a ward haben die dampty set in a rather's gonful ton.
It minds just what it choose it to me,
nizer more no less. Und das ist eben auch
genau das Problem mit den Programmiersprachen. Irgendjemand hat beschlossen,
was das bedeuten soll und das müssen wir wissen.
Also Symbolen in Reckett, das sind zunächst mal wirklich Philipp-Palle einfach.
Die werden einfach dadurch mächtig, dass wir tolle Sachen mit ihnen machen.
Also Symbole sind einfache Definitionen, Objekte,
die genau dann identisch sind, wenn ihr Name gleich geschrieben wird.
Und an der Stelle entscheidet nur noch
die Vereinbarung über Großknappschreibung und Kleinschreibung,
was damit gemeint ist
In Reckett ist jede Variable ein Symbol.
Aber auch jeder Name, den wir einfach so hinschreiben,
aus Jux und Dollerei, das ist ein Symbol.
Wir müssen ihm noch nicht mal einen Wert gegeben haben.
Wir müssen nicht gleich eine Variable definieren.
Wir haben schon mal eine Stützfunktion, die heißt Zimbel.
Ja, und das ist ein Typ-Prädikat. Und damit können
wir testen, ist etwas ein Symbol oder nicht.
Und wir haben die Funktion EQV, also oder EQV,
die kann Symbole vergleichen. Das soll kurz für Äquivalent sein
, ja. Wir haben die Möglichkeit,
wenn wir einen Text gelesen haben und Strings haben,
dass wir aus diesem Text symbolefrei erzeugen können,
das ist das Tor
Zu der Möglichkeit, dass wir Rektprogramme zur Laufzeit erzeugen.
Also String to simple. Das erzeugt uns ein neues Symbol aus
einem String, den wir uns ausgerechnet haben oder gelesen haben.
Und Simble to String sagt uns, was der Name des Symbols ist,
das uns übergeben wurde. Damit können wir Symbole fragen,
wie sie heißen. Auch das ist sehr gut. Also,
wir definieren ja einfach Macht mit einem Symbol Recic,
mit Variable, geben den Wert 1, wir definieren Java,
auch als Eins soll ja gleichberechtigt sein, können fragen,
ob Record ein Symbol ist.
Und halt stopp, Moment
Wir haben hier oben, habe ich so eben gerade gesagt,
wir haben ein Symbol Recket definiert. Ja, jetzt fragen wir,
es trackt jetzt ein Symbol und da kriegen wir Fords zurück.
Ja, was ich Ihnen nicht gesagt habe, ist,
wie Funktionsauswertung vor sich geht.
Das muss man uns im Detail noch mal angucken.
Haben wir Zeit dafür? Ja, wunderbar.
Wir schreiben hier den Aufruf einer Funktion hin, Symbol.
Ja, und übergeben ein Argument. Und was Recket macht,
ist vorgezogene Auswertung. Hier steht ein Ausdruck, der Ausdruck Recket
. Der wird erst mal ausgewertet, ihr diese Funktion,
die sie übergeben bekommt. Und soll ich verhindern,
dass wir alles mehrfach auswerten müssen, vorgezogene Auswertung, Eagle Evaluation,
also Rected wird ausgewertet und zu was wird es ausgewertet eins.
Also praktische Funktionen, Simble hier, das Argument eins zum
Testen und eins ist kein Symbol, eins ist eine Zahl.
Zweite Zeile, kleiner, aber feiner Unterschied. Hier steht
jetzt ein Portierungszeichen vor Rected. Durch dieses Quotierungszeichen sagen wir,
nehme wörtlich, was ich hier übergeben habe,
der hatte es nicht aus
Und wenn wir dann fragen, ist das,
was wir hier wirklich übergeben haben, ein Symbol,
dann sagt Trecket too. Das quotierte, crected wird übergeben,
als das Symbol Recket und das ist es dann.
Wir sehen es auch hier, wenn ich hier eingebe Recket,
dieser symbolische Ausdruck wird ausgewertet und ergibt eins,
diplotiert der Ausdruck, wird nicht ausgewertet.
Da kriegen wir das Symbol Recket zurück. Wir können jetzt
fragen, ob Precket und Java gleich sind mit EQV.
Was sagt uns Recket
Reckelt evaluiert zu eins, Java evaluiert zu eins, eins ist.
Gleich zu eins, also wahr. Wenn wir es aber
quotiert übergeben, dann haben wir hier zwei unterschiedliche Symbole,
die nicht gleich sind. Sie sind nicht gleich beschrieben.
Und damit bringen wir eben den Bird Volks zurück. So,
wenn wir jetzt ein Symbol übergeben haben und wollen es dringend draus machen,
lassen Symbol-to-String, übergeben, quotiert hier Java,
kriegen da Java raus, String to Simble vom String Java,
gibt uns ein neues Symbol Java, das ist noch undefiniert.
Und ist das, was hier zurückkommt,
tatsächlich ein Symbol,
Symbol angewendet auf String to Samble
Ja, das hat geklappt. Wir können, wie Sie jetzt,
an diesen Beispielen gesehen haben, Symbole selbst übergeben.
Also die Variable selbst und nicht den Wert der Variablen.
Und deshalb brauchen wir eben Diskutierungszeichen, dass uns sagt,
ob wir ein Symbol oder seinen Wert meinen.
Und wenn immer wir Textverarbeitung machen,
in Recket werden wir im Wesentlichen einfach Listen von Symbolen haben.
Und damit ist das Parsing dann so einfach,
dass wir, da keine große Mühe reinstecken müssen,
weil die Recket-Umgebung uns selbst
das zerlegt
Aber wir brauchen jedenfalls eine Notation,
ob wir ein Symbol oder seinen Wert meinen.
Das können wir ja auch aus der natürlichen Sprache, wenn wir uns unterhalten.
Ich denke jetzt gerade mal an die Feuerzangenwohle,
so wenn es auf die Weihnachtszeit zugeht,
wird es ja meist im Audi Max nochmal aufgeführt.
Und da gibt es den schönen Satz, der Pfeiffer ist ein frecher Lümmel.
Und was ist damit gemeint? Der Hanspfeiffer, dieser freche
Lümmel. Wenn man aber jetzt Dedicto sagt,
spricht und nicht der Reh,
dann Pfeiffer schreibt sich mit drei etwas,
dieser freche Lümmel gesagt hätte
Jetzt der Name gemeint. Und das ist genau das,
was das Quotieren für uns in Recket macht in Wesquotierungszeichen machen,
dann meinen wir die Variable selbst, das Symbol.
Und wenn wir das Quotierungszeichen weglassen,
meinen wir den Wert, der dran gebunden ist.
Und das ist die Funktion Quote, die das macht.
Ich bin hier gerade überlegen. Ich habe hier Standardfunktionen geschrieben
. Quote ist eine Special Form und keine Funktion.
Eine Standard-Special Form. Das muss ich mit bemerken,
Knoten, Taschentuch,
dass ich das ändere
So, wir können Quotierungen kaskadieren. Und dann fängt
der Spaß eigentlich erst richtig an, wenn wir damit,
wenn wir die Symbole mit Namen von Symbolen
praktisch wie Ketten von Referenzen oder Pointern verwenden können.
Wir können die erst mal definieren, ein Symbolfee,
das ist in Recket schon vordefiniert,
aber hier definieren sie das mal trotzdem mal, ja.
Fragen, Pi, kriegen wir den Wert zurück?
Bei QuotePea kriegen wir das Symbolpea zurück.
Wenn wir viermal quotieren, kriegen wir es dreifach quotierte
Pea zurück
Wir können hier einen erothmetischen Ausdruck quotieren. Und den
können wir später wieder evaluieren lassen. Also jedenfalls haben wir
hier praktisch eine Liste, die den erothmetischen Ausdruck darstellt.
Wir haben hier das ein quotiertes Auto,
du bist ein wohl Auto, wenn wir Auto noch nicht definiert haben,
schreiben es einfach so hin, kriegen wir einen Ondefinierten, Identifier.
Das Evaluieren, Moment, das macht. Die Standardfunktion E-Wail.
Jedes Recket-System hat eingebaut die Funktion Evel und das ist eigentlich die,
die immer im Entschörpretter läuft und das,
was wir da reintippen,
fleißig für uns auswertet
Die können wir, wenn wir im Entorpritter sind,
auch selbst aufrufen, um Dinge, die wir zusammengebaut haben,
evaluieren zu lassen. Wir haben hier quotiert hingeschrieben,
Quote plus 2-2. Wir können sagen, Evel,
Quote plus 2-2 oder wir haben irgendwas eingelesen,
was diesen Text darstellt.
Dann wird das hier evaluiert, ausgewertet, als hätten wir
es so in den Enteurpritter geschrieben und es kommt der Wert zurück.
Also der Evalue dann, der läuft eigentlich im Top-Level des Entorpritters,
in der sogenannten Read-Evel-Print-Loop, liest immer,
was wir schreiben, führt das Ausdruck,
das liest und so weiter,
das läuft so endlos vor sich hin
Dann diese Auswertungsschleife, die können wir sehr gut parametrisieren,
indem wir dem Ivellen mitgeben,
welcher Bindungskontext wir variablen gerade gelten sollen und so weiter.
Aber das soll uns erst mal nicht kümmern. Okay. Nehmen wir
mal Beispiele. Ich definiere hier jetzt eine variablen Name.
Susi, ja? Und jetzt geben wir dem Namen noch
einen Namen, Name von Name, den nennen wir den.
Wenn wir es auswerten, Name von Name,
kommt das Symbol Name zurück, was wir hier hatten.
Und wenn wir dann nochmal sagen, Ivell,
Name von Name, dann kriegen wir tatsächlich den Wert zu
Sie zurück
Nö, Gottes Bauen fürs Bauen, Herr. So,
klasse jemandem sagen, Herr, da ist Söhne,
Frau, uns hat die Möglichkeit, das Leben zu bauen.
Und davon bisher. Im Ernst, das ist nö,
das ist nö, das ist nö, das ist nö,
das ist nö, das ist nö, das ist nötig.
Versorge es, auch welches Gelegens, was vielleicht schon ein
neues Vorwärtssyologe. Oh, das ist ein nö,
nö, nö, nö,
Zuerst. Und da ist es so, dass ich mich
auch okay, ich bin jetzt von der Versorgung gefetzt.
Okay, also Alice in Wanderland ist voll von Fragen über
Symbolik, Symbiotik, Bedeutung und logischen Widersprüchen.
Und das beschreibt aber hier ziemlich genau die Situation,
die ich versucht habe darzustellen. Wir können einem Namen,
einen Namen geben und dem Namen dieses Ding wieder einen neuen Namen
und so weiter und müssen uns dann durchhandeln, was eigentlich gemeint ist.
Ich habe es hier mal versucht, in Reckett nachzumachen.
Voice and Means ist der Name von der Sitting on a Gate.
The aged it man
Ist der Name von Ways and Means.
And Headdogs Eyes is the name of the hidged men.
Wir haben jetzt Fragen, Headdogs Eyes, The Hidget Man zurück,
wenn wir es evaluieren lassen, kriegen wir Ways and Means.
Und wenn wir das nochmal evaluieren lassen, dann kriegen wir
Assitting on a Gate and the tunes my owns invention.
Rechnen wir mal mit Symbolen um symbolische Werte zurückgeben zu können.
Ein Beispiel, was Tick weniger trivial ist.
Die kennen auch aus dem Geometrieunterricht in der Schule noch Dreiecke.
Und man hatte unterschieden zwischen Dingen, die kein Dreieck sind,
über die am meisten
nicht gesprochen
Gleichseitige Dreiecke gleich schenklige und schiefwinklige. Und jetzt schreibt mir mal
ein Programm, dem geben wir drei Seitenlängen. A,
B, C. Und dann sollen es uns sagen,
ob das ein Dreieck sein kann oder schiefwinklink oder gleichzeitig und so weiter.
Und wir haben die Vereinbarung, dass wir die Seitenlängen übergeben mit A,
kleiner, gleich B, kleiner, gleich C.
Also das C ist immer die längste Seite. Ja?
Okay. Und das schreiben wir jetzt mal als Analyse-Programm. Das nennen wir deshalb auch einfach Analyst,
hier ein kleiner Kommentar, A, kleiner, gleich,
B, kleiner, gleich C. So,
und wenn jetzt jemand A, B, Cs übergibt,
Wir machen uns nicht mal die Mühe zu prüfen,
ob das eingehalten wurde.
Sondern wir gehen davon aus, dass sich die Leute
eine Spezifikation halten beim Übergeben. Ansonsten knallt es eben.
Jetzt machen wir ihn konditional. Denn A, plus B,
kleiner ist als die längste Seite, dann sagen wir kein Dreieck.
Wir geben das Symbol kein Dreieck zurück. Wenn A gleich zäh ist,
dann sagen wir, wir haben ein gleichzeitiges Dreieck.
Moment, wir haben Bier gar nicht abgefragt. Warum können
wir da sicher sein, dass Bier gleich lang ist?
Genau, wir vertrauen hier auf unsere Zusicherung. A,
Kleiner, gleich Bier, Kleiner, gleich C. Wenn A,
gleich C ist, bleibt dem wenig viel anderes übrig,
als gleich zu sein.
Genau. Gut erkannt. So, wenn es also nicht gleichzeitig ist,
dann testen wir noch ab A, gleich B ist,
dann sagen wir gleich schändlich.
Und wir dürsten noch testen auf B, gleich C,
es sagen will, gleich schenkt ihr den in allen anderen Fällen,
sagen wir schiefwindlich.
Wird dieses konditional, wird hier sequenziell abgearbeitet. Deshalb geht
das gut. Ja, und dann als drei Testfälle,
da kriegen wir auch die erwarteten Werte raus.
Also sie sehen eine ganz typische Verwendung
Gebt gerne in Reckett ein Symbol als Wert zurück. Und man kann an diese Symbole,
wenn man die vorher als Variable definiert hat,
zusätzliche Werte ranbinden, die man bei der Gelegenheit mit übergibt.
Ja, die Auswertung in einem Kiste,
mit Käse habe ich noch nicht angesprochen,
aber auch das ist ganz praktisch, wenn wir Fallunterscheidungen haben.
Beim Käse können wir eine Liste von möglichen Werten für
eine Variable angeben und dann wird je nachdem,
welcher Wert aus der Liste es ist, entschieden,
was zu tun ist.
Hier habe ich also Als Fall eben das Geräusch gewählt,
was ein Tier von sich gibt. Also, als die erste Variante,
wenn der Wert des Tiers der Symbolhund ist, dann soll Wau-Wort zurückkommen.
Wenn es Katze oder Tiger ist, also hier kann der
Liste mit mehreren Werten stehen, dann kommt Mayor zurück.
Und wenn es eine Kuh ist, kommt Mut zurück.
Und so können wir hier Werte aufzählen und für alle Fälle,
die gleich sind, immer hier den Wert geben.
Auch das wird von oben nach unten durchgearbeitet und der
erste Wert, der gefunden wird. Der trifft zu,
also die Symbole, die hier stehen werden,
mit EROV verglichen
Also der Ausdruck für der Reihe nach mit verschiedenen Schlüsselwerten ausgewertet,
wenn der Vergleich erfolgreich ist,
werden die Resultatausdrücke der betreffenden Klausel der Reihe nach ausgewertet.
Also hier hätten jetzt verschiedene Werte stehen können, nicht nur ein einfaches Myau.
Sondern da kann eine lange Kaskade von Ausdrücken stehen und
der letzte Wert kommt als Wert des Käse zurück.
Die letzte Klausel darf mit Erz beginnen, um alles andere abzufangen.
Okay. Also Beispiele nochmal, wir können hier Zeichen abfragen
oder numerische Werte. Und die Listen können hier beliebig
besetzt sein
Okay. Gut, noch zu den Namenskonventionen,
wenn Sie jetzt Ihre ersten Programme schreiben.
Typdeklarationen sind nicht unbedingt üblich, wenn völlig klar ist,
was der Typ ist, weil wir sollen die Typen,
da wo es nicht klar ist, natürlich als Kommentar reinschreiben.
Und wir werden später auch sehen,
wie wir dort Prädikate reinsetzen können, die die Typprüfung machen.
Schon die Namen von Funktionen sollten den Typ andeuten,
welche Art von Funktion es sich endet.
Es ist in Drecket üblich, dass Prädikate,
also Funktionen, die Wahrheitswerte zurückgeben,
dass deren Namen mit einem Fragezeichen endet
Wenn wir eine Funktion schreiben, die Werte verändert,
den Zustand der Berechnung verändert,
Seiteneffekte hat, dann muss der Name eine Warnung enthalten.
Also alle Funktionen, Standardfunktionen, Reckett, die einen Wert,
die Werte verändern können, Variablen verändern können.
Deren Namen endet sein Ausrufezeichen. Und das sollten sie auch
tun. Abgesehen davon, dass sie bis Weihnachten hin bitteschön
die Abgabe ihrer Übung niemals Modifikatefunktionen verwenden.
Sonst treiben wir die Punkte nicht gut. Wir wollen funktional programmieren.
Und wenn sie jetzt zu Anfang, wo sie dabei sind,
dem funktionalen Programmierstil reinkommen, nach Java-Art schreiben.
Erst ist A gleich eins, dann ist A gleich zwei,
dann ist A gleich drei. Das sind eben Dinge,
die nicht funktional sind oder das würden wir dann nicht als richtig werten. Aber es gibt natürlich Situationen,
wo man tatsächlich mal einen Wert ändern muss, sagen wir,
sie haben eine Liste mit zehn Millionen Elementen und sie brauchen eine neue Form davon,
wo nur ein Element einen anderen Wert hat, dann ist es einfach schwach,
das ganze Teil zu kopieren und beim Kopieren dann einen geänderten Wert einzusetzen.
Dann greift man zur Modifikate. Aber das kommentiert man und das
macht man dadurch sichtbar, dass man den Namen der Funktion,
die etwas modifiziert, mit einem Bang enden lässt, ja?
Dann haben wir Konversionsfunktionen, hatten wir schon drüber gesprochen.
Also, ja, würde ich Sie bitten,
da einfach solchen Rechtsfall in den Namen zu setzen zwischen den beiden Typen,
zwischen denen konvertiert wird, ja?
Okay. Unser nächstes großes Thema über die Datenabstraktionen sein,
da werden wir über Datentypen reden.
Welche Datentypen kompatibel sind, welche nicht? Es ist im
weiten Teilen so, wie sie es Osyava gewöhnt sind,
also können wir da auch ziemlich schnell durch.
Wir dürfen nur solche Daten Objekte an Werte übergeben,
die an Funktionen übergeben, die kompatibel sind mit dem, was erwartet wird.
Das muss kommentiert sein. Also nicht Äpfel mit Birnen verknüpfen
und so was, dann kriegen wir eben Tälermeldungen.
Also im Wesentlichen werden wir das nächste Mal die Datenabstraktion
durchsprechen und dann zur Semantik von Recket übergehen.
Damit erstmal für heute Schluss. Danke für die Aufmerksamkeit