eg.
/inch {72 mul} bind def
'bind' receives a 2-element executable array
containing the integer 72 and the name mul.
it notes the type of 72 (pushing /integer to it's internal stack)
it looks up the name mul and finds a polymorphic operator
that can accept an integer or a real on top of the stack
and notices that the stack image consists of an integer,
and replaces the name object with a polymorphic operator
that already "knows" that the top is an integer and needs
only to dispatch on the second element (or stackunderflow
if it's at the bottom of stack).
'bind' then returns the (optimized) procedure.
Do any existing interpreters go this far?
Is there further to go?
Not a good idea.
The following won’t beheave as prescribed in the PLRM:
/will-work { 1 1 mul } bind def
/will-fail { 1.0 1.0 //will-work 2 get exec } bind def
will-work = % OK
will-fail = % KO
quit
This code would fail:
/addSomething {
1 add
} bind def
/addSomething load 0 .5 put
2 addSomething
Yeah. ok. Even worse: it would try to interpret raw bits for
any object as though it were an integer. What's the result
of multiplying two names?!
Well, the idea to make it inside the accessible parts of an object is
bad.
But I could imagine it's possible to write a JIT-compiler that works
without that you notice it (except the higher execution speed).
That would be a lot of work to get it correct.
Regards,
-Helmar
What if I give it a different name, like bindfast?
And does anyone actually do what the example here shows?
Pull an operator out of a bound procedure and execute it?
While I accept the counterexample as valid, it does seem
a little artificial.
Yes, I do things like this sometimes (not only pull something from a
bound procedure, but also put something into it). One example where I
remember having done this: I wrote a PS program that reads binary
files that are used by a specific application to store symbols. The
symbols are polygons/polylines (unclosed polygons) with filled and/or
stroked parts. Each vertex is represented by three values: x/y
coordinates and a "z" value (ranging from 0 to 3) that says what kind
of vertex it is. I put the action that is associated with the z value
into an array like this:
/z_action
{
%Line (z = 0)
lineto
{%Jump (z = 1) %paint_proc x y
3 -1 roll exec %x y
moveto %-empty-
{stroke} %paint_proc'
}
{%Fill (z = 2) %paint_proc x y
3 -1 roll exec
moveto
{gsave eofill grestore stroke}
}
%JmpFil (z = 3)
moveto
} bind cvlit def
Later, when I read the z value from the file, I execute the associated
command like this:
//z_action exch get exec
I don't think it's a good idea to speculate about what programmers
will or won't do.
Thomas W.