Yeah, me

Foto: Uwe Pirr

Informatik


previous Page home toc next Page

Programmieren in HyperTalk, Teil II

Nachdem wir im ersten Teil dieses Kurses unsere ersten Erfahrungen mir HyperTalk gemacht haben, ist es nun an der Zeit, diese ein wenig zu systematisieren. Im Gegensatz z.B.. zu C oder PASCAL ist HyperTalk eine interpretierende Programmiersprache, wie z.B. auch BASIC. Neben der dadurch in Kauf zu nehmenden relativen Langsamkeit von HyperCard ist damit auch eine gewisse Freiheit verbunden, die im strikten Gegensatz zu der Strenge von strukturierten Sprachen wie PASCAL oder MODULA-2 steht. Zwar erleichtert dies die Entwicklung von kleinen Quick & Dirty Programmen, erhöht jedoch die Gefahr, daß sich der Programmierer bei größeren Projekten in seinem unübersichtlich gewordenen Programmcode verliert. Auch dies ist eine Art von Lost in Cyberspace! Um dies zu vermeiden, sollten von Anfang an gewisse Grundregeln eingehalten werden. Glücklicherweise unterstützt HyperTalk vielfach die Möglichkeiten der strukturierten Programmierung, ohne sie jedoch zu erzwingen. Ich werde daher in diesem Kurs immer wieder Konventionen vorschlagen, die das Leben des HyperTalk-Programmierers erleichtern helfen. Erst einmal aber werden wir die grundlegenden Sprachelemente von HyperTalk kennenlernen.

Datentypen

HyperTalk kennt im Prinzip nur einen einzigen Datentyp, den Datentyp Text. Alles wird erst einmal als Text behandelt - nur wenn aus dem Kontext einwandfrei etwas anderes zu erschließen ist, wird der Text in Zahlen konvertiert. Wenn also im Script steht
	put 3*a into ergebnis
erkennt HyperTalk aus dem Kontext, daß a eine numerische Variable sein und das Ergebnis von 3*a in die Variable ergebnis geschrieben werden soll. Dies ist erst einmal sehr einfach, kann jedoch zur Verwirrung und auch zum verzögerten Programmablauf führen, da HyperTalk erst nachprüfen muß, wie z.B. folgendes Script-Fragment gemeint ist:
	put 3*a into cd fld ergebnis
Hier kann ergebnis einmal der Name des Feldes sein oder aber eine String-Variable (eine Textvariable) in der der Name des gewünschten Kartenfeldes steht. HyperTalk muß also erst einmal nachprüfen, ob irgendwo im Script vorher folgender Text stand:
	put "Summe" into ergebnis
Dies würde nämlich bedeuten, daß das Ergebnis im Kartenfeld "Summe" abgespeichert werden soll. Um hier HyperTalk die Arbeit zu erleichtern und die Ausführung des Scriptes zu beschleunigen, sollten Sie, falls ergebnis tatsächlich der Name des gewünschten Feldes ist, dies in Hochkommata einschließen:
	put 3*a into cd fld "ergebnis"
Dann weiß HyperTalk, daß ein Name und keine Variable gemeint ist und erspart sich das zeitraubende Nachsehen. Bei zusammengesetzten Namen, wie z.B. "Ergebnis alt" ist dies sowieso erforderlich. Daher sollten Sie sich diesen Hochkommata-Einschluß von Anfang an angewöhnen. Als angenehmen Nebeneffekt erleichtert es auch das Lesen von HyperTalk-Programmen.

Zusammengesetzte und strukturierte Datentypen, wie wir sie aus den oben genannten höheren Programmiersprachen kennen, sind in HyperTalk unbekannt, können jedoch, wie ich in einem späteren Beitrag dieses Kurses zeigen werde, über Felder leicht simuliert werden.


Konstanten und Variablen

Variable heißen in HyperTalk Container und müssen nicht explizit deklariert werden. So bald ein Name zum erstenmal in einem Script auftaucht, nimmt HyperTalk an, daß es sich um einen Container handelt. Da, wie oben erwähnt, HyperTalk nur den Datentyp Text kennt, kann ein Container im Laufe seines Lebens alle möglichen Werte enthalten. So kann im Script stehen
	put 3.14159/2 into piHalbe
	put line i of cd fld "Magermilch" into piHalbe
