From: Frode Vatvedt Fjeld
Subject: compilation of generated code
Date: 
Message-ID: <2hzoww2x5s.fsf@dslab7.cs.uit.no>
I have a function that returns a function [i.e. a list like
(lambda (x) ....)]

Now I would like to use this generated function like any other
function, and to have the function compiled like any other function
(at compile-time). I believe if I do this:

(compile 'generated-function (generate))

..then GENERATED-FUNCTION is compiled at load-time. How can I change
this so that it is compiled at compile-time? If I put the above form
inside an eval-when (compile), GENERATED-FUNCTION is unbound when I
load the compiled file (which somehow seems reasonable to me).

In case it is unclear: By compile-time above I mean when I do
COMPILE-FILE on the relevant file.


Thanks,
-- 
Frode Vatvedt Fjeld

From: R. Matthew Emerson
Subject: Re: compilation of generated code
Date: 
Message-ID: <87yacg8gtg.fsf@nightfly.apk.net>
Frode Vatvedt Fjeld <······@acm.org> writes:

> I have a function that returns a function [i.e. a list like
> (lambda (x) ....)]
> 
> Now I would like to use this generated function like any other
> function, and to have the function compiled like any other function
> (at compile-time). I believe if I do this:
> 
> (compile 'generated-function (generate))
> 
> ..then GENERATED-FUNCTION is compiled at load-time. How can I change
> this so that it is compiled at compile-time? If I put the above form
> inside an eval-when (compile), GENERATED-FUNCTION is unbound when I
> load the compiled file (which somehow seems reasonable to me).

If the function which returns a function as its value is a compiled
function, then the returned function will also be compiled.  You don't
have to do anything special.

Here is an example (using Allegro CL):

;; create a function which returns a function

USER(22): (defun make-counter ()
	    (let ((n 0))
	      #'(lambda ()
		  (incf n))))
MAKE-COUNTER

;; create a function
USER(23): (setf c1 (make-counter))
#<Interpreted Closure (:INTERNAL MAKE-COUNTER) @ #x109c50b2>

;; it works
USER(24): (funcall c1)
1
USER(25): (funcall c1)
2
USER(26): (funcall c1)
3

;; notice:  the returned function is not compiled, although it
;; is in fact a function.
USER(27): (type-of c1)
FUNCTION
USER(28): (compiled-function-p c1)
NIL

;; compile the generator function
USER(29): (compile 'make-counter)
MAKE-COUNTER
NIL
NIL
USER(30): (setf c2 (make-counter))
#<Closure (:INTERNAL MAKE-COUNTER 0) @ #x109c8092>

;; now the functions it returns are also compiled
USER(31): (compiled-function-p c2)
T

;; it works too
USER(32): (funcall c2)
1
USER(33): (funcall c2)
2
USER(34): (funcall c2)
3

Hope this helps.

-matt
From: Frode Vatvedt Fjeld
Subject: Re: compilation of generated code
Date: 
Message-ID: <2hvh7k2tae.fsf@dslab7.cs.uit.no>
> Frode Vatvedt Fjeld <······@acm.org> writes:
> 
> > I have a function that returns a function [i.e. a list like
> > (lambda (x) ....)]

···@nightfly.apk.net (R. Matthew Emerson) writes:

> Here is an example (using Allegro CL):
> 
> ;; create a function which returns a function
> 
> USER(22): (defun make-counter ()
> 	    (let ((n 0))
> 	      #'(lambda ()
> 		  (incf n))))

I may have been unclear about this, but my function-generating
function doesn't really generate objects of type function (or
closures), but lambda-lists.

Like this (would be nicer with backquote, I know):

(defun make-stupid-function (n)
  (list 'lambda ()
        (list '+ 1 n)))

: (make-stupid-function 3) => (lambda () (+ 1 3))
: (funcall (coerce (make-stupid-function 3) 'function)) => 4


I kind of solved the problem by making a macro that will call
make-stupid-function at read-time, so the whole thing expands to a
DEFUN form and really looks like any regular defun to the compiler.

-- 
Frode Vatvedt Fjeld
From: Barry Margolin
Subject: Re: compilation of generated code
Date: 
Message-ID: <f3RT3.28$Q6.1766@burlma1-snr2>
In article <··············@dslab7.cs.uit.no>,
Frode Vatvedt Fjeld  <······@acm.org> wrote:
>I may have been unclear about this, but my function-generating
>function doesn't really generate objects of type function (or
>closures), but lambda-lists.

Why not change your code to create closures?  That's usually the more
appropriate technique.

>I kind of solved the problem by making a macro that will call
>make-stupid-function at read-time, so the whole thing expands to a
>DEFUN form and really looks like any regular defun to the compiler.

Macros don't run at read time, they run at compile time, so I don't
understand what you're saying here.

-- 
Barry Margolin, ······@bbnplanet.com
GTE Internetworking, Powered by BBN, Burlington, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
From: Frode Vatvedt Fjeld
Subject: Re: compilation of generated code
Date: 
Message-ID: <2h904fok0q.fsf@dslab7.cs.uit.no>
Barry Margolin <······@bbnplanet.com> writes:

> Why not change your code to create closures?  That's usually the
> more appropriate technique.

Because the program transformations are too complex. If I was to
return a closure, this closure would consist of the complete
code-transformer function, and the original transformed to-be data. So
the code that gets compiled in this case is really just the
transforming code, not its output (which is what I wanted to do).

> Macros don't run at read time, they run at compile time, so I don't
> understand what you're saying here.

Hum.. yes, my mistake. But macros do run before the actual compilation
occurs, so I like to think of it as "before compile-time"
somehow. Anyways, it solved my problem. Thanks also to Tim Bradshaw
who suggested this.

-- 
Frode Vatvedt Fjeld
From: Erik Naggum
Subject: Re: compilation of generated code
Date: 
Message-ID: <3150625440252142@naggum.no>
* Frode Vatvedt Fjeld <······@acm.org>
| Hum.. yes, my mistake.  But macros do run before the actual compilation
| occurs, so I like to think of it as "before compile-time" somehow.

  I suggest you don't, as it will only confuse you terribly.

#:Erik
From: Barry Margolin
Subject: Re: compilation of generated code
Date: 
Message-ID: <YzYT3.42$Q6.2091@burlma1-snr2>
In article <··············@dslab7.cs.uit.no>,
Frode Vatvedt Fjeld  <······@acm.org> wrote:
>Barry Margolin <······@bbnplanet.com> writes:
>
>> Why not change your code to create closures?  That's usually the
>> more appropriate technique.
>
>Because the program transformations are too complex. If I was to
>return a closure, this closure would consist of the complete
>code-transformer function, and the original transformed to-be data. So
>the code that gets compiled in this case is really just the
>transforming code, not its output (which is what I wanted to do).

I suggest you take a look at data-directed programming, as it sounds like
this may be what you're doing.

-- 
Barry Margolin, ······@bbnplanet.com
GTE Internetworking, Powered by BBN, Burlington, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
From: Tim Bradshaw
Subject: Re: compilation of generated code
Date: 
Message-ID: <ey3u2n45o7j.fsf@lostwithiel.tfeb.org>
* Frode Vatvedt Fjeld wrote:

> In case it is unclear: By compile-time above I mean when I do
> COMPILE-FILE on the relevant file.

If the information needed (the source form, really) to compile the
function is available at compile time, then you should use a macro,
which will do what you want, because all your doing is what the macro
system does.  If it's not, then you can't do it any other way, you
just need to compile the function at run time.

--tim