From: Tin Gherdanarra
Subject: recursive load/require
Date: 
Message-ID: <516isqF1ivjbbU1@mid.individual.net>
Good morning.

If string.lisp requires a function in util.lisp,
and util.lisp requires a function in string.lisp,
what's a lad supposed to do? The mutually recursive
loads blow up the computer.

I lifted a trick from C. In pseudo-code:


FUNCTION smart-load "loadee"
IF we-have-already-loaded "loadee"
THEN dont-load
ELSE load "loadee".

In Lisp-code:
(defun smart-load (loadee)
   (unless (gethash loadee *loaded*)
     (setf (gethash loadee *loaded*) t)
     (load loadee)))

My question: Anything wrong with that? Is this
the way real Lispniks do this?


-- 
Lisp kann nicht kratzen, denn Lisp ist fluessig

From: ·············@gmail.com
Subject: Re: recursive load/require
Date: 
Message-ID: <1169037912.596913.28670@51g2000cwl.googlegroups.com>
Uhm, I'd say it depends on what you mean by "requires a function
in...". If the function is not called during load-time (e.g. it is only
used in the bodies of functions and/or macro expansions) then the order
in which you load the files doesn't matter, since Lisp is able to deal
with forward-referenced functions. Just load them both one after the
other.
If, instead, the function is actually used when the file is loaded
(e.g. the function is called to expand a macro) then your solution has
more sense, but I think the best way is just to put the incriminated
functions in a third file and load that before the other 2. Maybe with
the help of some system definition library such as ASDF... Somebody
else might give you a better answer, though.
From: Thomas A. Russ
Subject: Re: recursive load/require
Date: 
Message-ID: <ymiejpte4sj.fsf@sevak.isi.edu>
Madhu <·······@meer.net> writes:
> (require 'strings #p"/path/to/strings.lisp")
>  ;; utilities
> 
> 
> With the caveat, of course, that this portable use of PROVIDE and
> REQUIRE with physical pathnames will make this non-portable...

Couldn't you get portability by using logical pathnames?

--
Thomas A. Russ,  USC/Information Sciences Institute
From: ···············@space.at
Subject: Re: recursive load/require
Date: 
Message-ID: <uzm8hh4ad.fsf@space.at>
>>>>> "Madhu" == Madhu  <·······@meer.net> writes:

    Madhu> * Tin Gherdanarra <···············@mid.individual.net> :
    Madhu> | If string.lisp requires a function in util.lisp,
    Madhu> | and util.lisp requires a function in string.lisp,
    Madhu> | what's a lad supposed to do? The mutually recursive
    Madhu> | loads blow up the computer.

    Madhu> No such thing happens if you PROVIDE the module-name at the top of
    Madhu> each file.  Assuming you have taken care that functions required at
    Madhu> load/compile time are available, the following should produce no
    Madhu> problems.

    Madhu> ;;; strings.lisp
    Madhu> (provide 'strings)
    Madhu> (require 'utils #p"/path/to/util.lisp")
    Madhu>   ;; string functions

    Madhu> ;;; utils.lisp
    Madhu> (provide 'utils)
    Madhu> (require 'strings #p"/path/to/strings.lisp")
    Madhu>  ;; utilities

    Madhu> With the caveat, of course, that this portable use of PROVIDE and
    Madhu> REQUIRE with physical pathnames will make this non-portable...

Chris Riesback said it best [1]:
  I recommend putting the provide at the end, because

    * if the file fails to load completely, a provide at the front
      will fool Lisp into thinking that the module has been loaded
    * circular dependencies should be fixed, not supported

[1] http://www.cs.northwestern.edu/academics/courses/325/readings/require.html


                                regards
                                    Roland
From: Andreas Thiele
Subject: Re: recursive load/require
Date: 
Message-ID: <eomgg5$674$00$1@news.t-online.com>
<···············@space.at> schrieb im Newsbeitrag ··················@space.at...
>>>>>> "Madhu" == Madhu  <·······@meer.net> writes:
> 
> Chris Riesback said it best [1]:
>  I recommend putting the provide at the end, because
> 
>    * if the file fails to load completely, a provide at the front
>      will fool Lisp into thinking that the module has been loaded
>    * circular dependencies should be fixed, not supported
> 
> [1] http://www.cs.northwestern.edu/academics/courses/325/readings/require.html
> ...

Chris Riesback seems to prefer provide/require over defsystem(/asdf). Interesting point.

What do other people think?

Andreas
From: ···············@space.at
Subject: Re: recursive load/require
Date: 
Message-ID: <uvej4helb.fsf@space.at>
>>>>> "Andreas" == Andreas Thiele <······@nospam.com> writes:

    Andreas> <···············@space.at> schrieb im Newsbeitrag ··················@space.at...
    >>>>>>> "Madhu" == Madhu  <·······@meer.net> writes:
    >> 
    >> Chris Riesback said it best [1]:
    >> I recommend putting the provide at the end, because
    >> 
    >> * if the file fails to load completely, a provide at the front
    >> will fool Lisp into thinking that the module has been loaded
    >> * circular dependencies should be fixed, not supported
    >> 
    >> [1] http://www.cs.northwestern.edu/academics/courses/325/readings/require.html
    >> ...

    Andreas> Chris Riesback seems to prefer provide/require over
    Andreas> defsystem(/asdf). Interesting point.

That's what I thought as well.

    Andreas> What do other people think?

To some extent it is a matter of preference, but I believe that
asdf/defsystem is more powerful than provide/require, at least
I do not know how to distinguish between compiling, loading source and
loading compiled code with (ANSI) require.
Comments from the wizards would be very welcome!

                                  regards
                                    Roland
From: Tin Gherdanarra
Subject: Re: recursive load/require
Date: 
Message-ID: <518vtfF1jd911U1@mid.individual.net>
Madhu wrote:
> * Tin Gherdanarra <···············@mid.individual.net> :
> | If string.lisp requires a function in util.lisp,
> | and util.lisp requires a function in string.lisp,
> | what's a lad supposed to do? The mutually recursive
> | loads blow up the computer.
> 
> No such thing happens if you PROVIDE the module-name at the top of
> each file.  Assuming you have taken care that functions required at
> load/compile time are available, the following should produce no
> problems.
> 
> ;;; strings.lisp
> (provide 'strings)
> (require 'utils #p"/path/to/util.lisp")
>   ;; string functions
> 
> ;;; utils.lisp
> (provide 'utils)
> (require 'strings #p"/path/to/strings.lisp")
>  ;; utilities
> 
> 
> With the caveat, of course, that this portable use of PROVIDE and
> REQUIRE with physical pathnames will make this non-portable...
> 
> -- Madhu

Thanks, this advice is infinitely excellent.
I also liked the link to Jens Riesbeck's explanation
of this, and how to handle search paths.

For the record: Putting PROVIDE last does not work
for circular references, because /before/ the provide
has opportunity to update *MODULES*, the recursion
is entered and re-entered, and PROVIDE is never
reached. Anyways, it /does/ work very well if we
put PROVIDE first. Thanks.

-- 
Lisp kann nicht kratzen, denn Lisp ist fluessig
From: Andreas Thiele
Subject: Re: recursive load/require
Date: 
Message-ID: <eonsbu$m9g$01$1@news.t-online.com>
"Tin Gherdanarra" <···········@gmail.com> schrieb im Newsbeitrag ····················@mid.individual.net...
> ... the recursion
> is entered and re-entered, and PROVIDE is never
> reached. Anyways, it /does/ work very well if we
> put PROVIDE first. Thanks.
> ...

 I think Chris explicitely mentionend that putting provide at the end will result in an endless loop:
"Some authors recommend putting provide at the front of the file, in order to

  a.. advertise up front what module the file provides, and 
  b.. avoid endless loops if there be any circularities (file A requires file B which requires file A) "
Andreas
From: Tim X
Subject: Re: recursive load/require
Date: 
Message-ID: <87irf2v0iv.fsf@lion.rapttech.com.au>
Madhu <·······@meer.net> writes:

> * Tin Gherdanarra <···············@mid.individual.net> :
> | If string.lisp requires a function in util.lisp,
> | and util.lisp requires a function in string.lisp,
> | what's a lad supposed to do? The mutually recursive
> | loads blow up the computer.
>
> No such thing happens if you PROVIDE the module-name at the top of
> each file.  Assuming you have taken care that functions required at
> load/compile time are available, the following should produce no
> problems.
>
> ;;; strings.lisp
> (provide 'strings)
> (require 'utils #p"/path/to/util.lisp")
>   ;; string functions
>
> ;;; utils.lisp
> (provide 'utils)
> (require 'strings #p"/path/to/strings.lisp")
>  ;; utilities
>

I think this can be quite dangerous. If you put the provide at the top of the
file and for some reason, the file doesn't complete loading correctly, the
system will be under the wrong assumption that the functionality has been
provided when it hasn't or has only partial functionality. This can cause
subtle problems that waste time tracking down. I also think it is hiding the
symptom of a problem rather than addressing the cause of the problem (i.e.
circular dependency). 

IMO the 'provide' should be the last line in the file. 

Tim


-- 
tcross (at) rapttech dot com dot au