HyperTalk kennt lokale und globale Container. Normalerweise sind alle Container lokal, daß heißt nur in Bereich ihres Handles sichtbar. Wenn also in einem Script steht:
	on erstes
		put 25 into ergebnis
		...
	end erstes

	on zweites
		put "Magermilch" into ergebnis
		...
	end zweites
dann existieren zwei Variable ergebnis mit unterschiedlichem Inhalt, die beide nur innerhalb ihres Handles erstes oder zweites gültig sind.

Globale Variablen müssen dagegen explizit in jedem Handle als global deklariert werden. Im Beispielprogramm "Der blinde Uhrmacher" (siehe unten) ist der Container summe als global deklariert.

Im Gegensatz zu Feldern, deren Größe auf 32 kByte beschränkt ist, ist die Größe von Containern nur durch den vorhandenen Hauptspeicher begrenzt. Ich habe schon testweise den Inhalt eines ganzen Buches in einen einzigen Container eingelesen und diesen dann im Hauptspeicher indiziert (was dann sehr schnell geht). Allerdings hatte der Rechner einen Hauptspeicher von ca. 150 MByte und dies dürften wohl die wenigsten Leserinnen und Leser dieses Kurses zur Verfügung haben. Und auch, wenn die Operationen im Hauptspeicher schneller ausfallen, ziehe ich es in der Regel vor, größere Datenmengen über Felder zu realisieren. Einmal kann ich im Fehlerfalle immer noch in den Feldern nachschauen, was mein Script da eigentlich hineingeschrieben hat und zum anderen können auf Feldinhalte ohne die umständliche Global-Deklarationen alle Handle zugreifen.

HyperTalk enthält einige eingebaute Konstanten, wie z.B. empty für die leere Zeichenkette "", pi für 3.1459265358979323864 oder space für das Leerzeichen. Eine vollständige Aufzählung entnehmen Sie bitte Ihrem Manual. Eine explizite Konstantendeklaration hingegen kennt HyperCard nicht. Entweder werden Sie durch Zuweisung und gegebenenfalls. einer Global-Deklaration, z.B.

	global epsilon
	put 0.00001 into epsilon
realisiert oder besser, wie ich weiter unten noch zeigen werden, über Funktionen.

Schleifen und Kontrollstrukturen

Die Verzweigung if <Bedingung> then <Anweisung> else <Anweisung> haben wir im ersten Teil unseres HyperTalk-Kurses schon kennengelernt. Alle durch andere Programmiersprachen bekannten Schleifenkonstrukte werden in HyperTalk durch das Schlüsselwort repeat eingeleitet. Es gibt im Einzelnen:
	repeat forever
		<Anweisungen>
	end repeat
Dies ist die bekannte und berüchtigte Endlosschleife. Sie kann nur mit exit repeat, pass oder return wieder verlassen werden.
	repeat for i times
		<Anweisungen>
	end repeat
Diese Schleife wird i mal durchlaufen, wobei der Programmierer sicherstellen muß, daß i einen ganzzahligen Wert (Integer-Wert) enthält. Ansonsten erfolgt eine Fehlermeldung.
	repeat with i = <Startwert> [down] to <Endwert>
		<Anweisungen>
	end repeat
Diese Schleife entspricht der aus anderen Programmiersprachen bekannten Zählschleife. Bei jedem Durchlauf erhöht sich der Wert der Variable i um 1. (Bei down to wird der Wert der Variable um 1 vermindert). Die Schleife wird verlassen, wenn <Endwert> erreicht ist.
	repeat until <Bedingung>
		<Anweisungen>
	end repeat

	repeat while <Bedingung>
		<Anweisungen>
	end repeat
