Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Reid G.C.Thinking in PostScript.1990.pdf
Скачиваний:
17
Добавлен:
23.08.2013
Размер:
846.44 Кб
Скачать

programs. In particular, you don’t have to use a name as the key, and if you get things backwards, it won’t complain.

{ moveto show } /S def

In this case, of course, if you tried to use the S procedure, it would tell you it was undefined, because it has no dictionary entry with S as the key. Now let’s look at the procedure call itself, which requires three values to be on the operand stack.

(some text) 100 200 S

This can be looked at as a single procedure call and its arguments, although it is better to keep in mind that the interpreter does not see it that way. It sees simply a sequence of tokens to execute.

(some text) 100 200

S

Of course, the string (some text) and the numbers 100 and 200 are literal objects, so they are simply pushed onto the operand stack. When the S is encountered, looked up, and the procedure is executed, the correct arguments just happen to be on the operand stack.

PARAMETER PASSING

The best way to pass specific information to a procedure is to place it on the operand stack. There is, however, no procedure declaration to give names to the parameters. In fact, no rule says you must use the parameters. The cooperation between the definition of the procedure and its invocation is entirely up to you. In general, though, a procedure should consume all of its operands from the stack, unless it returns a value of some kind.

108

Chapter 9: PROCEDURES

Example 9.3: Procedure S of Example 9.1

/S { moveto show } def (some text) 100 200 S

The procedure S in Example 9.3 has three parameters, a string body and the x, y coordinates. These are supplied on the operand stack in the order required. That is, since moveto must be executed before show, the parameters used by moveto appear on the top of the stack. Note that this requires them to be actually written after the string, so that they will be on top (last in, first out). Let’s rearrange this example a little to see what is going on (Example 9.4).

Example 9.4: Procedure S and Data Rearranged

(some text) 100 200 /S { moveto show } def S

This also is perfectly legal. The procedure is defined just before it is invoked, with the operands delicately hanging on the operand stack. This probably is not the way you would write a program like this, but it makes it a little easier to imagine how the procedure evolved, and to see how the operands are used. If you just remove the definition and the curly braces, as in Example 9.5, the program would work the same way, but read slightly differently.

Example 9.5: Code without the Procedure

(some text) 100 200 moveto show

This is a little unusual, because the data and instructions are not interleaved in a comfortable and readable fashion, as in Example 9.6.

Example 9.6: Data in a More Familiar Arrangement

100 200 moveto (some text) show

In a procedure body, you don’t have the luxury of interleaving data and instructions, so you need to rearrange slightly the way data are presented to the procedure. You must pile all of the data up on the operand stack and use it piece by piece from within the procedure. Or you can simulate local

Chapter 9: PROCEDURES

109

variables, and interleave the data and instructions in a familiar and readable way (see Example 9.7).

Example 9.7: Data Arrangement for Use by a Procedure

/S

% Xloc Yloc (string) S -

{ %def

 

/text exch def% string is on top of stack /Y exch def% Y and X reversed on stack /X exch def

X Y moveto text show

 

} def

 

100 200 (some text) S

 

To some extent, the program has gotten more complicated in favor of

 

readability. The last bit of the program, X Y moveto text show, is more

 

readable than it was before, in the sense that the data and instructions are

 

interleaved sensibly. However, this is at the expense of three pairs of exch

 

def instructions and three name lookups for X, Y, and text.

 

There is a trade-off, in readability and efficiency, between creating these

 

local names versus using data directly from the operand stack. If the data

 

from the stack are used several times within the procedure, or if they are

 

used in a very unusual order, significantly increased readability and a

 

more easily maintained program can be constructed using the exch def

 

approach. Otherwise the reduction in the number of operators executed

 

and the number of name lookups required results in significantly

 

improved performance.

 

 

TIP

A good rule of thumb is that if the operators within a procedure use each

 

parameter just once or twice, it is better not to use local names for the pa-

 

rameters. Conversely, in a complicated procedure, it is usually better to

 

choose sensible names for the parameters to heighten readability and to

 

make the program more robust.

 

 

110

Chapter 9: PROCEDURES