Aleph und Java

Die Erstellung grafischer Benutzeroberflächen ist für jede Programmiersprache ein Muss. Wenn Java die untergeordnete Maschine von Aleph (also der V2M) ist, ist bereits mit der "Maschinensprache" die Erstellung grafischer Elemente möglich.

Natürlich werden grafische Oberflächen mit entsprechenden Mitteln wie NetBeans oder eclipse erstellt, niemand wird den Quellcode in dieser Form schreiben. Aber hier geht es um Beispiele von Aleph und grafische Oberflächen mit etwas Funktion sind sehr anschaulich für die Verwendung von Java unter Aleph.

Leider fällt es gerade Anfängern schwer, grafisch orientierte Oberflächen zu erstellen. In Java sind es die vielen referenzierenden Variablen, die den Überblick erschweren. Dabei ist es prinzipiell sehr einfach die grafischen Komponenten zu verwalten.

Dieses Beispiel ist das umfangreichste und schwierigste. Es werden viele Methoden aus Java-Objekten aufgerufen. Auch die Ermittlung von Objekten aus gegebenen Objekten wird benutzt. Etwas Kenntnis der Sprache Java ist also von Vorteil, um dieses Beispiel im Detail nachzuvollziehen.

Die Situation auf dem Stack

Ein wichtiges Hilfsmittel bei der Erstellung von Programmen ist die Kommentierung. Java erzeugt sogar die Dokumentation aus den Kommentaren. Aleph ist hier noch etwas altmodischer.

Wesentlich für ein Command ist die Situation des Datenstacks. Weil jede Anweisung eine Funktion ist, stellt der Stack die Argumentliste dar. Jede Funktion nimmt sich genau die Elemente vom Stack, die sie benötigt und legt ihr Ergebnis wieder ab. Um hier immer informiert zu sein, hat sich ein bestimmtes Schema der Kommentierung als sehr hilfreich erwiesen, das Stackdiagramm.

Dabei wird jede Zeile des ausführbaren Quelltextes mit einer "vorher-nachher"- Konstellation der Daten kommentiert. Beide werden durch "-->" voneinander getrennt. Diese Kommentierung ist zwar mühsam, aber mit etwas Routine schnell "zusammenkopiert".

Ein Beispiel:

In diesem Stil sind die Kommentare in allen Beispielen von Aleph-Programmen gehalten.

Einfaches Fenster

Die Erstellung eines Fensters ohne Inhalt ist der Ansatz für die weiteren Beispiele. Bereits dieses einfache Fenster verlangt nach Funktionalität, denn der "close"-Button soll auch die Anwendung beenden.

Hier gleich der Quelltext. Er kann in die Zwischenablage kopiert und in die einfache GUI kopiert werden. Danach einfach den [Start]-Button anklicken.

// Objekt eines Frame-Windows mit Titel erzeugen

"Fenster mit Aleph"               // --> title
"javax.swing.JFrame"              // title --> name title
classify                          // name title --> class title
"{String}"                        // class title --> wrapper class title
creator                           // wrapper class title --> creator wrapper class title
build                             // creator wrapper class title --> inst
dup                               // inst -> inst inst

// DefaultCloseOperation an Frame-Window binden

"EXIT_ON_CLOSE"                   // inst inst --> name inst inst
swap                              // name inst inst --> inst name inst
fetch                             // inst name inst --> value inst
1 ndup                            // value inst --> inst value inst
"setDefaultCloseOperation {int}"  // inst value inst --> name inst value inst
call                              // name inst value inst --> inst
dup                               // inst --> inst inst

// Umfang des Frame-Windows festlegen

300                               // inst inst --> 300 inst inst
swap                              // 300 inst inst -->  inst 300 inst
200                               // inst 300 inst --> int inst 300 inst
swap                              // 200 inst 300 inst --> inst 200 300 inst
"setSize {int int}"               // inst 200 300 inst --> name inst 200 300 inst
call                              // name inst 200 300 inst --> inst

// Frame-Window anzeigen

"show {}"                         // inst --> name inst
call                              // name inst -->
.S                                // Stack sollte leer sein

Es wird ein JFrame-Fenster erzeugt, ohne eine einzige Variable zu verwenden. Bei pre- und postfix Notation, also bei funktionaler Programmierung, gilt:

Speichere nicht was auch ermittelt werden kann!

