Performs a circular shift of n elements on the operand stack by j positions.

1. Description

The roll operator performs a circular rotation of the top n elements on the operand stack. The rotation amount j can be positive (upward rotation) or negative (downward rotation).

Positive j values move elements toward the top of the stack, while negative j values move elements toward the bottom. The operation is circular, so elements that move off one end reappear at the other end.

This is a Level 1 operator, available in all PostScript implementations.

2. Syntax

anyn-1 ... any0 n j roll any(j-1) mod n ... any0 anyn-1 ... anyj mod n

2.1. Stack Effect

Table 1. Before Execution
Position Content

Top

j (integer) - Number of positions to rotate (positive=up, negative=down)

Top-1

n (integer) - Number of elements to rotate

Top-2

any0 - Topmost element of the n elements

…​

…​

Top-(n+1)

anyn-1 - Bottommost element of the n elements

Table 2. After Execution
Position Content

Top to Top-(n-1)

Elements rotated by j positions (circular)

3. Parameters

n

Non-negative integer specifying how many elements to rotate. Must be ≥ 0.

j

Integer specifying the rotation amount. Positive values rotate upward (toward top), negative values rotate downward.

anyn-1 …​ any0

The n elements to be rotated.

4. Return Values

The same n elements, rearranged by circular rotation.

5. Examples

5.1. Basic Usage

% Rotate 3 elements up by 1 position
(a)(b)(c) 3 1 roll    % Stack: (c)(a)(b)

% Rotate 3 elements down by 1 position
(a)(b)(c) 3 -1 roll   % Stack: (b)(c)(a)

% No rotation
(a)(b)(c) 3 0 roll    % Stack: (a)(b)(c)

5.2. Multiple Rotations

% Rotate by 2 positions
(a)(b)(c)(d) 4 2 roll     % Stack: (c)(d)(a)(b)

% Rotate by -2 positions
(a)(b)(c)(d) 4 -2 roll    % Stack: (c)(d)(a)(b)
% Same result! (4-2 = 2 mod 4)

5.3. Bringing Element to Top

% Move third element to top
1 2 3 4 5
3 -1 roll       % Stack: 1 2 4 5 3
% Third element (3) is now on top

5.4. Burying Top Element

% Move top element to third position
1 2 3
3 1 roll        % Stack: 3 1 2
% Top element (3) is now third

6. Advanced Examples

6.1. Implementing Stack Rotation Helpers

% Rotate top 3 elements: a b c -> b c a
/rot {              % a b c -> b c a
    3 1 roll
} def

% Reverse rotate: a b c -> c a b
/unrot {            % a b c -> c a b
    3 -1 roll
} def

1 2 3 rot           % Stack: 2 3 1
1 2 3 unrot         % Stack: 3 1 2

6.2. Moving Elements to Specific Positions

% Move element at position i to top
/bringToTop {       % ... elem_i ... i n -> elem_i ...
    % i is position from top (0-based)
    % n is total number of elements
    exch 1 add      % n (i+1)
    neg             % n -(i+1)
    roll
} def

10 20 30 40 50
2 5 bringToTop      % Brings element at position 2 to top
                    % Stack: 30 10 20 40 50

6.3. Reversing Top N Elements

% Reverse top n elements on stack
/reverseN {         % elem1 ... elemn n -> elemn ... elem1
    dup 1 sub 0 exch {
        % For each position
        1 index 1 roll
    } for
    pop
} def

1 2 3 4 5
5 reverseN          % Stack: 5 4 3 2 1

6.4. Cyclic Permutations

% Generate all cyclic permutations
/allRotations {     % elem1 ... elemn n -> (prints all rotations)
    dup 0 1 3 -1 roll 1 sub {
        % Print current arrangement
        (Rotation ) print dup =
        % Rotate for next iteration
        2 index 1 roll
    } for
    pop
} def

7. Edge Cases and Common Pitfalls

Using roll requires at least n+2 elements on the stack (n elements plus n and j). Insufficient elements cause stackunderflow.

7.1. Stack Underflow

% BAD: Not enough elements
1 2 3
5 1 roll            % ERROR: stackunderflow
                    % Need 5 elements, only have 3

7.2. Negative n Not Allowed

% BAD: n must be non-negative
1 2 3
-2 1 roll           % ERROR: rangecheck

7.3. Modulo Arithmetic

% Rolling by n is same as rolling by 0
(a)(b)(c) 3 3 roll  % Stack: (a)(b)(c)
% 3 mod 3 = 0, so no change

% Large rotations wrap around
(a)(b)(c) 3 4 roll  % Same as 3 1 roll
% 4 mod 3 = 1
The actual rotation is j mod n. Rolling by j and j+n produces identical results.

7.4. Roll with n=0 or n=1

% n=0 is valid but does nothing
1 2 3
0 5 roll            % Stack: 1 2 3 (no change)

% n=1 just removes n and j
1 2 3
1 5 roll            % Stack: 1 2 3 (no change)
  • exch - Equivalent to 2 1 roll or 2 -1 roll

  • index - Access element without reordering

  • copy - Duplicate elements

  • pop - Remove elements

9. PostScript Level

Available in: PostScript Level 1 and higher

This is a fundamental operator available in all PostScript implementations.

10. Error Conditions

stackunderflow

The stack contains fewer than n+2 elements (n elements plus n and j).

1 2 3
5 1 roll            % ERROR: stackunderflow
rangecheck

The value of n is negative.

1 2 3
-1 1 roll           % ERROR: rangecheck
typecheck

Either n or j is not an integer.

1 2 3
3.5 1 roll          % ERROR: typecheck
1 2 3
3 (not a number) roll   % ERROR: typecheck

11. Performance Considerations

The roll operator has O(n) time complexity. For small values of n (like 2 or 3), it’s very fast. For larger values, consider whether you really need to rotate all those elements or if there’s a more efficient approach.

Frequently rotating large numbers of elements may indicate poor stack management strategy.

12. Best Practices

  1. Use exch for two elements: 2 1 roll and 2 -1 roll both work, but exch is clearer

  2. Document rotations: Always comment what roll is doing, as it’s not immediately obvious

  3. Consider index instead: Sometimes psindex is clearer than roll for accessing buried elements

  4. Keep n small: Large rotations suggest stack management issues

  5. Use standard patterns: Establish conventions like 3 1 roll for rotating three elements

12.1. Common Rotation Patterns

% Three-element rotations (very common)
% a b c -> b c a
3 1 roll

% a b c -> c a b
3 -1 roll

% Four-element rotation to access buried value
% a b c d -> (use b)
3 -1 roll       % b a c d
% Use b
% Restore: 3 1 roll

12.2. Clear Documentation Example

% Good: Document what roll accomplishes
/computeDistance {  % x1 y1 x2 y2 -> distance
    % Stack: x1 y1 x2 y2
    3 -1 roll       % x1 x2 y2 y1 - bring y1 to top
    sub             % x1 x2 dy
    dup mul         % x1 x2 dy^2
    3 1 roll        % dy^2 x1 x2 - bring x's to top
    sub             % dy^2 dx
    dup mul         % dy^2 dx^2
    add sqrt        % distance
} def

13. See Also


Back to top

Copyright © 2025 Ribose. PostScript is a trademark of Adobe. Distributed under the MIT License.