[comp.lang.lisp.x] autoload

jsp@glia.biostr.washington.edu (Jeff Prothero) (11/20/90)

I'd kind of like to have xlisp load in class definitions as needed,
so I can have a large class library available without bogging down
by loading *all* of them at startup.  Looks simple to intercept
a (send xxx :new) and load file xxx.lsp from a directory specified
in, say, the environment variable XLISP-PATH.

Has anyone done this already?  I don't offhand see anything in CLtL:1
or CLOS about this.  PROVIDE and REQUIRE don't seem directly
relevant... Is there a standard syntax for making environment strings
available in lisp?
--
     jsp@glia.biostr.washington.edu (Jeff Prothero)
     jsp@u.washington.edu (If above bounces.)
     Biological Structure Graphics Lab, U Washington

mayer@hplabsz.HPL.HP.COM (Niels Mayer) (11/21/90)

In article <JSP.90Nov19145438@glia.biostr.washington.edu> jsp@glia.biostr.washington.edu (Jeff Prothero) writes:
>I'd kind of like to have xlisp load in class definitions as needed,
>so I can have a large class library available without bogging down
>by loading *all* of them at startup.  Looks simple to intercept
>a (send xxx :new) and load file xxx.lsp from a directory specified
>in, say, the environment variable XLISP-PATH.
>
>Has anyone done this already?  I don't offhand see anything in CLtL:1
>or CLOS about this.  PROVIDE and REQUIRE don't seem directly
>relevant... Is there a standard syntax for making environment strings
>available in lisp?

I've thought about and wanted this too... we currently use something akin
to PROVIDE/REQUIRE, but it is not nearly as automatic as what you suggest.

I believe that PROVIDE and REQUIRE are the right way to do this at the
primitive level. Why?? Because you'll have to do something similar to what
common lisp does anyway, so you might as well be compatible.

The other thing to look at is gnuemacs' autoload capabilities. For example,
whenever function call '(webster)' is evaluated, or whenever the command
"M-X webster" is given, gnuemacs will load the file "webster.el" (using the
path list set to symbol 'load-path'). THe call to set this up is:

  (autoload 'webster "webster" "look up a word in Webster's 7th edition" t)

With your (send xxx :new) example, you must do the OOP equivalent of
gnuemacs' 'autoload' -- rather than working on function call, it would have
to work on instatiation.

Off the top of my head, I think the way to hack this up is to use a
two-step :isnew initialization process....

Set up a function (autoload <class-sym-name> [<file-name>]) which sets
<class-sym-name> to an autoload-class object. The first time that you call
:new on the autoload-class object, the :isnew method on the autoload-class
object will load the appropriate class definition file, replace the
class-object value for <class-sym-name> with the just-loaded class
definition, and then call :isnew on that class. Information on the name of
the file to load would reside on a class variable in a subclass of
autoload-class....

This is probably full of holes and problems. Subtle problems can occur by
replacing the class object value of <class-sym-name> -- perhaps reusing the
original class-object and changing it's internals based on the info from
the loaded file is a better idea... As I said, it's just an
off-the-top-of-my-head implementation sketch.

Of course, this won't help at all for loading c-implemented classes (e.g.
loading a Motif widget class in WINTERP only when the class is needed.)
That requires dynamic loading and dynamic expansion of funtab[] -- this is
doable, but there don't seem to be any standards for portable dynamic
loaders on Unix. In WINTERP, I punted on this and on other things that
violated the KISSP principle (Keep It Simple Stupid and Portable)...

			--------------------

FYI, here's an implementation of PROVIDE/REQUIRE someone sent me:

; -*-Lisp-*-
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; File:         provide-require.lsp
; RCS:          $Header: provide-require.lsp,v 6.0 90/05/22 10:32:24 ken Exp $
; Description:  implement the Common Lisp provide and require functions.
; Author:       Eric Blossom, HP Response Center Lab
; Created:      Mon Feb 12 19:05:25 1990
; Modified:     Tue May 15 22:42:55 1990 (Eric Blossom) eric@hprcleb
; Language:     Lisp
; Package:      N/A
; Status:       Experimental (Do Not Distribute)
;
; (C) Copyright 1990, Hewlett-Packard Company, all rights reserved.
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;; For now, when we load provide-require, forget any already loaded modules
;(defvar *modules* nil)
(setq *modules* nil)

(defvar *default-load-path* '("."))

(defun provide (module-name)
  (let ((s (cond ((symbolp module-name)
		  (symbol-name module-name))
		 ((stringp module-name)
		  module-name)
		 (t
		  (error "wrong type argument to provide" module-name)))))

    (if (member s *modules* :test #'equal)
	t
      (setq *modules* (cons s *modules*)))

    t))

  
(defun require (module-name &optional pathname)
  (let ((s (cond ((symbolp module-name)
		  (symbol-name module-name))
		 ((stringp module-name)
		  module-name)
		 (t
		  (error "wrong type argument to require" module-name)))))
  (if (member s *modules* :test #'equal)
      t
    (if (not (try-to-load s pathname))
	(error "can't find required module" module-name)
      t))))

(defun try-to-load (module-name pathname)
  (or (and pathname (load pathname :verbose t))
      (try-to-load-using-load-path module-name *default-load-path*)))

(defun try-to-load-using-load-path (name path-list)
  (if (null path-list)
      nil
    (let ((path (strcat (first path-list) "/" name)))
      (if (load path :verbose nil)
	  (progn
	    (format t "; loading ~S\n" path)
	    t)
	(try-to-load-using-load-path name (cdr path-list))))))

-------------------------------------------------------------------------------
	    Niels Mayer -- hplabs!mayer -- mayer@hplabs.hp.com
		  Human-Computer Interaction Department
		       Hewlett-Packard Laboratories
			      Palo Alto, CA.
				   *

jsp@glia.biostr.washington.edu. (Jeff Prothero) (11/23/90)

In article <6241@hplabsz.HPL.HP.COM> mayer@hplabsz.HPL.HP.COM (Niels Mayer) writes:

>Of course, this won't help at all for loading c-implemented classes (e.g.
>loading a Motif widget class in WINTERP only when the class is needed.)
>That requires dynamic loading and dynamic expansion of funtab[] -- this is
>doable, but there don't seem to be any standards for portable dynamic
>loaders on Unix.

gnu.announce has a candidate standard:

 Dld version 3.2.1 is now available in prep.ai.mit.edu.  Dld is
 a library package of C functions that performs *dynamic link/unlink
 editing*.  Programs that use dld can *ADD* compiled object code to or
 *REMOVE* such code from a process anytime during its execution.
 Loading modules, searching libraries, resolving external references,
 and allocating storage for global and static data structures are all
 performed at run time.

 Currently dld is available for Vax, Sun3 and SparcStation.

Also, since my original post, I've noticed that xlispstat has autoload
support.  Haven't looked at it in detail yet.
--
jsp@glia.biostr.washington.edu (Jeff Prothero)
jsp@u.washington.edu (If above bounces.)
Biological Structure Graphics Lab, U Washington