This page (revision-21) was last changed on 03-Feb-2023 15:21 by Carsten Strotmann 

This page was created on 29-Jul-2010 13:57 by Carsten Strotmann

Only authorized users are allowed to rename pages.

Only authorized users are allowed to delete pages.

Page revision history

Version Date Modified Size Author Changes ... Change note
21 03-Feb-2023 15:21 27 KB Carsten Strotmann to previous

Page References

Incoming links Outgoing links

Version management

Difference between version and

At line 399 added 119 lines
Eine ganz anderen Lösungsansatz bietet ein positioneller CASE Konstrukt, bei dem die Fallunterscheidung durch den Fall-Index tabellarisch vorgenommen wird.
Bei den bisherigen Lösungen wurden immer eine Reihe von Vergleichen zwischen einem Fall-Index und einer Liste von Fall-Konstanten vorgenommen; nun wird der Fall-Index selbst benutzt, die gewünschte Prozedur auszuwählen. Die Verwendung des Fall-Index als Selektor bringt auch Vorteile in der Laufzeit, da die Vergleiche entfallen.
Wenn FORTH-Worte in Tabellen abgelegt werden sollen, stellt sich das Problem, daß ein FORTH-Wort bei seinem Aufruf normalerweise die einkompilierten Worte ausführt. Bei einer Tabelle ist das nicht erwünscht; dort ist sinnvollerweise gefordert, daß die Startadresse der Tabelle übergeben wird, um den Fall-Index als Offset in diese Tabelle zu nutzen.
Dies läßt sich in volksFORTH entweder auf die traditionelle Weise mit ] und [ oder dem volksFORTH-spezifischen __Create:__ lösen:
{{{
Create Glas
] nehmen links schieben
rechts schieben trinken [
Create: Glas
nehmen
links schieben
rechts schieben
trinken ;
}}}
Diese Tabelle Glas macht auch deutlich, welche Punktion das Dummy-Wort __schieben__ außer einer besseren Lesbarkeit noch hat: Es löst die Schwierigkeit, daß 6 möglichen Wurfergebnissen nur 4 mögliche Aktionen gegenüberstehen.
Die Art und Weise des Zugriffs in BEWEGEN entspricht dem Zugriff auf eine Zahl in einem eindimensionalen Feld, einem Vektor:
{{{
: bewegen ( addr n -- cfa )
2* + perform ;
: richtig ( n -- 0 <= n <= 3 )
swap
1 max 6 min
3 case? IF 2 1- exit THEN
5 case? IF 4 1- exit THEN
1- ;
}}}
Dieses Wort RICHTIG läßt zwar Werte kleiner als 1 und größer als 6 zu, justiert sie aber auf den Bereich zwischen 1 und 6. Auch hier müßte eine Möglichkeit geschaffen werden, ein Wurfergebnis außerhalb der 6 Möglichkeiten als Betrugsversuch zurückzuweisen!
Die Verbindung von Tabelle und Zugriffsprozedur wird von dem Wort :Does> vorgenommen:
{{{
\ :Does> für Create <name> :Does> <action> ; ks 25 aug 88
| : (does> here >r [compile] Does> ;
: :DOES> last @ 0= Abort" without reference"
(does> corrent @ context ! hide 0 ] ;
}}}
Dieses Wort __:DOES>__ weist dem letzten über __Create__ definierten Wort einen Laufzeit-Teil zu. Dieses Wort wurde von Klaus Schleisiek programmiert auch hier gilt der Hinweis, nach dem Kompilieren das mit | als headerless deklarierte Wort durch __clear__ zu löschen.
{{{
Create: Auswertung.8
nehmen
links schieben
rechts schieben
trinken ;
:DOES> richtig bewegen ;
}}}
Ohne :DOES> sind die Tabelle und die Zugriffsprozeduren voneinander unabhängige Worte:
{{{
: CRAPS1
cr Anfrage cr
input#
Glas richtig bewegen
cr Glückwunsch ;
}}}
Entschließt man sich dagegen, sowohl Tabelle als auch Zugriffsprozedur in einem Wort zu definieren, so ergibt sich das gewohnte Erscheinungsbild:
{{{
: CRAPS
cr Anfrage cr
input#
Auswertung
cr Glückwunsch ;
}}}
Bei häufigerem Einsatz solcher Tabellen bietet sich der Einsatz von "positional CASE defining words" an. Auch hier wiederum zuerst die volks4TH-gemäße Lösung, danach die traditionelle Variante:
{{{
: Case: ( -- )
Create: Does> ( pfa -- ) swap 2* + perform ;
\ Alternative Definition für CASE:
: Case:
: Does> ( pfa -- ) swap 2* + perform ;
}}}
Eine sehr elegante Möglichkeit, die Fehlerbehandlung im Falle eines unglaubwürdigen Fall-Indexes zu handhaben, bietet das Wort __Associative:__. Dieses Wort __Associative:__ durchsucht eine Tabelle nach einer Übereinstimmung zwischen einem Zahlenwert auf dem Stack und den Zahlenwerten in der Tabelle und liefert den Index der gefundenen Zahl (match) zurück. Im Falle eines Mißer­folgs (mismatch) wird der größtmögliche Index +1 ( out of range = maxIndex + 1 ) übergeben:
{{{
: Associative: ( n -- )
Constant Does> ( n -- index )
dup @ -rot
dup @ 0
DO 2+ 2dup @ =
IF 2drop drop I 0 0 LEAVE THEN
LOOP 2drop ;
6 Associative: Auswerten
1,
2 , 3 ,
4 , 5 ,
6 ,
Case: Handlen \ besteht aus
nehmen
links links
rechts rechts
trinken
schimpfen ;
}}}