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