Die obere Schleife wird solange durchlaufen, bis (until) die Bedingung wahr (TRUE) ist, die untere Schleife solange wie, die Bedingung wahr ist. Der Unterschied leuchtet nicht nur Programmieranfängern nicht so ohne weiteres ein: Beide Schleifen sind beinahe gleich, nur wird die obere Schleife immer mindestens einmal durchlaufen, während die untere gar nicht durchlaufen wird, wenn die Bedingung schon beim ersten Durchlauf TRUE ist (abweisende Schleife). Dieser Unterschied kann unter Umständen wichtig sein, meistens ist er jedoch ohne Bedeutung. Auch in den Beispielprogrammen habe ich einmal die "until"- und einmal die "while"-Schleife nur aus didaktischen Gründen gewählt.

Prozeduren und Funktionen

Wie wir gesehen haben, werden die einzelnen Script-Teile eines HyperTalk-Programmes durch Handles der Form
	on <handle>
		<Anweisungen>
	end <handle>
gegliedert. Dabei kann ein Handle sich auch selber aufrufen. Dieses Prinzip der Rekursion werden wird in einem späteren Beitrag dieses Kurses behandeln. Ein Handle wird aktiv, sobald die entsprechende message, sei es eine Systembotschaft, wie mouseUp, sei es eine benutzerdefinierte Botschaft, bei ihm eintrifft. Ebenso wie Prozeduren, können auch einem Handle Parameter übergeben werden, z.B.
	on initialisiere startwert
		put startwert into cd fld "Start"
	end initialisiere
Dieses Handle kann dann zum Beispiel mit initialisiere(27) aufgerufen werden. Jedoch kann ein Handle keine Parameter zurückgeben. Würde also startwert in obigem Handle verändert, hätte dies keinen Einfluß auf das aufrufende Script - es sei denn, startwert wäre in beiden Scripten als global vereinbart gewesen. Dann hätte es aber nicht als Parameter übergeben werden müssen.

Funktionen werden statt mit on mit dem Schlüsselwort function eingeleitet. Der Rückgabewert wird mit return zurückgegeben. Hätte HyperTalk nicht schon einen eigenen, so könnten wir z.B. folgenden kleinen Zufallszahlengenerator programmieren (nach Reiser/Wirth: Programmieren in Oberon, Bonn (Addison-Wesley) 1994):

	on initSeed seed
		global z
		put seed into z
	end initSeed
	function uniform
		global z
		put 16807 into a
		put 2147483647 into m
		put m div a into q
		put m mod a into r
		if gamma > 0 then
			put gamma into z
		else
			put gamma + m into z
		end if
		put z*(1/m) into z
		return z
	end uniform
Das Handle initSeed initialisiert den Zufallszahlengenerator. Dieser Initialwert ist global deklariert und damit auch für die Funktion uniform sichtbar. Damit der Generator funktioniert darf und muß initSeed nur einmal aufgerufen werden. uniform ist als Funktion realisiert und der Aufruf von
	put uniform() into zufall
