Programmieren in Simplicity

1 Erste Schritte

Ein Simplicity-Programm besteht aus einer Aneinanderreihung von Funktionsaufrufen. Jede Funktionsaufruf besteht aus dem Namen einer aufzurufenden Funktion und einer Menge an Funktionsargumenten. Im folgenden klassischen Beispiel ist write der Name der Funktion und "Hallo Welt!" das Funktionsargument:

write "Hallo Welt!&nl;"

Wie in den meisten Programmiersprachen, so gibt es auch in Simplicity Variablen. Es gibt aber in Simplicity keine spezielle Anweisung, um einer Variablen einen Wert zuzuweisen. Stattdessen kann man einfach eine Wertzuweisungsfunktion erzeugen. Der Ausdruck !Name erzeugt eine Funktion zum Setzen der Variable Name. Um der Variablen einen Wert zuzuweisen ruft man diese Funktion auf und übergibt ihr den zu setzenden Wert.

Somit kann man eine Zuweisung ganz einfach wie folgt schreiben:

!x 5

Im obigen Programm wird zunächst eine Funktion zum Setzen von x definiert (!x). Anschließend wird diese Funktion dann sofort mit dem Wert 5 aufgerufen, was zur Folge hat, dass x den Wert 5 zugewiesen bekommt.

Probieren wir uns nun an einem kleine Programm, das die Fläche eines Rechtecks berechnet und ausgibt:

!Breite 10
!Höhe 7
!Fläche Breite*Höhe
write Fläche "&nl;"

Die ersten beiden Zeilen bringen nichts Neues; den Variablen Breite und Höhe werden die Werte 10 bzw. 7 zugewiesen.

In der dritten Zeile sehen wir einen arithmetischen Ausdruck: Breite*Höhe. Der * ist das Symbol für die Multiplikation, der Variable Fläche wird also der Wert 10*7 (= 70) zugewiesen.

Abschließend wird in der vierten Zeile der Inhalt der Variable Fläche (70), gemeinsam mit einem Zeilenvorschub "&nl;" ausgedruckt.

Wie man sieht sind in Simplicity auch deutsche Umlaute (ebenso die Sonderzeichen aller anderen mittel- und westeuropäischen Sprachen) als Namensbestandteile zulässig.

Schreibt man mehrere Argumente hinter einen Funktionsnamen, so werden diese nicht wie in vielen anderen Programmiersprachen üblich, durch Beistriche getrennt!

2 Grundkonzepte

In Simplicity dreht sich alles um Funktionen - ihre Definition und ihre Verwendung.

Eine Funktion bekommt vom Aufrufer eine Menge an aktuellen Argumenten übergeben, die im Zuge des Funktionsaufrufs den formalen Parametern der Funktion zugewiesen werden.

Weiters liefert eine Funktion eine Menge an Rückgabewerten an den Aufrufer zurück.

Es ist auch möglich, dass Funktionen keine formalen Parameter haben, und/oder keine Werte an den Aufrufer zurück geben. Funktionen, die keine Werte retournieren nennt man auch Prozeduren.

2.1 Prozeduraufruf

Der Aufruf einer Prozedur ist denkbar einfach:

Prozedurname Argument-1 Argument-2 ... Argument-n

Somit kommen wir direkt zu unserem ersten, klassischen Beispiel:

write "Hallo Welt!&nl;"

"&nl;" ist eine Spezialzeichensequenz, eine solche beginnt stets mit einem "&"-Zeichen und endet mit einem Strichpunkt. Dazwischen steht der Name der Spezialzeichensequenz - in unserem Fall nl für "new line".

Benötigt ein Prozeduraufruf mehr oder längere Argumente, als in eine Zeile passen, so kann man die Argumente auch über mehrere Zeilen verteilen; die Folgezeilen müssen dabei aber gegenüber der ersten Zeile (alle um den gleichen Betrag!) eingerückt werden:

write "Dieses Beispiel "
  "macht nicht "
  "viel Sinn" "zeigt aber, "
  "wie man mehrere Argumente über mehrere "
  "Zeilen verteilen kann."

2.2 Variable

Variable speichern beliebige Objekte.

Variablennamen bestehen aus Buchstaben, Unterstrichen (_) und Ziffern. Ein Variablenname muss stets mit einem Buchstaben beginnen und mit einem Buchstaben oder einer Ziffer enden. Unterstriche können also nur im Inneren eines Namens verwendet werden. Es dürfen auch keine zwei Unterstriche direkt aufeinander folgen. Als Buchstaben dürfen auch alle Speziallaute westeuropäischer Sprachen (Latin-1) verwendet werden, insbesondere also auch die deutschen Umlaute und das scharfe S.