Im hier vorliegenden Fall ist jedoch bereits der Ansatz falsch. Mit GUIs verhält es sich wie mit mathematischen Formeln – sie werden von innen nach außen gelöst. Das JFrame ist praktisch die äußere Klammer einer GUI und sollte deshalb auch erst ganz am Ende der Sequenz stehen. Leider wird das Erscheinungsbild aber immer benötigt, um die einzelnen Schritte in ihren Auswirkungen zu kontrollieren. Es wird also immer auf einen Kompromiss hinauslaufen.

Die sichtbare GUI

Die sehr einfach gehaltene GUI, die im download von Aleph vorhanden ist, dient vorrangig als Beispiel. Hier wird wird es besprochen.

Der Ansatz

Zunächst werden die grundsätzlichen Schritte festgelegt. Einige der hier aufgeführten Punkte mögen trivial erscheinen, jedoch liegen bereits in diesem frühen Stadium der Entwicklung Ursachen für unerwünschte Verhaltensweisen.

  1. Es wird ein Rahmen-Fenster (JFrame) benutzt.

  2. Es wird „DefaultClose“ zum Schließen des Fensters verwendet.

  3. Der Inhalt (ContentPane) wird durch einen eigenen Container (hier ein Panel) ersetzt.

  4. Das Rahmen-Fenster übernimmt die Ausrichtung der Komponenten.

  5. Die Anzeige erfolgt unmittelbar nach dem Aufbau.

Das "main"-Programm (es ist von Aleph getrennt) muss noch über die Dateien informiert sein.

Als Eingabestrom wird nur die "oberste" Datei übergeben, denn aus ihr werden weitere geladen. Der Name der "obersten" Datei ist "gui_en/baseGUI.vvm".

Weil auch neue Anweisungen erstellt werden, wird vorher die Colon-Anweisung aus der Datei "KernelSec.vvm" gelesen.

public class testV2M {
 public static void main( String[] args) {
 engine.V2M v2m = new engine.V2M();
  v2m.inp = v2m.reader( "\"KernelSec.vvm\"      load");
  v2m.process();
  v2m.inp = v2m.reader( "\"gui_en/baseGUI.vvm\" load");
  v2m.process();
 }
}

Das "main"-Programm zeigt die einzelnen Schritte. Dem Eingabestrom "inp" wird ein "reader" übergeben. Danach wird der Eingabestrom mit "process" abgearbeitet.

Der gemachte Ansatz umfasst 5 Schritte, die in der Datei "gui/baseGUI.vvm" in Form von Aleph-Sequenzen umgesetzt sind. Diese Sequenzen werden in den folgenden Abschnitten ausführlich besprochen.

Schritt 1: Erzeugen des Rahmen-Fensters

Hier fällt der Unterschied von einfacher Instanzierung und Creation auf. Es wird eine Methode zum Aufbau des Objekts benutzt, die ein Argument verlangt. Diese Methode wird zunächst über die geforderten Argumente bestimmt und dann wird das Objekt mit "build" instanziert.

"Aleph in use" // --> title

"javax.swing.JFrame" // title --> name title

classify // name title --> class title

"{String}" // class title --> wrapper class title

creator // wrapper class title --> creator wrapper class title

build // creator wrapper class title --> frame

Der Begriff "wrapper" stammt aus Java und bedeutet "einwickeln / verpacken". Die V2M von Aleph benutzt diese Angabe zweifach; einmal um die entsprechende Methode zu finden und dann um die Argumente auf dem Stack so zu "verpacken", wie die Methode es erwartet.

Jetzt eine Instanz der Klasse JFrame auf dem Stack vorhanden. Sie besitzt bereits einen Titel, ist aber nicht sichtbar und hat keine Angaben über das Verhalten beim Schließen.

Schritt 2: Verhalten beim Schließen

Am Anfang der Entwicklung sind kaum besondere Verhaltensweisen beim Schließen eines Fensters zu beachten. Dateien sind nicht zu aktualisieren, Threads nicht über den eigenen Weggang zu informieren, es kann einfach verschwinden.

"EXIT_ON_CLOSE" // frame --> name frame

1 ndup // name frame --> frame name frame

fetch // frame name frame --> value frame

1 ndup // value frame --> frame value frame

"setDefaultCloseOperation {int}" // frame value frame --> name frame value frame

call // name frame value frame --> frame

