On Sat, Mar 8, 2014 at 7:15 PM, Faré <fahree@gmail.com> wrote:
Dear Liam,

> I am using asdf-system-connections and notice a glitch in its design. As the
> original author no longer maintains it, I'm try to fix this myself. This
> system is designed to allow the loading of a connected system (say "A")
> automatically when two or more dependent systems (say "B" and "C") are
> loaded. The problem I'm encountering is that when another system (say "D")
> is defined to depend on B and C, then A is not loaded until after D is done
> loading, but D may need the definitions in A. asdf-system-connections
> defines a function load-connected-systems which does the work of loading the
> connected system definitions, but this is called from a new #'operate :after
> method which apparently doesn't get called until A is done loading.
>
If you depend on A rather than merely on B and C, then
the obvious solution is to depend on A.

Thanks Faré, this is so obvious, I'm embarrassed I didn't think of it myself!

Actually, I would go so far as to discourage use of asdf-system-connections,
and encourage only explicit dependency on connection systems.
IIUC, the hu.dwim team changed their systems this way, at my suggestion.

> I am looking for a place from which to call load-connected-systems that will
> trigger its call as soon as it's able, i.e., immediately once both "B" and
> "C" are loaded. I'm not familiar with the internals of ASDF and wonder if
> someone can guide me to a good place to define this.
>
There is no such place. Even what asdf-system-connections is a bit of a stretch.
On @(ASDF3), you could try an after method on make-plan, or something like that,
but it will be quite ugly, and will confuse the hell out of the
methods that call
traverse-action directly, etc.

Frankly, the whole idea is bunk. A build system ought to be
predictable, reproducible, and minimize surprise.
asdf-system-connections, as it stands, is not great in this regards,
but at least does not disrupt the internal dependency model of ASDF;
it stands on top. Your proposed extension requires subverting basic
invariants of ASDF internals.

Well, I think it has some use, though now in the Quicklisp era it's less important, and that is to define an optional dependency for something that's incidental to the main system. For example, one of my projects (Antik) defines units as part of a large system for doing science/engineering math. As a convenience, it will  use the degree symbol. In order to get the degree symbol, I use cl-unicode. This is an incidental use of one (big) system for the occasional (cosmetic) augmentation of another. Most people will not care about units at all, and so loading cl-unicode grows the system mostly unnecessarily, and adding a new user-visible system definition complicates users' mindspace for a mostly unused benefit (and imagine you have 3 optional definitions like this - then you would need to define 7 new systems to capture each combination). The alternative is to give up on the degree symbol, but it is nice to have it when you use degrees, and easy (one line of source code) to add if cl-unicode is present.

The old Lisp machine (Symbolics) had an option in the defsystem form :load-when-systems-loaded, which allowed you to add on modules/files to be loaded when certain other specified system(s) were loaded, but would not force the load of those systems. This worked quite well and was very nice for a case like this.

From Symbolics SCT, Volume 12, "Program Development Utilities," p. 24:
:load-when-systems-loaded
"The :load-when-systems-loaded option instructs SCT not to load some
modules of a system when a set of required systems is not loaded.
When all the required systems become loaded, SCT automatically loads
the unloaded modules.
Including this option in a module has two effects:
- If the required systems are not all loaded, that module is not
loaded.
- When all the required systems become loaded, SCT goes back and loads
the module.
- You cannot safely patch that module, as it might not be loaded yet
at the time patches are loaded.
:load-when-systems-loaded differs from the :required-systems option
to defsystem in that :required-systems gives an error if the required
systems are not present.  :load-when-systems-loaded never gives an
error.
...
Example:
(defsystem print-spooler
   (:default-pathname t)
  (:module unix-spooler ("ux-spool")
           (:load-when-systems-loaded :unix-support))
  (:serial (:parallel "defs" "macros")
           "spooler"
           "unix-spooler"))
Suppose the system UNIX-SUPPORT    is _not_ loaded.  When you load the
PRINT-SPOOLER system, all the files in the system are loaded except
for those files in UNIX-SPOOLER module (namely, ux-spool).  If and
when you load the UNIX-SUPPORT system, the files in the UNIX-SPOOLER
[module] will get loaded."

[Yes, I still have the full set of Symbolics manuals on my shelf.]


Liam