I’ve just discovered Factor, a new programming language. It is a stack-based language like Forth and Postscript. Factor works on many different platforms.
I’m currently looking at it as one of the possible programming languages I’ll cover in my Programming Languages module at the University of Mauritius. Simple stack-based languages are interesting because they are low-level meaning that a student who understands Factor really understands how a computer works. And also the Java virtual machine which is also a stack-based bytecode interpreter.
Some example code
The Factor programming language is simple. For example,
10 20 30 + * .
displays 500. 10 20 and 30 are pushed onto the stack. + consumes the last two elements on that stack (20 and 30) and produces 50 which is pushed on the stack. * consumes the 50 and 10 and 500 is pushed. The . consumes one element of the stack (i.e. 500) and prints it on screen…
This morning, Pascal Grosset and I have been experimenting with different functions in Factor using the Factor workspace which is a great IDE. We have come up with the following:
: square ( x -- y ) dup * ;
This is a function called square that consumes one element of the stack (the x) and produces one element (the y). What it does is easy. dup duplicates the topmost element of the stack. * obviously multiplies the two topmost elements. That’s it.
: cube ( x -- y ) dup dup * * ;
Easy!
: big ( x -- y ) 10 > ;
big looks at the topmost element of the stack and replace it by t(rue) if it is bigger than 10 and (f)alse otherwise. t and f are Boolean values.
: negative ( x -- y ) 0 swap - ;
The swap is used to swap (what else?) the two topmost values on the stack. Notice that 0 is pushed before. And the – only does 0 – the number which was there already i.e. calculates the negative of that number.
: max ( x y -- z ) 2dup < [ swap drop ] [ drop ] if ;
What about this one? It contains a conditional statement (the if) which consumes three elements on the stack: a Boolean and two quotations (which are like Smalltalk and Ruby blocks which are evaluated later if needed). The first quotation [ swap drop ] will be evaluated if the condition is true and the second one [ drop ] otherwise. The 2dup function simply duplicates the two topmost elements on the stack. Get it?
Recursion in Factor
More complex Factor functions allow for recursion:
: fact ( x -- y ) dup 0 = [ drop 1 ] [ dup 1 - fact * ] if ;
Do you recognize our friend factorial? drop simply discards the topmost element of the stack. Notice that fact is called recursively until it hits the boundary case.
And finally,
: fib ( x -- y ) dup 1 <= [ drop 1 ] [ dup 1 - fib swap 2 - fib + ] if ;
This is another friend, the Fibonacci function. Have fun understanding it.
PS: Elie Chaftari says that according to Doug Coleman, one of Factor’s top gurus, you need to learn the following words (aka functions) by heart: dup, keep, 2dup, 2keep, swap, pick, rot, -rot, roll, -roll, 2apply, 2array, first2, nth, set-nth, append. Doug also advises to learn the following words for iterating: each, each-with, map, map-with, 2each, 2map.
Pascal says
I agree, good IDE except that had the Data Stack representation been reversed it would have helped a lot.
Reviewing posfix (or Reverse Polish Notation) is a great help to understand this language; after all, it’s stack based.