Hier wird einfach die "default"-Methode der Klasse über das statische Field "EXIT_ON_CLOSE" indiziert und an das Objekt delegiert.

Schritt 3: Inhalt des Fensters festlegen

Der Inhalt eines JFrames ist im sog. ContentPane vorhanden. Dieser Container wird hier einfach durch einen neuen (ein Jpanel) ersetzt. Aufbau und Inhalt dieses Panels wird in der Datei "gui_en/panel.vvm" festgelegt. Nachdem diese Datei gelesen und die enthaltenen Anweisungen bearbeitet wurden, ist auf dem Stack ein JPanel vorhanden.

"gui_en/panel.vvm" load // frame --> panel frame

1 ndup // panel frame --> frame panel frame

"setContentPane {java.awt.Container}" // frame panel frame --> name frame panel frame

call // frame panel frame --> frame

Mit der Methode "setContentPane" wird dieser "Container" der neue Inhalt des Fensters.

Schritt 4: Komponenten ausrichten

Der Inhalt eines Fensters unterliegt normalerweise einem umfangreichen "Layout Management". Erst nachdem alle Komponenten entsprechend dem jeweiligen Layout angeordnet wurden, stehen die Ausmaße des Fensters fest.

dup // frame --> frame frame

"pack {}" // frame frame --> name frame frame

call // name frame frame --> frame

Die Methode "pack" durchläuft die gesamte Baumstruktur der Fensters und ruft für jeden Container wieder die pack-Methode auf. Dort wird der jeweilige Manager für das Layout bemüht. So erfolgt die Ausrichtung, wie bei der Lösung eines Terms, von innen nach außen. Die Container stellen dabei die Klammerebenen dar.

Schritt 5: Fenster Anzeigen

Es bleibt nur noch, das aufgebaute Fenster mit der Methode "show" anzuzeigen.

"show {}" // frame --> name frame

call // frame -->

Weil es in diesem Beispiel aber um die Zusammenhänge geht, wird eine Ausnahme gemacht. Die gesamte Programmierung achtet auf Trennung von Anzeige und Funktionalität. Dieser Ansatz entspricht etwa der Trennung von Format und Inhalt bei modernen Textsystemen. Bis jetzt stand Format im Vordergrund.

Das Wesentliche der Anwendung ist demnach der Inhalt eines Fensters. Bisher ging es nur um die Präsentation; vergleichbar mit der Suche nach einem Rahmens für ein Gemälde. Der Rahmen mag "was her machen", den Preis aber bestimmt der Inhalt.

Die letzte Zeile der Datei "gui_en/baseGUI.vvm" lautet:

"gui_en/actions.vvm" load

Hier wird nach dem Aufbau des gesamten Fensters mit seinen Inhalten die Funktionalität erzeugt. Diese Position wurde gewählt, weil Desktop-Anwendungen stets einer Baumstruktur folgen (sollten). Das erzeugte Fenster ist eine solche Anwendung und seine Komponenten unterliegen einer Baumstruktur.

Im Vorgriff auf die folgenden Abschnitte wird die angestrebte Struktur bereits hier gezeigt. Damit wird die Übersicht erleichtert. Außerdem werden die Komponenten deutlich, welche über Funktionalität verfügen oder davon betroffen sind.

Aus der Kombination von Baum- und Tabellenstruktur wird deutlich, dass nur die Actions an den Positionen 7, 5 und 9, 5 Einfluss auf das JTextField an Position 4, 4 haben.

Diese Darstellung hat sich für das schnelle Auffinden von Komponenten innerhalb einer Instanz komplexer Container sehr bewährt. Trotzdem wird in diesem Beispiel der alte Weg über Variablen gewählt.

Der Inhalt des Fensters

Wieder wird das Erscheinungsbild in den Vordergrund gestellt, diesmal aber müssen funktionale Elemente (z.B. Buttons und Actions) berücksichtigt werden.

Zu diesem Zweck muss eine Aufstellung der benötigten Komponenten gemacht werden. Eine Analyse bestehender Oberflächen hilft, die unbedingt benötigten Elemente zu bestimmen. Es ergeben sich überraschend wenige.

  1. Ein Textbereich zum Eingeben des Programms.

  2. Ein Button zur Umsetzung des Programms.

  3. Ein Button zum löschen der Eingabe.

