rokicki@neon.Stanford.EDU (Tomas G. Rokicki) (05/05/91)
Bind cuases problems if a document that includes a definition such as /p /show load def then includes a graphic file that does something along the lines of /test { /p exch def p show } bind def for a simple example. I have found that this happens fairly often. -tom
Jamie Zawinski <jwz@lucid.com> (05/05/91)
In article <488@heaven.woodside.ca.us> glenn@heaven.woodside.ca.us (Glenn Reid) wrote: > > Maybe it's not "bind" that's at fault, but for people (like me) to > recommend using "load" to tie an operator directly to a user name. > Perhaps you shouldn't do that unless you're quite sure the name is > likely to be unique. I think the problem is using insanely short identifier names. This isn't AppleSoft Basic! If you're doing something like /p /show load def then I can respect that, because it's probably to reduce file size. But if you're doing /test { /p exch def p show } bind def then you've probably got no excuse. Not only does the name "p" have no semantic content, making the code hard to decipher if it's not a trivial example like this, but since PostScript has -no- facility for local variables or lexical scope, you're just asking for trouble. Every nominally "local" variable you use is screwing with the global namespace. Tread lightly. (I know you can pretend you have dynamically-scoped locals by consing dictionaries on the fly, but that's a big pain in the butt.) Anyway, in the /p /show load def example, upcasing the P couldn't hurt either... -- Jamie
glenn@heaven.woodside.ca.us (Glenn Reid) (05/06/91)
Tomas G. Rokicki writes > Bind cuases problems if a document that includes a definition such as > > /p /show load def > > then includes a graphic file that does something along the lines of > > /test { /p exch def p show } bind def > > for a simple example. I have found that this happens fairly often. Hmmm. So the problem is really a name collision between an outer and an inner program that use the same variable name. Maybe it's not "bind" that's at fault, but for people (like me) to recommend using "load" to tie an operator directly to a user name. Perhaps you shouldn't do that unless you're quite sure the name is likely to be unique. If the original document had used /p { show } bind def There would be no problem. "bind" actually helps in this case, and although there's procedure call overhead, it's almost as fast as /p /show load def It's not just "free variables" that cause the problem. It's limited to names that are bound directly to operators, which can only be accomplished using the "load" operator. I'd place the blame there. -- Glenn Reid RightBrain Software glenn@heaven.woodside.ca.us NeXT/PostScript developers ..{adobe,next}!heaven!glenn 415-326-2974 (NeXTfax 326-2977)
bvs@BitBlocks.COM (Bakul Shah) (05/06/91)
rokicki@neon.Stanford.EDU (Tomas G. Rokicki) writes: >Bind causes problems if a document that includes a definition such as > /p /show load def >then includes a graphic file that does something along the lines of > /test { /p exch def p show } bind def >for a simple example. I have found that this happens fairly often. This is a problem due to the dynamic scoping rules of postscript. What happens if show was redefined in the enclosing environment? The included file has no easy way of protecting itself from such redefinitions, with or without the use of bind. The point is that a programmer has to know language rules and their consequences. Of course, this particular problem is very hard to figure out without being actually bitten by it. And may be even then. A workaround may be to define a procedure that binds to operators only if their names appear in system dict and redefine bind to it (assuming new definitions do not get put in systemdict). Redefining bind to a null proc will work even better but bind does improve performance in some cases so that may not be such a great idea. IMO Adobe should write an app-note about the correct use of bind and other consequences of dynamic scoping to help avoid such problems. Hopefully. Bakul Shah bvs@BitBlocks.com
tneff@bfmny0.BFM.COM (Tom Neff) (05/06/91)
In article <JWZ.91May5141303@thalidomide.lucid.com> jwz@lucid.com (Jamie Zawinski) writes: >I think the problem is using insanely short identifier names. This isn't >AppleSoft Basic! No, but it frequently is serially transmitted. The urge to keep spooling time to a minimum is a natural one. When you reach the point where you're picking weird names to try and survive, there's something wrong.
andwi@ida.liu.se (Andreas Wickberg) (05/06/91)
In article <488@heaven.woodside.ca.us> glenn@heaven.woodside.ca.us (Glenn Reid) writes: >Maybe it's not "bind" that's at fault, but for people (like me) to >recommend using "load" to tie an operator directly to a user name. >Perhaps you shouldn't do that unless you're quite sure the name is >likely to be unique. I don't agree. If the idea of EPS-files should work, both sides must cooperate. Since there are a lot of programs out there already, new programs must add some extra protection both when importing and exporting. The current bind problem should be solved by 'declaring' variables before they are used. For example, /s /show load def ... /s () def /m { /s exch def s show } bind def This is not too much work once you get used to it. The importing program should also take some actions. The most common is to have a special dict that contains all the 'loaded' operators, and use a unique name for this dict in userdict. As a bonus you will avoid some dict overflows (when you use the Macintosh PrintManager you will run inside the md dict, not userdict, and this might have a quite small extra space sometimes.) Of course, your special dict will only be on the dict-stack for you own routines, when importing an EPS you might instead push a dict that redefines some operators (for color separations), and then push userdict. When you get all this to work, try to import and color separate an EPS-file created in your own program... Andreas
jwz@lucid.com (Jamie Zawinski) (05/07/91)
In article <80426796@bfmny0.BFM.COM> tneff@bfmny0.BFM.COM (Tom Neff) wrote: > In article <JWZ.91May5141303@thalidomide.lucid.com> jwz@lucid.com (Jamie Zawinski) writes: >>I think the problem is using insanely short identifier names. This isn't >>AppleSoft Basic! > > No, but it frequently is serially transmitted. The urge to keep > spooling time to a minimum is a natural one. When you reach the point > where you're picking weird names to try and survive, there's something > wrong. If you will recall, what I said was > I think the problem is using insanely short identifier names. This isn't > AppleSoft Basic! If you're doing something like > > /p /show load def > > then I can respect that, because it's probably to reduce file size. But if > you're doing > > /test { /p exch def p show } bind def > > then you've probably got no excuse. I am not suggesting that the non-prolog part of PostScript files look like (foo) draw-one-word-at-current-point (bar) draw-one-word-at-current-point (baz) draw-one-word-at-current-point but I am suggesting that, in the prolog sections, nominally local variables should have long names. To do otherwise is an affront to all that is holy. You shouldn't be "picking weird names to try and survive." You should be picking meaningful identifiers because it's good programming style in any language. If you are writing a prolog that is large enough to be a transmission-time hit in and of itself, like the prologs generated by most mac programs, and by Adobe Illustrator, then you're doing something wrong already. It's not really very hard AT ALL to structure your PostScript-producing application to dump out only the subroutines which are necessary to a particular document. If I'm just printing text, I don't need all those routines to screw around with RGB values and curves, thank you very much. -- Jamie
jwz@lucid.com (Jamie Zawinski) (05/10/91)
In article <1998@chinacat.Unicom.COM> woody@chinacat.Unicom.COM (Woody Baker @ Eagle Signal) wrote: > In article <JWZ.91May6183906@thalidomide.lucid.com>, jwz@lucid.com (Jamie Zawinski) writes: >> >> If you are writing a prolog that is large enough to be a transmission-time >> hit in and of itself, like the prologs generated by most mac programs, and >> by Adobe Illustrator, then you're doing something wrong already. It's not > > I think that the prolog generaly is a small portion of the file. I have seen many many (generated) files where the prolog was a staggering amount larger than it should have been, like 800%. There's no excuse. > The deeper problem as far as transmission times go, is the many references > to a variable name. For example, if you have a variable called > Current_X_Position You have 18 characters. If you use this each time > you have to position a word on the page, it is going to add up to A LOT > of transmission time, and space. Much better to use X in this case. Yes, I said this. > For a compiled language, it does not matter, as the variables are reduced > to memory locations at compile or link time, but for interpreters, it does > matter. Lookups take time. The scheme that Adobe uses, is fast, but still > takes time. [...] > In general, in an interpreter type language, the most frequently used > variables should be as short as possible name wise, and the less frequently > used variables should be longer. No! These two pieces of code will run at exactly the same speed: /foo { 0 1 10 { /x x 1 add def } for } def /foo { 0 1 10 { /a-much-longer-name a-much-longer-name 1 add def } for } def The second will take an infinitesimal amount of time longer to PARSE, but once parsed, the executable array which the interpreter has a handle on contains pointers to the name-objects themselves. It does not have to parse the name each time through the loop. Anyway, I think an attempt to make a prolog section shorter by picking bad variable names is misguided to say the least. -- Jamie
woody@chinacat.Unicom.COM (Woody Baker @ Eagle Signal) (05/10/91)
In article <JWZ.91May6183906@thalidomide.lucid.com>, jwz@lucid.com (Jamie Zawinski) writes: > > > I think the problem is using insanely short identifier names. This isn't > > /p /show load def > > You shouldn't be "picking weird names to try and survive." You should be > picking meaningful identifiers because it's good programming style in any > language. I have to agree with this in part. For a compiled language, it does not matter, as the variables are reduced to memory locations at compile or link time, but for interpreters, it does matter. Lookups take time. The scheme that Adobe uses, is fast, but still takes time. > > If you are writing a prolog that is large enough to be a transmission-time > hit in and of itself, like the prologs generated by most mac programs, and > by Adobe Illustrator, then you're doing something wrong already. It's not I think that the prolog generaly is a small portion of the file. The deeper problem as far as transmission times go, is the many references to a variable name. For example, if you have a variable called Current_X_Position You have 18 characters. If you use this each time you have to position a word on the page, it is going to add up to A LOT of transmission time, and space. Much better to use X in this case. In general, in an interpreter type language, the most frequently used variables should be as short as possible name wise, and the less frequently used variables should be longer. This does make a certain amount of sense, because a variable that is used infrequently, can be forgotten about easily, and if it has a cryptic name, it makes it that much harder for the next guy coming along to understand things. Programs should be written for the next programmer who will follow you, this applies to Postscript as well as any other language. Cheers Woody
glenn@heaven.woodside.ca.us (Glenn Reid) (05/10/91)
Woody Baker @ Eagle Signal writes > In article <JWZ.91May6183906@thalidomide.lucid.com>, jwz@lucid.com (Jamie Zawinski) writes: > > > > > I think the problem is using insanely short identifier names. This isn't > > > /p /show load def > > > > You shouldn't be "picking weird names to try and survive." You should be > > picking meaningful identifiers because it's good programming style in any > > language. > I have to agree with this in part. For a compiled language, it does not > matter, as the variables are reduced to memory locations at compile or link > time, but for interpreters, it does matter. Lookups take time. The > scheme that Adobe uses, is fast, but still takes time. Name lookup is not affected by the length of the identifier name. Only scanning (or transmission time). > In general, in an interpreter type language, the most frequently used > variables should be as short as possible name wise, and the less frequently > used variables should be longer. This does make a certain amount of sense, Jamie's post was correct, although not many people seemed to read it carefully. There are two kinds of uses for identifiers (roughly speaking): A. those that are used only within procedures in the prologue, as variable names and as names for procedure names called from other procedures in the prologue. B. those used in the body of the document, to invoke procedures from the prologue. Identifiers in the "B" category should be short, because they're transmitted often. Identifiers in the "A" category should be long and readable, because they are only read ONCE (or a few times, at most) by the scanner, as it is digesting the prologue. Here's a short example, using a long name for a procedure that is only called from within the prologue, and a short name for an often-transmitted procedure call: /lock_coordinates { transform round exch round exch itransform } bind def /L { lock_coordinates moveto lock_coordinates lineto stroke } bind def %%EndProlog 100 300 500 700 L -- Glenn Reid RightBrain Software glenn@heaven.woodside.ca.us NeXT/PostScript developers ..{adobe,next}!heaven!glenn 415-326-2974 (NeXTfax 326-2977)