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

Re: coercion to functions



> To: info-mcl
> From: spector@mimsy.umd.edu (Lee Spector)
> Newsgroups: comp.lang.lisp.mcl
> Subject: coercion to functions
> Date: 12 Sep 91 16:28:07 GMT
> 
> I'm working on something that does a lot of dynamic creation of functions,
> and this has lead me to a couple of observations and questions.
> 
> (eval `#'(lambda () ...)) runs very slowly.  In my system I have invocations
> that take about 6 seconds.  I suppose this is because the compiler is being
> invoked.  The resulting function, however, runs quickly.
> 
> (coerce `(lambda () ...) 'function) has the same funcitonal behavior (as per
> CLtL2, p.65: "A list x whose car is the symbol lambda is coerced to a function
> as if by execution of (eval `#',x) ...")  However, the COERCE version runs
> very quickly (much less than a second everywhere in my system); while the
> function that it creates runs slowly.  I suppose the COERCEd function isn't
> compiled until run time, if at all.
> 
> The COERCE version suits my needs better for the moment, since I create many
> functions at once and I'd rather have the delay distributed through the future
> than all at once.  However, I have a couple of questions:
> 
> 1) Is the COERCEd version being compiled at all?  If so, could the compiled
>    code be saved for subsequent runs?
> 

In 2.0b1, (COERCE `(LAMBDA () ...) 'FUNCTION) produces an interpreted
function, whereas (EVAL `#'(LAMBDA () ...)) invokes the compiler iff
*COMPILE-DEFINITIONS* is true (the default). Hence the relative timings
of function creation and invocation. In 2.0 final, both will depend on
the value of *COMPILE-DEFINITIONS*.

> 2) Is there any good way to speed up either of these techniques?  Particular
>    declarations etc. that will have an effect?  These delays are significant...

If you want your code to run quickly, you have to compile it.  If you need
to be able to cons up functions quickly, you probably can't afford to wait
for the compiler.  Catch 22, I'm afraid.  One thing that could make the
compiler run faster if you can afford the memory is to disable purging of
swappable functions.  Then the compiler won't need to be swapped in every
time you compile a function.  You can do this with (PURGE-FUNCTIONS NIL).
This will probably cause MCL to require a 4 megabyte partition.

> 
> 3) Is the behavior that I've observed stable? i.e, can I expect that the same
>    thing will occur in MCL2.0 final?

Since the behavior of COERCE has changed for 2.0 final, I suggest that you
do the following to get behavior that will remain the same for both:

(let ((*compile-definitions* nil))
  (eval `#'(lambda () ...)))

> 
> 4) Is my analysis totally off base?

Looks sound to me.

> 
> I've included a few lines of code below to show what I mean. Thanks in advance
> for any help or musings etc. you can provide!
> 
> [...]

Ciao.

Bill St. Clair
bill@cambridge.apple.com