Puristen können auf den dritten Punkt verzichten, denn bei Programmen handelt es sich immer um fehlerfreie Zeichenfolgen. Fehlerfrei ist relativ. Frei von welchen Fehlern; syntaktischen, grammatikalischen, orthographischen semantischen oder stilistischen?

Aleph besitzt keinerlei Ansprüche derartige "Fehler" zu beurteilen. Aleph "läuft" oder "läuft nicht"; der Verfasser (Programmierer) hat immer recht.

Deshalb besteht ein Recht auf Irrtümer. Diese sollen schnell zu beseitigen sein und deshalb ist Punkt 3 unverzichtbar.

Zusammengefasst kann die Problematik in die Abschnitte

Einige Punkte können wieder in mehrere Abschnitte unterteilt werden. Zuerst jedoch der Aufbau des Panels aus der Datei "gui_en/panel.vvm":

// Instanzierung



"javax.swing.JPanel" // --> name

classify // name --> class

instantiate // class --> panel



// Layot-Management festlegen



"java.awt.BorderLayout" // panel --> name panel

"gui_en/layout.vvm" load // name panel --> panel



// Eingabefeld im Panel positionieren



"CENTER" // panel --> name panel

"gui_en/where.vvm" load // name panel --> panel where panel

"gui_en/textfield.vvm" load // panel where panel --> field panel where panel

"gui/insert.vvm" load // field panel where panel --> panel



// Panel mit Buttons ins Panel



"SOUTH" // panel --> name panel

"gui/where.vvm" load // name panel --> panel where panel

"gui/buttpanel.vvm" load // panel where panel --> panel panel where panel

"gui/insert.vvm" load // button panel where panel --> panel

Die Instanzierung eines Panel-Objekts erfolgt hier über den einfachen Creator. Eine Unterteilung in Creator-Methode und "build" ist also unnötig.

Nach der Instanzierung des Panels wird als Layout Management das Border-Layout für den Container (Panel) angefordert. Weil Layout-Management häufig verwendet wird, ist hierfür die Datei "gui_en/layout.vvm" vorhanden. Diesem Layout-Manager werden die Container für "Eingabefeld" und "Buttons" übergeben.

Layout festlegen

Die Sequenz geht von den Angaben "name" (des Managers) und einem "container" aus. Bezeichnungen in den Kommentaren sollten stets die allgemeinsten sein. Diese Sequenz ist in einer eigenen Datei vorhanden, weshalb statt "panel" hier "container" verwendet wird.

1 ndup // name cont --> cont name cont

swap // cont name cont --> name cont cont

classify // name cont cont --> class cont cont

instantiate // class cont cont --> layout cont cont

swap // layout cont cont --> cont layout cont

"setLayout {java.awt.LayoutManager}" // cont layout cont --> nmng cont layout cont

call // nmng cont layout cont --> cont

Dieser Abschnitt bringt also einen Layout-Manager, über Angabe von "name", und einen Container über die Methode "setLayout" zusammen.

Jetzt brauchen nur noch die zukünftigen Komponenten des Containers dem Layout unterworfen zu werden. Bei dem hier verwendeten Manager wurde "Border"-Layout verwendet, womit die Ortsangaben der Komponenten "NORTH", "SOUTH", "EAST", "WEST" und "CENTER" sind. Für andere Manager sind natürlich andere Ortsangaben nötig.

Ort des Einfügens

Namen von Methoden oder Sequenzen sollten einem Bezug zu ihrer Aufgabe enthalten. Deshalb trägt die Sequenz zum Einfügen einer Komponente hier den Namen "gui_en/where.vvm".

Hier wird vorausgesetzt, dass die Bezeichnung der Ortsangabe (Nord, Süd ...) und der Container mit dem entsprechenden Layout auf dem Stack liegen.

1 ndup // name panel --> panel name panel

"getLayout {}" // panel name panel --> name panel name panel

call // panel name panel --> layout name panel

fetch // layout name panel --> where panel

1 ndup // where panel --> panel where panel

Weil es sich bei den Ortsangaben im „BorderLayout“ um Klassenvariablen handelt, werden die Fields aus dem im Container vorhandenen Layout-Manager geholt. Mit "getLayout" wird der Manager aus dem Container ermittelt und mit "fetch" das entsprechende Field der Ortsangabe.

Einfügen von Komponenten

