[comp.windows.news] newcomer, need help with forall

don@brillig.umd.edu (Don Hopkins) (08/10/89)

In article <7725@pogo.WV.TEK.COM> richk@pogo.WV.TEK.COM (Richard G. Knowles) writes:
>In article <JNP.89Aug9134311@mjolner.tele.nokia.fi> jnp@mjolner.tele.nokia.fi (J|rgen N|rgaard) writes:
>>Consider the following program:
>>
>>    /Helvetica findfont 10 scalefont setfont
>>    100 100 translate
>>    /en   { gsave 0 0 moveto 1 10 string cvs show grestore } def
>>    /to   { gsave 0 0 moveto 2 10 string cvs show grestore } def
>>    /tre  { gsave 0 0 moveto 3 10 string cvs show grestore } def
>>    /fire { gsave 0 0 moveto 4 10 string cvs show grestore } def
>>
>>%% method one
>>    [en to tre fire]{ 0 50 translate exec} forall showpage
>>
>>    100 100 translate
>>%% method two 
>>    [1 2 3 4]{ 0 50 translate 0 0 moveto 10 string cvs show} forall showpage
>>
[...]
>Correct ways of specifying method one are:
>
>  [//en     //to     //tre     //fire    ] { 0 50 translate exec} forall
>  [/en load /to load /tre load /fire load] { 0 50 translate exec} forall
>  [/en      /to      /tre      /fire     ] { 0 50 translate load exec} forall
>

Quite right! But you could also go:

{en to tre fire} {0 50 translate exec} forall

That way would be more efficient if it were executed more than once
(if it was wrapped up inside another procedure), since the methods
using [ ... ] create a new literal array every time they're executed,
and the { ... } method always reuses the same (executable) array
(created by the scanner).

"[" is a normal PostScript function, that pushes a mark into the stack
("/[ mark def"). "]" is a normal function that makes an array out of
the things on the stack between the mark and the top of the stack ("/]
{counttomark array astore exch pop} def"). The tokens between [ and ] are
executed normally.

"{" and "}" are handled specially by the scanner. They are not
functions. The scanner does not execute the tokens between "{" and
"}", it just makes an executable array out of them.

So the difference between "{ [ en to tre fire ] }" and "{ { en
to tre fire } }" is that the former is an executable array of six
elements, while the latter is an executable array of one element, and
that one element is an executable array of four elements.

The former creates and returns a new literal array whenever it's
executed. The array it returns is of zero length, because the
procedures "en", "to", "tre", and "fire" are called while the array is
being accumulated on the stack, and they don't leave anything on the
stack. The latter returns the same four-element executable array every
time. The array elements are executable, but weren't executed when the
array was scanned in.  So the "exec" in the forall function will do
the right thing with them at the right time.  And since "forall"
doesn't care if the array you're iterating over is executable or
literal, you can use executable arrays in cases where they array
you're looping over will always be the same, whose elements don't have
to be computed every time.

	-Don

amanda@intercon.uu.net (Amanda Walker) (08/10/89)

In article <18978@mimsy.UUCP>, don@brillig.umd.edu (Don Hopkins) writes:
> Quite right! But you could also go:
> 
> {en to tre fire} {0 50 translate exec} forall

You can also do:

	{en to tre fire} {0 50 translate exec} bind forall

Which will probably be marginally faster (except under NeWS, where the
interpreter will do the "bind" for you by default...).

--
Amanda Walker
InterCon Systems Corporation
--
amanda@intercon.uu.net    |    ...!uunet!intercon!amanda