Skip to main content

Blocks

A block is defined using the special words { and }. All words listed between { and } constitute the body of the block, which is then pushed into the stack as an execution token. A block may be stored as a definition of a new Fift word by means of the word : as explained in the Words section, or executed by means of the word execute:
A slightly more convoluted example:
In the above example, block { 2 * } acts as the “anonymous function” x -> 2x that gets applied twice on 17, producing the result 2 * (2 * 17) = 68. The above examples show that a block is an execution token, which can be duplicated, stored into a constant, used to define a new word, or executed. The word ' <WORD_NAME> recovers the current definition of a word. Namely, ' <WORD_NAME> pushes the execution token equivalent to the current definition of the word <WORD_NAME>. For instance, the following two lines are equivalent:
And,
defines duplicate as a synonym for the current definition of dup.

Conditional execution of blocks

Conditional execution of blocks is achieved using the words if, ifnot, and cond. Word if expects a stack of the form v e, where v is a value and e is an execution token at the top of the stack. The word if consumes both e and v and executes e only if v is non-zero. If v is zero, it does nothing. Word if is roughly equivalent to the statement if (v) { e } in a high level programming language. Word ifnot is similar to if, but instead, it executes e only if v is zero. Word ifnot is roughly equivalent to the statement if (not v) { e } in a high level programming language. Word cond expects a stack of the form v e e', where v is a value, e and e' are execution tokens. The word cond consumes e', e and v, and executes e if v is non-zero, otherwise it executes e'. Word cond is roughly equivalent to the statement if (v) { e } else { e' } in a high level programming language. For instance,
Blocks can be arbitrarily nested, as already shown in the previous example. For example, the following code defines word chksign that consumes the integer at the top of the stack and pushes either "positive", "negative", or "zero", depending on the sign of the integer.
To illustrate how chksign executes, here are the traces for -17 chksign, 17 chksign, and 0 chksign. Trace for -17 chksign:
Trace for 17 chksign:
Trace for 0 chksign:

Loops

Fixed repeat loops

To execute a code a fixed number of times, use word times. Word times expects a stack of the form e n, where e is an execution token and n is an integer at the top of the stack. The word times consumes both n and e and executes e exactly n times. If n is negative, times throws an exception. For instance,
pushes 1 and then executes the block { 10 * } exactly 20 times, producing ((1 * 10) * 10) * 10 ..., i.e., 10^20. The following more complex example implements the factorial function, which computes the factorial of the integer at the top of the stack:
Here is the trace for 4 fact:

Loops with an exit condition

More sophisticated loops can be created with the aid of words while and until. Word while executes a block while a condition is true, and until executes a block until a condition becomes true. Word while expects a stack of the form e e', where e and e' are execution tokens, with e' at the top of the stack. The word while consumes e and e'; then, it executes e, which produces an integer at the top of the stack, which gets consumed. If this integer is zero, while stops execution; otherwise, executes e' and begins a new loop iteration by executing e and carrying out the integer check again. Word while is roughly equivalent to the statement while (e) { e' } in a high level programming language, where e usually encodes the loop condition. Word until expects a stack of the form e, where e is an execution token. The word until consumes e; then, it executes e, which produces an integer at the top of the stack, which gets consumed. If this integer is non-zero, until stops execution; otherwise, begins a new loop iteration by executing e and carrying out the integer check again. Usually, the last instructions in e encode the loop condition. Here is a simple example for while:
The example multiplies by 10 repeatedly, starting from 1, but as long as the intermediate result is strictly smaller than 123. In other words, it pushes number 1000 into the stack. Here is the trace:
Here is the equivalent example, but using until:
The example also multiplies by 10 repeatedly, starting from 1, but stops until the intermediate result is greater or equal to 123. It pushes number 1000 into the stack. Here is the trace:
The next is a more complex example that modifies slightly the factorial function defined in the section for fixed repeat loops. fact-input below defines a word that computes the smallest integer that would produce a factorial bigger or equal to the integer at the top of the stack. For example, 10 fact-input produces 4, because 4! = 24 >= 10 and 4 is the smallest integer x such that x! >= 10.
Here is the trace for 10 fact-input:

Throwing exceptions

Fift uses the words abort and abort"<MESSAGE>" for throwing exceptions. Word abort takes the string at the top of the stack and throws an exception with the string as the message. Similarly, abort"<MESSAGE>" throws an exception with message "<MESSAGE>" but only if the integer at the top of the stack is non-zero, which is also consumed. If the integer at the top of the stack is zero, abort"<MESSAGE>" consumes the integer but does not throw an exception. The Fift interpreter handles exceptions by aborting all execution up to the top level and printing a message with the name of the source file being interpreted, the line number, the currently interpreted word, and the specified error message. The entire stack is cleared in the process. For instance, word safe/ below is a safe division that checks if the divisor is zero or not. Executing 5 0 safe/ throws an exception with message “safe/: Division by zero” and clears the stack. But executing 5 2 safe/ produces 2 at the top of the stack, since 5/2 = 2 and the divisor 2 is non-zero.
Additionally, when the Fift interpreter encounters an unknown word that cannot be parsed as an integer literal, an exception with the message ”-?” is thrown and the stack is cleared.