Tutorial

Our program uses a GUI, which is built around a single window. This window is divided in several functionnal areas:

The biggest window (rightmost) is the edit window. Here you can type in definitions and expressions. The second biggest window (bottom left corner) is the output window. Try typing something like

+ 12 53

into the edit window, highlight it, and click on the EVAL button. That should print 65 in the output window. As you may have noticed, everything is in prefix notation (use parentheses to force order of evaluation). The only datatypes in the language are numbers and functions (booleans are simulated with numbers like it is done in C). Now try this. Click on the TRACE button (this will enable tracing both when defining things and when evaluating expressions). Then type

def f x = + 5 x (function 'f' with one argument 'x', that returns 'x plus 5')

Highlight the text and click on EVAL. There will be a bunch of things displayed in the output window. Each ouput line represente one step in the abstraction process that leads to the combinator form.

To see what f is actually being defined to, just highlight the character 'f' (be careful not to add a possible carriage return with the 'f') and click on DEF. That will search the global environment and display its binding in the top left window (that's exactly what that window is for). The contents in the global environment is shown in the central window. You can also highlight things in there and then click on DEF to get the bindings of variables (look at the 'fact' function if you like).

The primitives are +, -, *, / (all taking two arguments). There is a > and =, which take two arguments and return 0 for false or 1 for true. Finally there is an 'if' taking three arguments, the test (whose result is treated as a boolean), the 'then' expression, the 'else' expression. There are also primitives S, K, I, B, and C, which stand for the five combinators we implemented (defined as in Turner's paper).

Functions are first order and they are always curried. So you can define things like

def f x = x 4

(i.e. you highlight it and then click on EVAL) and then evaluate the expression (again you need to highlight it and then click on EVAL)

f + 2

which should print 6 in the output window. You might want to think about this as (f +) as returning (+ 4) (i.e. a function expecting one argument) and then calling ((+ 4) 2).

One note of caution. Be very careful with tracing complicated expressions. Do not expect this program to trace (fact 50) till completion. You will probably blow the output display buffer before it gets done. Try (fact 3) first and get a feeling of how big these combinator expressions get. It used to be much worse before we added optimizations (B, C combinators) to the code. Note that an identifier can be pretty much anything. *#$%^& is (I think) a legal identifier. The reduction machine we implemented is purely functional, you cannot redefine things or erase definitions (you have to restart the program to get a fresh environment).

That leads to incremental programming, believe me!

def suc = + 1 x

(oops)

def succ x = + 1x

(arghh)

def successor x = + 2 x

(ahh!!!!!)

def working_successor x = + 1 x

:-)

Oh and please ignore the minor inconveniences with the GUI (like how the windows scroll at times).