From: robert maas, see http://tinyurl.com/uh3t
Subject: Autoload stubs (best-practice question)
Date: 
Message-ID: <rem-2007jan28-001@yahoo.com>
I have an application program in one Common Lisp source file, let's
call it 'main' for short. Some of the functions in that file call
utility functions in another file, let's call it "libr" for short.

I don't want to automatically nest the loading of libr inside the
loading of main. Instead I want to wait until a fuction in libr is
actually called, and *then* from inside the attempted call I want
to silently load libr and then proceed to call the actual function
which presumably is now defined as a result of loading libr.

What's the best way to do this?

One idea is to define a bunch of stubs for each function in libr
which is likely to be the first function called in the application,
which might be only one or two functions because all other
functions are logically used only after those very first functions
are used in the application.

Another idea is to have (unless (fboundp 'firstcalled) (load "libr..."))
at the start of each toplevel application function that is going to
call anything from libr, so all the functions are already defined
before first call attempt, and no stubs are needed.

Another idea is to install a hook on the undefinded-function
situation deep inside lisp somewhere, which first checks for
autoload properties before throwing a exception, instead silently
loading the needed file then re-trying the failed call.

I've been hacking variations of the first two ideas, but I'd like
to either clean up one or the other nicely or switch to the third.
What do you experts reccommed?
Don't tell me to load a asdf module and let it handle everything.
I'd rather understand what's going on, and code it myself, rather
than have all my stuff dependent on some third-party module just
for this simple autoloading task. (Not to mention that autoloading
an asdf autoload module begs the question.)

From: Kaz Kylheku
Subject: Re: Autoload stubs (best-practice question)
Date: 
Message-ID: <1170021954.158270.173460@a75g2000cwd.googlegroups.com>
On Jan 28, 12:08 pm, ·······@yahoo.com (robert maas, see http://
tinyurl.com/uh3t) wrote:
> I have an application program in one Common Lisp source file, let's
> call it 'main' for short. Some of the functions in that file call
> utility functions in another file, let's call it "libr" for short.
>
> I don't want to automatically nest the loading of libr inside the
> loading of main. Instead I want to wait until a fuction in libr is
> actually called, and *then* from inside the attempted call I want
> to silently load libr and then proceed to call the actual function
> which presumably is now defined as a result of loading libr.

This would be interesting if it was done efficiently /and/ if it 
supported re-loading the library whenever the loaded version is out of 
date with what's available on disk. Thus the function stubs could not 
be  performing the up-to-date check each time they are called.

> Don't tell me to load a asdf module and let it handle everything.

ASDF won't do this lazy loading. But you could hack the support into 
it. The module definition syntax could support a way of declaring a 
lazy module (with a list of functions ``through'' which the lazy 
loading is handled). For those functions, ASDF would generate stubs. 
The ASDF:LOAD-OP operation would then not load these modules, but 
instead generate the stubs, if necessary, and set a flag indicating 
that the module is out of date (if that is the case). The next call to 
those functions would then perform the load. In fact the stub 
functions could just be replaced by the real ones when the load 
occurs, so there is no overhead in calling them. If LOAD-OP finds the 
module to be loaded, but out of date, then it simply re-instates the 
stubs, so the next time any one of them is called, the load will 
occur, replacing those stubs by the real functions once again.

> I'd rather understand what's going on, and code it myself, rather
> than have all my stuff dependent on some third-party module just
> for this simple autoloading task. (Not to mention that autoloading
> an asdf autoload module begs the question.)

Of course, this hacked ASDF would still itself be loaded in the usual 
way. No chicken-and-egg problems.
From: Pascal Bourguignon
Subject: Re: Autoload stubs (best-practice question)
Date: 
Message-ID: <874pqakiq1.fsf@thalassa.informatimago.com>
·······@yahoo.com (robert maas, see http://tinyurl.com/uh3t) writes:

> I have an application program in one Common Lisp source file, let's
> call it 'main' for short. Some of the functions in that file call
> utility functions in another file, let's call it "libr" for short.
>
> I don't want to automatically nest the loading of libr inside the
> loading of main. Instead I want to wait until a fuction in libr is
> actually called, and *then* from inside the attempted call I want
> to silently load libr and then proceed to call the actual function
> which presumably is now defined as a result of loading libr.
>
> What's the best way to do this?
>
> One idea is to define a bunch of stubs for each function in libr
> which is likely to be the first function called in the application,
> which might be only one or two functions because all other
> functions are logically used only after those very first functions
> are used in the application.
>
> Another idea is to have (unless (fboundp 'firstcalled) (load "libr..."))
> at the start of each toplevel application function that is going to
> call anything from libr, so all the functions are already defined
> before first call attempt, and no stubs are needed.
>
> Another idea is to install a hook on the undefinded-function
> situation deep inside lisp somewhere, which first checks for
> autoload properties before throwing a exception, instead silently
> loading the needed file then re-trying the failed call.
>
> I've been hacking variations of the first two ideas, but I'd like
> to either clean up one or the other nicely or switch to the third.
> What do you experts reccommed?
> Don't tell me to load a asdf module and let it handle everything.
> I'd rather understand what's going on, and code it myself, rather
> than have all my stuff dependent on some third-party module just
> for this simple autoloading task. (Not to mention that autoloading
> an asdf autoload module begs the question.)


Well I'm no expert of autloading functions, but here is what I've done
for an autoloading function, after emacs feature:

(defmacro defautoload (name arguments loader)
  `(defun ,name ,arguments
     (load ,loader)
     (eval '(,name ,@arguments))))

;; I use it for example as:

(defautoload scheme () "LOADERS:PSEUDO")

It is assumed that the loader file will redefine the function defined
by the defautoload, otherwise of course an infinite loop occurs.  Note
that the use of EVAL also allows the loader file to define the name as
a macro instead of a function.

-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

"You can tell the Lisp programmers.  They have pockets full of punch
 cards with close parentheses on them." --> http://tinyurl.com/8ubpf
From: Barry Margolin
Subject: Re: Autoload stubs (best-practice question)
Date: 
Message-ID: <barmar-8A5F2F.17351528012007@comcast.dca.giganews.com>
In article <··············@thalassa.informatimago.com>,
 Pascal Bourguignon <···@informatimago.com> wrote:

> Well I'm no expert of autloading functions, but here is what I've done
> for an autoloading function, after emacs feature:
> 
> (defmacro defautoload (name arguments loader)
>   `(defun ,name ,arguments
>      (load ,loader)
>      (eval '(,name ,@arguments))))
> 
> ;; I use it for example as:
> 
> (defautoload scheme () "LOADERS:PSEUDO")
> 
> It is assumed that the loader file will redefine the function defined
> by the defautoload, otherwise of course an infinite loop occurs.  Note
> that the use of EVAL also allows the loader file to define the name as
> a macro instead of a function.

If you're going to allow the file to define the name as a macro, then 
you had better implement the autoload stub as a macro.  Otherwise, the 
"macro's" arguments will get evaluated when calling the stub.

Although there's no standard autoload in CL, I'll bet most of the 
popular implementations have it built in.

-- 
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***
From: Pascal Bourguignon
Subject: Re: Autoload stubs (best-practice question)
Date: 
Message-ID: <87r6tepxv1.fsf@thalassa.informatimago.com>
Barry Margolin <······@alum.mit.edu> writes:
> In article <··············@thalassa.informatimago.com>,
>  Pascal Bourguignon <···@informatimago.com> wrote:
>
>> Well I'm no expert of autloading functions, but here is what I've done
>> for an autoloading function, after emacs feature:
>> 
>> (defmacro defautoload (name arguments loader)
>>   `(defun ,name ,arguments
>>      (load ,loader)
>>      (eval '(,name ,@arguments))))
>> 
>> ;; I use it for example as:
>> 
>> (defautoload scheme () "LOADERS:PSEUDO")
>> 
>> It is assumed that the loader file will redefine the function defined
>> by the defautoload, otherwise of course an infinite loop occurs.  Note
>> that the use of EVAL also allows the loader file to define the name as
>> a macro instead of a function.
>
> If you're going to allow the file to define the name as a macro, then 
> you had better implement the autoload stub as a macro.  Otherwise, the 
> "macro's" arguments will get evaluated when calling the stub.

Good point.  We would have to have both a define-auto-load-function
and a define-auto-load-macro.


> Although there's no standard autoload in CL, I'll bet most of the 
> popular implementations have it built in.


-- 
__Pascal Bourguignon__                     http://www.informatimago.com/
Until real software engineering is developed, the next best practice
is to develop with a dynamic system that has extreme late binding in
all aspects. The first system to really do this in an important way
is Lisp. -- Alan Kay