The first of these operators is
def.
'def' is responsible for entering a
definition into the top-most dictionary on the dictionary stack. The
top operand on the operand stack is the value, and the operand below
the value is the key (and should be a name). Let's say that we wanted
to define the name 'x' to have a value of 5. The PostScript to do this
is: /x 5 def
. Notice the use of the slash on the 'x.'
The slash ensures that the name 'x' will be pushed onto
the stack and not any value it may already have in the dictionary
stack.
'def' is also used to define new operators. The value in this case is
just a procedure. The following code defines an operator 'foo' which
adds its top-most two operands and multiplies the result with the next
operand on the stack: /foo {add mul} def
. Remember,
operands that return results push them onto the stack, where they may
be used later.
An important point to know when defining procedures is that the
elements in the procedure are not evaluated until the
procedure is invoked. That means that in the procedure {1 2 add
3 mul}
, the actual names 'add' and 'mul' are stored in the array
that is the procedure. This is different from an actual array in which
the components are evaluated when the array is created. For
contrast, the array [1 2 add 3 mul]
contains one object: the
number 9.
This delayed evaluation of procedure components has two important effects. First, the definition of an operator used in a procedure is the one that is in effect when the procedure is run, not when it is defined. Second, because each operator has to be looked up each time the procedure is invoked, things can be a little slow. Fortunately, PostScript provides a handy operator to replace each name in a procedure object with it's current definition. This operator is called bind, and it can speed up your program considerably. Bind is typically used as:
/foo {add mul} bind defThis defines foo to be a procedure array with two components: the procedures for add and mul. Note that, if add or mul is re-defined after defining foo, foo will have the same behavior as before. Without the use of bind, foo's behavior would change.