liefert, wenn man Wirth und Reiser glauben darf, gleichverteilte Zufallszahlen im Intervall ]0..1[. Ich möchte in einem späteren Beitrag einmal diesen und andere Zufallszahlengeneratoren mit dem in HyperTalk eingebauten vergleichen.

Wie wir an obigem Beispiel sehen, liefert HyperTalk auch die Ganzzahl-Operatoren mod und div: Ihre Funktion wird deutlich, wenn wir uns die normale Division ansehen (5 : 2 = 2,1). Als Ganzzahloperator liefert mod den Rest (nach dem Komma) einer Division zweier ganzer Zahlen (also: 5 mod 2 = 1), div den ganzzahligen Anteil (vor dem Komma) einer Division zweier ganzer Zahlen (also: 5 div 2 = 2).

Das Evolutionsspiel

Abb. 1: Das Evolutionsspiel

Mit diesem Wissen sind wir nun in der Lage, unser erstes komplexeres HyperTalk-Programm zu schreiben. Es ist ein Spiel, mit dem die Statistik der Evolution untersucht wird und stammt aus dem Buch von Manfred Eigen und Ruthild Winkler: Das Spiel. Naturgesetze steuern den Zufall, München/Zürich (Piper-Verlag) 1975. Es ist ein sehr empfehlenswertes Buch mit vielen weiteren naturwissenschaftlich interessanten Simulationsideen. Bei Eigen/Winkler ist das Evolutionsspiel als (von Menschen ausgeführtes) Würfelspiel mit bunten Kugeln vorgeschlagen, wir hingegen überlassen das Würfeln lieber HyperTalk und ersetzen die Kugeln durch Zahlen. (Wenn wir nach der nächsten Folge die grafischen Möglichkeiten von HyperCard erkundet haben, bleibt es dem Leser überlassen, das Spiel in einer grafischen Variante zu programmieren.) Bei diesem Spiel siegt immer eine Farbe (eine Zahl) und es ist ein Modell für das darwinsche Survival of the fittest..

Die Spielregeln: Auf einem 6 x 6 großem Feld werden anfangs gleichverteilt die Ziffern von eins bis sechs ausgelegt. Wir erledigen dies mit Hilfe des in HyperCard eingebauten Zufallszahlengenerators:

	repeat with i = 1 to 6
		repeat with j = 1 to 6
			put random(6) into neu
			put neu into item i of line j of cd fld~
			"Spielfeld"
			add 1 to cd fld (neu + 3)
		end repeat
	end repeat
Zuvor haben wir das linke große Feld "Spielfeld" angelegt und die Schriftgröße so gewählt, daß das Feld ungefähr ausgefüllt wird. Und in diesem Feld sehen wir eine weitere Besonderheit von HyperTalk: Auch Matrizen (für PASCAL-Programmierer: zweidimensionale Arrays) werden in HyperTalk über Felder realisiert. Dabei sind line die Zeilen und item die Spalten der Matrix. Wie wir an der Zeichnung sehen können, werden die einzelnen Elemente durch Kommata getrennt in dem Feld abgespeichert.

Während des Spiels erwürfeln wir mit zwei Würfeln die Zeile und Spalte der Matrix. Danach erwürfeln wir genauso ein zweites Feld. Dort wird dann die darin vorhandene Ziffer durch die Ziffer des ersten erwürfelten Feldes ersetzt. Jede erwürfelte Ziffer verdoppelt sich also auf Kosten einer anderen auf dem Spielfeld. Sie können das Spiel spielen, so oft sie wollen: Nach einer gewissen Zeit wird immer eine Ziffer, die das gesamte Spielfeld besetzt hält, als Sieger hervorgehen.

Jetzt weiter zur Realisierung: Nach dem Spielfeld habe ich das Feld "Anzahl" unten rechts neben "Spielzüge" angelegt und danach das Titelfeld, in dem nur die Überschrift steht und das auch sonst keine weiteren Funktionen hat. Ich füge grundsätzlich Texte auf den Karten in Feldern ein, sie lassen sich einmal leichter korrigieren und zum anderen kann man danach suchen lassen. Gegenüber dem auch möglichen Einfügen von Texten im Grafikmodus hat dies den Nachteil, daß auf dem Rechner, auf dem der Stack läuft auch die Schrift vorhanden sein muß. Daher benutze ich grundsätzlich nur die Schriften Courier, Geneva und New York. Diese sind mit Sicherheit auf jedem Macintosh vorhanden.

Durch die oben angegebene Reihenfolge haben die danach von oben nach unten angelegten Felder rechts neben "Eins" bis "Sechs" die Feldnummern 4, 5, 6, 7, 8 und 9 erhalten. So wird folgendes Codefragment (aus dem Handle initialisiere) verständlich:

	repeat with i = 4 to 9
		put 0 into cd fld i
	end repeat
Feldern lassen sich nicht nur mit ihrem Namen, sondern auch mit ihrer Nummer ansprechen. So ist es möglich, diese Felder innerhalb einer Schleife mit "0" zu füllen. Dies ist notwendig, weil die add und sub Kommandos von HyperTalk mit einer Fehlermeldung reagieren, wenn der angesprochene Container oder das angesprochene Feld keinen numerischen Wert enthalten. Und leere Felder haben in HyperTalk den Wert empty, sind also nicht numerisch, wohingegen bei Null HyperTalk mit uns übereinstimmt, daß dies ein numerischer Wert ist.

Im Handle playGame erwarten uns keine Neuigkeiten mehr, außer vielleicht, daß uns folgende Zeile

	set the textStyle of item x2 of line y2~
	of cd fld "Spielfeld" to outline
zeigt, daß wir die Textattribute auch von HyperTalk aus beeinflussen können. Wie ich im letzten Beitrag schon geschrieben hatte: Alles, was wir in HyperCard mit Maus und Tastatur erledigen können, können wir auch von HyperTalk aus programmieren. (Eine Ausnahme bilden lediglich einige Color-Tools von HyperCard 2.3. Doch hierzu mehr in einem späteren Beitrag.) Wichtig ist auch noch das Häkchen am Ende der ersten Zeile, das mit der Tastenkombination [Wahl][L] erzeugt werden kann. Normalerweise enden HyperTalk Befehle am Ende der Zeile, mit diesem Häkchen wird HyperTalk signalisiert, daß sich ein Befehl in der nächsten Zeile fortsetzt.

Ansonsten ist nur noch zu bemerken, daß sich das ganze HyperTalk-Programm für dieses Spiel hinter dem Button "Start" verbirgt und in Listing 1 abgedruckt ist.

Der blinde Uhrmacher

Abb. 2: Shakespeare und der blinde Uhrmacher

Noch etwas komplexer ist das zweite Beispielprogramm "Der blinde Uhrmacher", das sich ebenfalls mit der Evolution beschäftigt. Wir alle kennen das Beispiel des Schimpansen an der Schreibmaschine, der, wenn er nur unendlich lange genug in die Tasten hackt, irgendwann einmal auch einen Satz aus Shakespeares Hamlet (vielleicht "To be or not to be") hervorbringt. Statistisch gesehen dauert dies jedoch beinahe unendlich lange. Dawkins hat sich in seinem Buch Der blinde Uhrmacher, München (dtv) 1990) gefragt, was denn passiert, wenn man zufällige Mutationen immer wieder auf das Ergebnis anwendet, das dem Ziel am nächsten kommt. Im Buch ist es der Satz "Methinks it is like a weasel" (Mich dünkt, sie sieht aus wie ein Wiesel), ebenfalls aus Hamlet. Dieses Prinzip der kumulativen Selektion führt schon recht schnell zu einem Ergebnis. Dawkins gibt 50 - 60 Generationen an, macht jedoch weder Angaben über die Mutationshäufigkeit noch über die Anzahl der "Nachkommen" jedes Zwischenergebnisses, auf dem die Mutationen angewandt werden. Unser Beispielstack arbeitet mit 20 Nachkommen, auf denen je eine zufällige Veränderung vorgenommen wird. Ich habe diesen Stack lange laufen lassen. Im Schnitt wird der Zielsatz nach ca. 150 Generationen erreicht. Der beste Wert lag bei knapp über 100, der schlechteste bisher bei knapp unter 200 Generationen. Und Vorsicht: Selbst auf meinem Power PC lief der Stack jedes Mal ca. eine halbe Stunde!

