Konkatenative Programmierung mit Factor, Teil 2

29. Juli 2009 – 18:44 von Andreas

Nachdem wir uns im ersten Teil der Factor-Reihe mit dem grundlegenden Ausführungsmodell befasst haben, kommen wir nun zu den Words (Funktionen). Wir werden also sehen, wie wir eigene Words definieren und ein paar vordefinierte, sehr hilfreiche Words verwenden können. Zum Schluss werden wir uns dann noch anonyme Funktionen (diese werden in Factor als Quotations bezeichnet) anschauen.

1. Definieren von eigenen Words

Mit dem Schlüsselwort : ist es möglich eigene Words zu definieren. Ein Beispiel hierfür ist unter Listing 1.1 zu finden.

: add-and-sq ( x y — result )
+ sq ;

Listing 1.1 Definieren eigener Words

Wie in dem Beispiel zu sehen ist, wird die Definition durch ein : eingeleitet. Danach folgt der Bezeichner und der Stack-Effekt. Dieser zeigt an, was das Word zu Beginn auf dem Stack erwartet und welche Elemente am Ende der Verarbeitung wieder auf dem Stack liegen. Im Listing 1.1 werden zwei Elemente (x und y) vom Stack benötigt und am Ende ein Element (result) wieder auf den Stack gelegt. Hierbei zu beachten ist vor allem, dass man innerhalb des Funktionsrumpf nicht auf die Parameter x und y namentlich referenzieren kann. Es handelt sich nur um die Angabe, welche Effekte das definierte Word auf den Stack hat. Im Funktionsrumpf kann man nun mit den erwarteten Eingangswerten arbeiten. Im Beispiel wird wieder eine Addition durchgeführt und anschließend das Ergebnis mit sich selbst multipliziert. Abgeschlossen wird eine Word-Definition mit einem ; .

2. Shuffle-Words
Unter Shuffle-Words versteht man vordefinierte Words, welche einem helfen auf dem Stack zu arbeiten. Angenommen es sind drei Werte x y und z auf dem Stack. Zur nachfolgenden Verarbeitung werden diese allerdings in einer anderen Reihenfolge benötigt. Ein Shuffle-Word kann genau in dieser Situation helfen. Wollen wir hier z.B. y und z vertauschen, verwenden wir einfach das Shuffle-Word swap, welches folgenden Stack-Effekt hat: ( x y — y x ). Eine Übersicht über die existierenden Shuffle-Words sind in der Factor-Dokumentation zu finden.

3. Anonyme Funktionen
Anonyme Funktionen werden in Factor als Quotations bezeichnet. Diese werden durch zwei eckige Klammern ([, ]) definiert. Innerhalb der Klammern wird dann der Code geschrieben, welcher in der anonymen Funktion ausgeführt werden soll. Ein Beispiel ist unter Listing 3.1 zu finden.

[ + sq ]
=> [ + sq ]

Listing 3.1 Definieren einer Quotation

Im Listing 3.1 werden die im vorherigen Abschnitt verwendeten Words + und sq in einer Quotation verpackt. Die Quotation wird allerdings nicht sofort ausgeführt sondern mit den beiden Befehlen auf den Datenstack gelegt und kann dann zu einem späteren Zeitpunkt ausgeführt werden (auch verzögerte Ausführung genannt). Wollen wir die auf dem Stack liegende Quotation nun ausführen, können wir das Word call, wie in Listing 3.2, verwenden.

2 4 [ + sq ] call
=> 36

Listing 3.2 Ausführen einer Quotation

Wenn die Quotation ausgeführt wird müssen natürlich auch die benötigten Werte für die Befehle innerhalb der Quotation auf dem Stack liegen (in unserem Beispiel 4 und 5 für die Addition). Die Ausführung läuft also folgendermaßen ab: Zuerst wird die Quotation ausgeführt, so dass 2 4 + sq zur Ausführung bereitsteht. Nun werden 2 und 4 durch + addiert und danach durch sq weiterberechnet. Anschließend steht dann nur noch das Ergebnis auf dem Stack.
Durch Quotations gibt es eine Möglichkeit Code, wie normale Daten auf den Stack zu legen und verzögert auszuführen. Es können natürlich auch Words definiert werden, welche am Ende ihrer Ausführung eine Quotation auf den Stack legen. Ein Beispiel ist in Listing 3.3 und 3.4 zu finden.

: get-add-and-sq-quot ( — quot )
[ + sq ] ;

Listing 3.3 Arbeiten mit Quotations in eigenen Words

get-add-and-sq-quot
=> [ + sq ]

Listing 3.4 Setzen einer Quotation durch ein Word

Es können also Quotations über den Programmablauf hinweg an verschiedene Words weitergegeben und dann verzögert ausgeführt werden. Das Problem beim Word call ist, dass wenn man z.B. eine Quotation als Parameter an ein Word übergibt, an call nicht sieht welchen Stack-Effekt diese aufgerufene Quotation hat. Um dies (für den Compiler und auch den Entwickler) darstellen zu können, wird das Word call( verwendet. Mit call( kann der Stack-Effekt der Quotation, wie bei Listing 3.5 und 3.6 hinter die Klammer geschrieben werden.

: get-add-and-sq-quot ( — quot )
[ + sq ] ;

: add1-to-result-of-quot ( x y quot — result )
call( x y — result ) 1 + ;

Listing 3.5 Verwendung des Words call(

! Kommentare werden mit ! und einem Leerzeichen
! eingeleitet.
! rot ist ein shuffle Word und hat folgenden
! Stack-Effekt: rot ( x y z — y z x )
! Da add1-to-result-of-quot x y quot erwartet, aber quot
! x y auf dem Stack liegt muss der Stack mit rot passend
! umgebaut werden.

get-add-and-sq-quot 2 4 rot add1-to-result-of-quot
=> 37

Listing 3.6 Anwendung der definierten Words

In add1-to-result-of-quot wird in diesem Beispiel also die Quotation mit dem Stack-Effekt ( x y — result ) ausgeführt und dem Ergebnis wird dann noch die Zahl eins zuaddiert.

  1. 5 Responses to “Konkatenative Programmierung mit Factor, Teil 2”

  2. Ganz schön knifflig die letzte Zeile. Ich hab 5 Minuten gebraucht, bis ich das verstanden hatte :) Für die, die auch noch nicht so ganz die “Stack-Denke” intus haben wie ich, hier mal ne Schritt für Schritt Abarbeitung des Stacks der letzten Zeile:

    get-add-and-sq-quot 2 4 rot add1-to-result-of-quot
    [ + sq ] 2 4 rot add1-to-result-of-quot
    2 4 [ + sq ] add1-to-result-of-quot
    2 4 + sq add1-to-result-of-quot
    6 sq add1-to-result-of-quot
    36 add1-to-result-of-quot
    36 1 +
    37

    By Aaron on Aug 1, 2009

  3. Hey Aaron,
    Super! Dank dir!! So wirds denke ich viel besser verständlich!
    Wenn sonst noch was unklar sein sollte, einfach posten:)! Es dauert schon bis man in das Ganze reinkommt. Das Coole is aber, wenn man mal drin ist, fängt man an z.B. in C# die Parameter vor die Funktionen zu schreiben und wundert sich dann, warum der Compiler rummeckert ;).

    Grüße
    Andreas

    By Andi on Aug 1, 2009

  1. 3 Trackback(s)

  2. Aug 25, 2009: ybicodu
  3. Sep 25, 2009: ymypyteqany
  4. Jun 11, 2010: Webmaster

Post a Comment