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

coercion to functions

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?

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...

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

4) Is my analysis totally off base?

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!

  -Lee (spector@cs.umd.edu)

P.S. I'm running MCL2.0b1p3 on a IIcx in a 6.7Meg partition under sys 6.0.7
;; this is slow
(time (dotimes (n 500) (eval `#'(lambda () ,n))))

;; this is "equivalent" but much faster
(time (dotimes (n 500) (coerce `(lambda () ,n) 'function)))

;; however, the results of the EVAL version run quickly
(time (let ((f (eval `#'(lambda () 23))))
          (dotimes (n 500) (funcall f))))

;; while the COERCE version runs slowly
(time (let ((f (coerce '(lambda () 23) 'function)))
          (dotimes (n 500) (funcall f))))

;; create-then-make-one-call is about the same with both techniques
(time (dotimes (n 500)
        (let ((f (eval `#'(lambda () ,n))))
          (funcall f))))
(time (dotimes (n 500)
        (let ((f (coerce `(lambda () ,n) 'function)))
          (funcall f))))