[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Read time/compile time

I have been wrestling with the T feature that all macros are expanded
when a function is defined.  Although my knee-jerk-stylist reflex was
to see this as a straightforward way of forcing read time and compile
time to be logically the same, it has proved to be such a pain that
I started questioning it.  The more I question, the fewer answers
occur to me.  I suppose the basic answer is, Things have to be this
way to make the compiler run smoothly.  This raises the question,
How come everything used to seem smoother in the Good Old Days?

To be concrete, I have some type-definition stuff whereby you
can define things like this:

(DEFINE TYPE-FOO -basic-definition-

(DEFINE TYPE-BAZ -basic-definition-

The patches are essentially function definitions (they provide a
flexible way of defining slots -- like operations, but filling a
different need).  The whole point of defining types like these is
so they will be known at compile time in other function
definitions.  When a function using slot S of type FOO (notated
:(FOO S)) is compiled, all that has to be known about :(FOO S)
are the names and types of the accesser and setter of :(FOO S),
and the type of the contents of :(FOO S).  There is no need at
compile time to actually run the accesser or setter, and hence no
need to expand the definition (e.g., if it is defined in another

There is nothing preventing the patches of FOO and the patches
of BAZ from referring to each other.  That is :(FOO S) might
be defined by a function that refers to slot :(BAZ R), and vice
versa.  This causes no trouble under the old regime.  At interpret
time the right thing obviously happens.  At compile time, each
function only needs to know the "external" information described
before.  (You do need a two-pass compiler to make sure the
external information is extracted before compilation begins.)

Under the new regime, the whole thing collapses, even in
interpreted code.  T insists on knowing about :(BAR R) while
defining :(FOO S), and vice versa.  So far, I have avoided the
problem by rearranging files, but clearly that is not a general

I suppose the "official" response is that, since compiled and
interpreted T are identical, I should just go to a two-pass
loader of interpreted code.

On the other hand, there is really no reason for things to stay
the way they are.  As far as I can see, adding a hack to the
interpreter to delay macro-expansion until the first call would
solve the problem.  (Sorry -- if hacks offend you, think of it
as a kind of functional call by need.)

If all that seems esoteric, here is a practical consideration
that everyone will appreciate:  One often loads a file full of
interpreted functions with the intention of running only a
fraction of them.  Why should you have to pay for macro-expanding
all of them?

An alternative is for me to define DE to interpose a level of
indirection and delayed evaluation between function definition
and calling. I have a feeling that this would be a mess.

How do other people feel about this issue?