Wir beginnen mit diesem Stack, indem wir als erstes ein Kartenfeld "children" anlegen. Dieses Feld soll unsichtbar sein, nur zum Zweck der Fehlersuche mußte ich es bei der Entwicklung sichtbar machen. Mit [Apfel][M] holen wir uns daher wieder die Messagebox aus dem ersten Teil dieses Kurses auf den Monitor. Mit Hilfe der Messagebox können HyperTalk-Kommandos interaktiv eingegeben werden. Wir tippen daher

	hide cd fld "children"
in die Box und tippen [ENTER]. Und siehe da, das Feld "children" ist verschwunden. Mit
	show cd fld "children"
können wir es jederzeit wieder sichtbar machen und seinen Inhalt überprüfen. Ich hätte genau so gut das, was in dieses Feld geschrieben wird, in einem Container abspeichern können, aber ich mußte tatsächlich mal während der Programmentwicklung den Inhalt kontrollieren und einen Container hätte ich dazu erst wieder umständlich in ein Feld schreiben müssen.

Natürlich soll im fertigen Programm das Feld nicht mehr zu sehen sein. Wir wählen daher "Card Info..." aus dem Menü "Objects", drücken in der Dialogbox den Knopf "Script" und geben folgendes HyperTalk-Script ein:

	on openCard
		hide cd fld "children"
		pass openCard
	end openCard
