Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

The `count -1 1{-1 roll =}for` Idiom

61 views
Skip to first unread message

luser- -droog

unread,
Aug 1, 2013, 3:20:35 AM8/1/13
to
I've discovered myself using this little pattern a lot,
but I know it would have been gibberish to me as a beginner.
So this message is to explain how this little loop does
its marvelous job.

count -1 1{-1 roll =}for

To begin with, it's a `for` loop.

init incr fin {-body-} for

So in our loop, init=count (== number of elements on stack),
incr=-1 (counting down), fin=1 (stop at 1). So it's counting
down from the stack size to 1. If we pop something each time
through the loop, then this loop gives a running count of
the stack size.

Now the inside of the loop.

-1 roll =

If you're a real postscript programmer, this line should
bother you. Because `roll` takes 2 arguments: a count of
the number of stack elements it should mess with, and a
number of elements to move from the top (bottom if negative)
to the bottom (top if negative). So `-1 roll` is a curried
application of `roll`, set to always grab 1 element from
the bottom of a yet-to-be-specified total number of elements
and bring it to the top. Then it prints the object with `=`.

So the loop itself, being a `for` loop, pushes the index
on the stack before each iteration of the loop body.
So the stack picture looks something like this:

% a b c d e f g
count % a b c d e f g 7
-1 1 {} % a b c d e f g 7 -1 1 {}
for
**loop push index 7**
% a b c d e f g 7
-1 % a b c d e f g 7 -1
roll % b c d e f g a
= % b c d e f g (output a)
% b c d e f g
**loop push index 6**
% b c d e f g 6
-1 % b c d e f g 6 -1
roll % c d e f g b
= % c d e f g (output b)
% c d e f g
**loop push index 5**
% c d e f g 5
-1 % c d e f g 5 -1
roll % d e f g c
= % d e f g (output c)
% d e f g
**loop push index 4**
% d e f g 4
-1 % d e f g 4 -1
roll % e f g d
= % e f g (output d)
% e f g
**loop push index 3**
% e f g 3
-1 % e f g 3 -1
roll % f g e
= % f g (output e)
% f g
**loop push index 2**
% f g 2
-1 % f g 2 -1
roll % g f
= % g (output f)
% g
**loop push index 1**
% g 1
-1 % g 1 -1
roll % g
= % (output g)
%
**loop final reached**

So this little loop (and `roll` usage) lets you access the
stack bottom-to-top!


0 new messages