[comp.lang.postscript] Bind problems

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)