openCard ist ein ähnliches Systemhandle wie mouseUp. Er wird von HyperCard immer dann abgeschickt, wenn die entsprechende Karte aufgerufen wird. Wir fangen es in unserem Script ab und setzen den Befehl hide cd fld "children" dort ein. Es ist guter Brauch, solche abgefangenen Systemhandles weiterzugeben (mit pass <handle>), damit es auch an anderer Stelle, z.B. in einem Background-Script, wiederverwendet werden kann.

Wir ersehen daraus, daß nicht nur hinter Buttons in HyperCard Scripte versteckt sein können. Hinter jedem Objekt kann sich ein Script verbergen, hinter Feldern, Hintergründen, Karten, Stapeln, ja sogar im Home-Stack. (Dort verbergen sich tatsächlich noch einige System-Scripts. Es ist jedoch schlechter Stil, eigene Scripte im Home-Stack unterzubringen, da die Stacks dann auf anderen Computern nicht mehr laufen.)

Wir legen nun auf unserem Stack noch weitere Felder an: Das linke große heißt "intermediate", das über dem Startknopf "goal" und das darüber "parent". Diese Felder erhalten die Schrift Courier, da nur diese streng nonproportional ist, d.h. die Buchstaben immer genau untereinanderstehen. So können wir die Annäherung an den Zielsatz optisch leicher verfolgen. Das Feld neben dem Text "Anzahl Generationen" heißt "generation" und das darüber neben "Anzahl Übereinstimmung" habe ich "summe" genannt. Auch in diesem Stack sind alle Texte auf der Karte ebenfalls in Feldern, dies hat hier jedoch nur einen kosmetischen Effekt und ist für die Programmausführung bedeutungslos.

Bis auf das oben erwähnte Card-Script verbirgt sich auch hier das gesamte Programm hinter dem einzigen Button "Start". Die Struktur des Scripts ist ähnlich wie bei dem Evolutionsspiel, auf das Handle mouseUp folgt das Handle initialisiere und dann das Handle evolution mit dem eigentlichen Algorithmus. Dann folgt noch die Funktion makeLetter, die zufällig einen (Groß-)Buchstaben auswählt. Hier wird nur ein bißchen gebastelt, da unser im Programm benutztes Alphabet die 26 Großbuchstaben und das Leerzeichen enthält. Die Großbuchstaben haben die ASCII-Nummern 65 - 90, das Leerzeichen den ASCII-Wert 32. random(27) liefert uns einen zufälligen Wert zwischen 1 und 27. Wir addieren 63 auf. Die in HyperTalk eingebaute Funktion numToChar liefert uns dann das Gewünschte. Nur wenn der Zufallszahelngenerator 1 liefert, das Ergebnis also 32 ist, müssen wir durch 2 teilen, um den ASCII-Wert für das Leerzeichen zu erhalten.

Die beiden letzten Funktionen dagegen sind ein kleiner Trick. Um Konstanten nicht immer wieder neu zu definieren oder versehentlich zu überschreiben sind sie ebenfalls als Funktionen realisiert:

	function anzNachkommen
		return 20
	end anzNachkommen
Jedesmal, wenn im Programm anzNachkommen() aufgerufen wird, ist damit diese Konstante gemeint. Mit dem kleinen Mehraufwand, die öffnenden und schließenden Klammern zu tippen (und natürlich die Konstantendeklaration als Funktion zu realisieren) erhalten wir die Sicherheit, die die Konstantendeklaration der "höheren" Programmiersprachen bieten.

Ansonsten bietet das Programm, das komplett in Listing 2 abgedruckt ist, nur noch wenige Neuheiten: Wenn wir lange auf eine Antwort eines Programmes warten, sollten wir den Benutzer davon informieren, daß der Rechner nicht abgestürzt ist. Eine Möglichkeit ist der Befehl

	set cursor to busy
Jedesmal, wenn er aufgerufen wird, dreht sich der busy-Cursor (dieser kleine, schwarzweiße Ball) um einen Viertelkreis. Wir merken somit, daß noch etwas passiert. Es sollte nicht vergessen werden, anschließend den Cursor wieder zu hand zurückzusetzen.

