jnp@mjolner.tele.nokia.fi (J|rgen N|rgaard) (08/09/89)
Hello everybody, As I'm quite new to PostScript and having a problem I do not understand I hope somebody experienced can help me. 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 I would expect "method one" and "method two" to be equivalent. But they are not, but why ? (method one prints all characters on top of each other, method two prints all characters one above the other: 4 3 2 1 ) In the PostScript book (Adobe on Addison-Wesley) the "forall" operator is not (as I understand it) documented to save something. (Equipment: DEC LN03R, ScriptPrinter Version 47.2) Hope someone can enlighten me on this. -- -- | Regards, J|rgen N|rgaard ('|' is '\o{}' in \LaTeX{}) | | e-mail: jnp@tele.nokia.fi or pedersen%tnclus.dnet@tele.nokia.fi | -- telephone: <..>-358-0-511-5671 -- -- -- -- | Regards, J|rgen N|rgaard ('|' is '\o{}' in \LaTeX{}) | | e-mail: jnp@tele.nokia.fi or pedersen%tnclus.dnet@tele.nokia.fi | -- telephone: <..>-358-0-511-5671 --
richk@pogo.WV.TEK.COM (Richard G. Knowles) (08/10/89)
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 > >I would expect "method one" and "method two" to be equivalent. But they are >not, but why ? >(method one prints all characters on top of each other, > method two prints all characters one above the other: They are different because method 1 forall recieves an empty array and thus does not ever execute the proc. What is happening, however, is that the en, to, tre, and fire procedures are getting executed instead of being placed into the array. Since those procedures leave nothing on the operand stack the array ends up empty. Arrays are built, not created verbatim. Thus the '[' leaves a mark on the stack, each following token is parsed (and "executed" if executable), and the ']' packs all objects on the stack down to the mark into an array object. 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 -------- Whatever I say is my fault and no one elses! ----------- Richard G. Knowles richk@pogo.WV.TEK.COM Graphics Printing and Imaging (503) 685-3860 Tektronix, Inc; D/S 63-356 Wilsonville, Or 97070 or just yell "Hey, Rich!"
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
geof@apolling (Geof Cooper) (08/11/89)
In article <7725@pogo.WV.TEK.COM> richk@pogo.WV.TEK.COM (Richard G. Knowles) writes: > [/en /to /tre /fire ] { 0 50 translate load exec} forall should be "{ 0 50 translate load cvx exec }". Otherwise, a great response to the canonical PostScript "you should have used load" bug. I guess that the array [/en /to /tre /fire] gets turned into [/one /two /three /four] by the "translate" operator... :-) - Geof