I've been handwriting PostScript on occasion for more than half my life –
Usually, in a language where the assignment operator can only change one variable at a time, the idiom for swapping two variables requires three statements, using a temporary variable to save one value in at the point where you've just copied the other value from one variable to the other (so they both hold the same value).
PostScript is such a language. The syntax for doing a swap that way (supposing the variables you're swapping are called foo
and bar
) would be
/tmp foo def
/foo bar def
/bar tmp def
in which, for example, /tmp
pushes a variable name on the operand stack; foo
pushes a variable's value; and the def
operator pops both of those operands back off and writes the given value into the variable identified by the given name.
But this is excessively roundabout. PostScript may only let you assign one variable at a time, but its stack structure lets you avoid defining a temporary name: in order to save the old value of the first variable, you only have to push it temporarily on the operand stack, and recover it after the redefinition of the other. For example:
bar % push the original value of bar
/bar foo def % set the final value of bar
/foo exch def % set foo to the value pulled back off the stack
But a neater way avoids even the need for that exch
:
/foo bar % parameters for the 'def' that will set foo
/bar foo % parameters for the 'def' that will set bar
def % set bar, using the second pair of params
def % set foo, using the first pair
or, once you're using it in anger and not explaining it every time,
/foo bar /bar foo def def
I thought that was unexpectedly cute! It's got the same set of words as the two separate assignment operations ‘/foo bar def
’ and ‘/bar foo def
’, but it uses the fact that PostScript assignment ‘statements’ are in some sense not atomic –
And that's why I think I can't ever have had to do that before –
Not surprisingly – PS and Forth have the common feature of being essentially RPN-shaped languages based around an operand stack, so they look quite similar in some ways.
But PS is higher-level. Forth deals in addresses and pointers: declaring a variable allocates space for it (somewhere) and defines the variable's name as a word that pushes the address of that space, so even reading a variable requires a word for "dereference" (if I remember rightly, "varname @" is the rune), and the word to set a variable ("!", I think) is the same as the word for "store this data to some other arbitrary memory address I've come up with by other methods".
By contrast, PS is all logical data types with garbage collection and doesn't give you access to the underlying address space at all. Instead, it has the Lisplike concept of symbolic name tokens (written with that leading /, unlike Lisp's really awkward unmatched quote character), and also a dictionary data type not unlike your Perl/Python hash / dict / associative array. Dictionaries can be used explicitly as user variables using the
get
andput
operators, but there's also an implicit stack of them that hold the current variable scopes, so what "/foo value def" really means is "add the key-value pair (/foo, value) to the dict at the top of the current scope stack, overwriting any previous value that went with that key".But yes, I suppose that this same idiom for variable-swapping would work very similarly, in that if you'd do a normal Forth assignment by saying
then you can do a swap by saying or perhaps it looks neater to rearrange things a bit: