Recursion and while loops in Factor
October 11th, 2007 by Samuel TardieuTonight, I was willing to create a while construct in Factor taking two items on the stack:
- a quotation to execute when the test is true
- a test quotation
For example, I wanted to be able to find the smallest power of two greater than or equal to an arbitrary number (here 34098) by doing:
1 [ 2 * ] [ dup 34098 < ] while
(of course there are much better ways of doing that, such as 34098 2 * 1 + 2 /i but that’s not the point here)
This would be much easier if we could recurse from within a block (by using a recurse word). Let’s start with that:
SYMBOL: recursive-block : set-block ( quot -- ) recursive-block set ; : recurse ( quot -- ) recursive-block get call ; : with-recurse ( quot -- ) recursive-block get >r dup set-block call r> set-block ;
A quote passed through with-recurse can use the recurse word and re-execute itself.
Now that we have recursion, it is easy to implement while using currying:
: while ( quot quot -- ) swap [ call recurse ] curry [ slip when ] 2curry with-recurse ; inline
Note that inline is used here to give the optimizing compiler a chance to build the complete quotation at compile-time if both quotations given to while are statically known.
To create a vocabulary recursion containing this code, one can create a file extra/recursion/recursion.factor containing:
USING: kernel namespaces ; IN: recursion <PRIVATE SYMBOL: recursive-block : set-block ( quot -- ) recursive-block set ; : init-block ( -- ) [ "recurse called without with-recurse" throw ] set-block ; PRIVATE> : recurse ( quot -- ) recursive-block get call ; : with-recurse ( quot -- ) recursive-block get >r dup set-block call r> set-block ; : while ( quot quot -- ) swap [ call recurse ] curry [ slip when ] 2curry with-recurse ; inline MAIN: init-block
Loading this library can be done by issuing the following command in the listener: "recursion" run.
That’s all folks.

October 11th, 2007 at 6:45
: while ( pred quot — ) dupd 2slip rot [ tuck 2slip while ] [ 2drop ] if ; inline
October 11th, 2007 at 9:45
Hum, I feel like I can no more be ignorant about factor programming language … I’ll fix that quickly.