Auch das Einfügen von Komponenten wird aus einer Datei übernommen. Ihr Name ist "gui_en/insert.vvm". Wegen der allgemeinen Verwendbarkeit wird sie bereits an dieser Stelle besprochen. So der Bezug mit dem Layout-Management bestehen. Es wird jetzt von einer vorhandenen Komponente "comp" ausgegangen, die in den Container über die Methode "add" integriert werden soll.

swap // comp panel where panel --> panel comp where panel

"add {String java.awt.Component}" // panel comp panel --> name panel comp panel

call // name panel comp panel --> comp panel



// Vorsicht! Die Methode add gibt die Komponente zurück.



drop // comp panel --> panel

Die letzte Zeile ist sehr wichtig! Weil die Methode "add" stets die eingefügte Komponente zurückliefert. Alle bisher verwendeten Methoden waren vom Typ "void" und gaben nichts zurück. Das Schema ist stets "wo, was, einsetzen".

Damit ist die Integration abgeschlossen. Die gleichen Sequenzen werden sowohl für den Bereich des Textes als auch für den Bereich der Buttons verwendet.

Eingabefeld bereitstellen

Eine "JTextArea" wird in ein "JScrollPane" eingebettet. So ist es möglich Zeilen und Spalten über den sichtbaren Bereich hinaus einzugeben und mit den "Slidern" den Sichtbereich zu verschieben. Die "Slider" werden erst bei Bedarf aktiv.

"javax.swing.JTextArea" classify // --> field



// TextField in Variable ablegen



"input" variable // field --> field

dup "input" is // field --> field



// Zeichensatz des TextFields bereitstellen



"Monospaced" 0 12 // field --> [parms] field

"gui/font.vvm" load // [parms] field --> font field



// Zeichensatz binden



1 ndup "setFont {java.awt.Font}" call // font field --> field



// Zeichen pro Zeile festlegen



70 1 ndup "setColumns {int}" call // field --> field



// Zeilenanzahl festlegen



20 1 ndup "setRows {int}" call // field --> field



// TextField mit ScrollBars versehen



"javax.swing.JScrollPane" // field --> name field

classify // name field --> class field

"{java.awt.Component}" // class field --> wrapper class field

creator // wrapper class field --> creator wrapper class field

build // creator wrapper class field --> pane

Auf eine Besprechung zur Bereitstellung des Zeichensatzes in der Datei "gui_en/font.vvm" kann wohl verzichtet werden. Wichtig ist in der Sequenz ist nur, dass die JTextField-Komponente in der Variablen "input" gespeichert wird.

Buttons bereitstellen

Die Buttons sind in einem eigenen Panel untergebracht. So können beide Buttons als Komponenten in das große Panel integriert werden. Auf die Besprechung zur Erstellung eines Panels mit zwei Buttons wird verzichtet, denn alle wesentlichen Schritte wurden bereits gezeigt. Jeder der beiden Buttons wird in einer Variablen "abgelegt". Die Namen dieser Variablen sind "button1" und "button2".

Zur besseren Übersicht sind hier noch einmal alle Variablen aufgelistet:

input:

Der Eingabebereich, realisiert als JTextArea.

button1:

Schaltfläche für die Ausführung der Anweisungen im Eingabebereich.

button2:

Schaltfläche zum leeren des Eingabebereichs.

Verhaltensweisen der Buttons

Wird auf einen Button geklickt, soll eine ganz bestimmte Aktion ausgeführt werden. Hierfür gibt es bei Aleph eine eigene Klasse namens "vAct".

Diese Klasse ermöglicht die Erstellung von "Actions" und deren Bindung an Komponenten (hier Buttons). Die Formulierung des erforderlichen Programms erfolgt in der Sprache von Aleph.

Zunächst die Aufgabe des „Startknopfs“:

Wenn der Knopf gedrückt wird, soll der Inhalt des Textbereichs als Sequenz von Aleph-Anweisungen angesehen und entsprechend behandelt werden.

Der Text muss also der V2M zum lesen übergeben werden. Es wird der einfachste Weg gewählt, womit der Text aus der Anzeige einfach als String auf den Stack gelegt wird. Diese Aufgabe übernimmt das folgende Command namens „start“:

: start
input
"getText {}"
call
;

Die Variable "input" (siehe: „Textbereich bereitstellen“) ist der Textbereich der Anzeige. Damit stehen auch die Methoden dieses Objekts zur Verfügung. Der Aufruf der Methode "getText" legt den Text aus der Anzeige auf dem Stack ab.