Groß- und Kleinschreibung sind relevant; Breite, breite und BREITE sind also 3 verschiedene Variablennamen.

2.3 Zuweisung

Variablen können Objekte zugewiesen werden. Dies kann auch wiederholt geschehen, d.h. der Inhalt von Variablen kann geändert werden.

Die Zuweisung in Simplicity unterscheidet sich syntaktisch von Zuweisungen in anderen Programmiersprachen:

!Variable Wert

2.4 Arithmetische Ausdrücke

In arithmetischen Ausdrücken können wie gewohnt die mathematischen Operatorsymbole "+", "-", "*" (Multiplikation), "/" Division, "%" (Modulo) und "^" (Potenzierung) verwendet werden. Dabei gelten die üblichen Operatorvorränge, die durch das Setzen von Vorrangsklammern aufgehoben werden können.

$a 4
$b 5
write a*a+1
write (a+1)*(a-1)
write a^2 + 2*a*b + b^2

Arithmetische Ausdrücke in Operatorschreibweise müssen in Simplicity immer in einer Zeile stehen; sie dürfen sich also nicht über mehrere Zeilen erstrecken!

Achtung: Die Negation ("Vorzeichenminus") muss stets so geschrieben werden, dass vor dem Negationsminus ein Abstand (Leerzeichen) steht und hinter dem Negationsminus ohne Abstand, unmittelbar der zu negierende Ausdruck folgt.

write 3 -2

und

write 3-2

sind also unterschiedliche Anweisungen, während erstere den Text "3-2" druckt (die Zahlen 3 und -2 ohne Abstand), druckt letztere den Text "1" (die Differenz von 3 und 2).

2.5 Relationale Ausdrücke

Die relationalen Operatoren "==" (Gleichheit), "!=" (Ungleichheit), ">", ">=", "<", "<=" haben geringeren Vorrang als die arithmetischen Operatoren.

2.6 Logische Ausdrücke

Das logische Und wird als "&&" geschrieben, das logische Oder als "||". Der Vorrang der logischen Operatoren ist niedriger als der der relationen Operatoren, wobei Und einen höheren Vorrang hat als Oder.

Auch hier gelten die oben beschriebenen Abstandsregeln.

3 Variable und Namensräume

3.1 Lokale Variable

Lokale Variable können an jeder beliebigen Stelle im Programm definiert werden, einfach indem man ihrem Namen ein $-Zeichen voran stellt:

!$lokaleVariable Wert

Da lokale Variable mit dem Wert undefiniert vorbelegt sind, und der Zugriff auf einen undefinierten Wert stets zu einem Laufzeitfehler führt (der aber abgefangen werden kann), impliziert ein "$" stets auch ein "!". Das obige Beispiel lässt sich also auch in vereinfachter Form schreiben:

$lokaleVariable Wert

3.2 Lokale Konstante

Lokale Konstante können ebenfalls an jeder beliebigen Stelle im Programm definiert werden, einfach indem man ihrem Namen zwei $-Zeichen voran stellt:

!$$lokaleKonstante Wert

Lokalen Konstanten kann nur genau einmal ein Wert zugewiesen werden. Ebenso wie bei lokalen Variablen impliziert auch hier die Schreibweise "$" ein "!". Das obige Beispiel lässt sich also auch in vereinfachter Form schreiben:

$$lokaleKonstante Wert

4 Funktionsaufrufe

Es gibt 2 syntaktische Varianten Funktionen aufzurufen.

4.1 Klammersyntax

In den folgenden Beispielen verwenden wir die Funktionen sin und cos aus der eingebauten Mathematikbibliothek. Diese Funktionen befinden sich im Namensraum "math" und werden daher mit einem vorangestellten math:: geschrieben.

$alpha 0.7
write math::sin[alpha] ", " math::cos[alpha] "&nl;"

4.2 Einücksyntax

Nun das gleiche Beispiel aber ohne Verwendung von (eckigen) Klammern:

$alpha 0.7
write
  math::sin
    alpha
  ", "
  math::cos
    alpha
  "&nl;"

In einem einfachen Beispiel wie diesem ist die Einrückvariante wohl nicht wirklich angebracht, aber in komplexeren Ausdrücken kann sie die Lesbarkeit deutlich erhöhen.

Um die Einrücksyntax für Funktionsaufrufe verwenden zu können, müssen folgende Regeln eingehalten werden:

  • der Funktionsname muss alleine auf einer Zeile stehen

  • die Funktionsargumente müssen gegenüber dem Funktionsnamen (stets um den gleichen Betrag) eingerückt werden; dabei dürfen aber durchaus mehrere Funktionsargumente auf einer Zeile stehen