Dann ist noch das Feld intermediate als Scrollfeld realisiert. Ohne weiteren Befehl schreibt HyperTalk zwar auch in den unsichtbaren Teil des Feldes, der Benutzer sieht aber während der Programmausführung nicht, was da hineingeschrieben wird. Daher habe ich mit dem Kommando

	set the scroll of cd fld "intermediate" to  9999
dafür gesorgt, daß nach jedem Einschreiben das Feld ganz nach unten gerollt wird. (Der Wert 9999 ist einfach geschätzt worden, weil er sehr groß ist und der Scroll in Pixeln berechnet wird. Bei größeren Scrollfeldern kann er daher noch zu klein sein und ist entweder durch einen berechneten Wert oder durch noch eine größere Zahl zu ersetzen.)

Außerdem sind unser verstecktes Feld children und die anderen Felder diesmal nicht als Matrix realisiert. Auf die einzelnen Buchstaben greifen wir daher mit der Sequenz char j of line i zu. Die Buchstaben sind so auch nicht durch Kommata getrennt. Neben den nun bekannten item und char können wir auch mit chunk und word in HyperCard auf einzelne Elemente eines Textfeldes zugreifen. Dies werden wir in einem späteren Kursteil, wenn wir Hypertext-Elemente realisieren werden, noch benötigen.

Als letzte Neuheit habe ich diesmal für die umfassende Schleife die repeat while-Konstruktion gewählt. Aber wie schon oben gesagt, geschah dies aus didaktischen Gründen und hat in diesem Beispiel keinen praktischen Wert.

Genetischer Algorithmus oder Evolutionsstrategie

Der im "Blinden Uhrmacher" verwendete Algorithmus ist eine nur auf Mutation beruhende Evolutionsstrategie ohne crossing over. Mit crossing over wird der Vorgang bezeichnet, zwei für die Weiterentwicklung ausgewählte "Nachkommen". zu "kreuzen", um so vielleicht einen geeigneteren Nachkommen zu finden. Solche Algorithmen heißen genetische Algorithmen. (Theoretische Informatiker mögen mir die arg verkürzte Darstellung verzeihen!) Wir haben bisher alles gelernt, um aus dem "Blinden Uhrmacher" einen genetischen Algorithmus zu machen. Denn während sonst das zu lösende Problem mühsam in eine Zeichenkette (meist in binärer Darstellung) codiert werden muß, um ein Auseinanderschneiden und Zusammenfügen zu ermöglichen, liegt unser Problem schon in der Form einer Zeichenkette vor. Statt eines Nachfolgers wählen wir zwei aus (es müssen nicht unbedingt die "besten" sein). Beide Zeichenketten werden an einer zufälligen Stelle auseinandergeschnitten und mit dem jeweils anderen Teil wieder zusammengefügt. Wir müssen daher nur noch wissen, daß der HyperTalk-Befehl zum Zusammenfügen zweier Teilstrings & oder && ist. & fügt zwei Zeichenketten unmittelbar zusammen, && fügt zwischen den beiden Zeichenketten ein Leerzeichen ein. Also
	put "Mager" & "milch" into ergebnis
füllt den Container ergebnis mit "Magermilch", während dagegen
	put "Anton" && "Reiser" into name
der Variablen name die in diesem Fall sicher erwünschte Zeichenkette "Anton Reiser" zuordnet.

Vielleicht haben Sie Lust, als Übung solch einen genetischen Algorithmus zu programmieren.

Verwendete Literatur:

Dawkins, Richard: Der blinde Uhrmacher, München (dtv) 1990

Eigen, Manfred und Ruthild Winkler: Das Spiel. Naturgesetze steuern den Zufall, München/Zürich (Piper-Verlag) 1975

Reiser, Martin, und Niklaus Wirth: Programmieren in Oberon. Das neue Pascal, Bonn (Addison-Wesley) 1994


previous Page home toc next Page

This pages need no frames
This site is edited with Radio UserLand, the first personal Web Application server for Windows and Macintosh. © 1996 - 2001 by Jörg Kantel
Last modified: JK, 04.09.2001; 20:33:25 Uhr
email:joerg@kantel.de
This page is best viewed with a computer and a monitor

Site Meter