Ein Objekt der Klasse vAct benötigt drei Argumente. Vor der Instanzierung müssen auf dem Stack folgende Daten vorhanden sein:

ein Command:

cmnd

TopOfStack

eine V2M:

v2m


Beschriftung des Buttons:

label


Die Bereitstellung der beiden untersten Elemente ist am einfachsten. Ein String mit der Beschriftung "Start" und das Command "envionment" stellen die ersten erforderlichen Objekte bereit.

Schwieriger ist es eine Anweisung auf dem Stack abzulegen. Wenn der Name direkt angegeben wird, führt die V2M das Command sofort aus. Es muss also ein indirekter Zugang gewählt werden. Dazu wird zunächst der Name "start" als String auf dem Stack abgelegt. Danach wird die Anweisung "find" gegeben.

"start" // --> name

find // --> true cmnd

Die Anweisung wird gefunden und auf dem Stack liegt demzufolge ein true und das start-cmnd. Das Ergebnis der Suche (true) ist uninteressant und wird einfach mit „drop“ entfernt. Das true kann einfach entfernt werden. Die gesamte Sequenz für die Bereitstellung der Argumente zur Instanzierung eines vAct-Objekts lautet also:

"Start" envionment "start" find drop // --> cmnd v2m label

Nachdem nun die Argumente auf dem Stack liegen, steht einer Instanzierung nichts mehr im Weg. Die Vorgehensweise entspricht genau der von anderen Objekten.

"engine.vAct" classify

stellt die Klasse bereit.

"{String engine.V2M engine.command}"

Bescheibt die Argumente beschrieben für den

creator

damit

build

die Instanz erzeugt und auf dem Stack ablegt.

Damit liegt auf dem Stack eine Action (vAct-Instanz) bereit, die nur noch an eine Komponente gebunden werden muss.

Actions an Komponenten binden

Weil auf dem Stack ein vAct-Objekt liegt und es sich dabei auch um eine "Action" handelt, kann die Bindung einfach über

button1 "setAction {javax.swing.Action}" call

erfolgen. Genau die gleiche Vorgehensweise wird nun für den [Clear]-Button angewendet, wobei natürlich statt des "start"-Commands ein "clear"-Command erwendet wird.

Eine Besonderheit ist noch zu beachten. Die Anweisung "start" gibt einen String zurück, die Anweisung "clear" legt einen leeren String ab (im Eingabefeld). Beide Commands werden von vAct-Instanzen verarbeitet. Diese Objekte verlangen stets einen String, der als Eingabestrom von der virtuelle Maschine verarbeitet wird.

Die "clear"-Anweisung soll aber gerade den Eingabestrom leeren und keinesfalls etwas Ausfühbares bereitstellen.

: clear
""
input "setText {String}" call
input "requestFocus { }" call
"// String muss sein!"
;

Deshalb wird einfach ein Aleph-Kommentar geliefert, der von der zwar V2M zur Kenntnis genommen, aber gewiss nicht ausgeführt wird. Es könnte auch ein String aus mindestens einem Leerzeichen sein, was aber weniger aussagekräftig ist.

Unnötiges vergessen

Im Verlaufe des Aufbaus der GUI wurden drei Variablen und zwei Commands definiert. Diese Objekte haben nur für die GUI Bedeutung, sind jedoch für die Programmierung völlig unbedeutend. Trotzdem sind sie im Wörterbuch vorhanden.

Am einfachsten ist das Problem zu lösen, wenn diese Einträge einfach vergessen werden. Es genügt, das zuerst definierte Aleph-Command (Variablen sind auch Command-Instanzen) zu mit "forget" zu entfernen, denn alle später erstellten Commands werden ebenfalls entfernt.

Allerdings werden sie jetzt nur aus dem Wortschatz von Aleph entfernt. Ihre Funktionalität bleibt erhalten. Die übersetzten Sequenzen sind auch an die Komponenten der GUI (Buttons) gebunden. Werden jetzt die Namen vergessen, sind auch nur die Namen betroffen.

"input" find drop forget

Diese Zeile ist die letzte auszuführende in diesem Beispiel. Damit ist auch das letzte Beispiel besprochen und eigene Programme können jetzt einfacher mit dem wichtigsten aller Hilfsmittel – "kopieren, einfügen" – erstellt werden.