This is the mail archive of the guile@sourceware.cygnus.com mailing list for the Guile project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: circular dependences


"Greg J. Badros" wrote:
> 
> AFAICT, no one ever responded to my concern about the handling of
> circular module dependences in Guile:
> 
> http://sourceware.cygnus.com/ml/guile/1999-10/msg00101.html
> 
> I repeat my message below.  This is becoming more and more of a problem
> for Scwm.  Should I really have to avoid circular dependences?  Does the
> new module system handle this better?
> 

It is my impression that the Guile module system as it stands attempts to
handle circular dependencies, sort of. The loading code specifically
tries to not what modules are in the process of being loaded, so if
others that are loaded as a result require them, they won't be loaded
again. However, I think it's following sort of a `letrec' model, in
that mutual dependencies are allowed, but may not be usable immediately
depending on context.

For instance, if you did

(letrec ((b a)
         (a #t))
  a
 )

You'd get about the same error as below:

guile> (letrec ((b a)
...          (a #t))
...   a
...  )
ERROR: In expression (letrec (# #) a):
ERROR: Unbound variable: a
ABORT: (misc-error)

However, indirect use is always OK:

(letrec ((b (lambda () a))
         (a #t))
  a
 )

is problem-free. In fact, the equivalent with the module system would also work
fine.

It would be nice to give a better error message, but I am not sure how it's
possible, since when modules are loading the statements are evaluated in
sequence, and there is no contextual knowledge of what variables might
be bound in other modules if the load order were different. I guess the
answer is to try to not depend on variables in other modules in
an immediate way as below, because there are no reasonable semantics
you could assign to mutually dependent modules that use each other's
variables. I mean, what would you do with:

bar.scm:
(define-module (bar)
  :use-module (foo))

(define-public b a)

bar.scm:
(define-module (foo)
  :use-module (bar))

(define-public a b)

However, it may be possible to at least give nicer errors if exports
were all declared as part of the `define-module' form - then circular
dependencies of this type could at least be detected.

 - Maciej


> Previous message follows:
> 
> Consider:
> 
> bar.scm:
> (define-module (bar)
>   :use-module (foo))
> 
> (define-public b a)
> ;; eof
> 
> foo.scm:
> (define-module (foo)
>   :use-module (bar))
> 
> (define-public a #t)
> ;; eof
> 
> test.scm:
> (use-modules (foo))
> ;; eof
> 
> Thus creating a circular dependency of modules.  With Guile-1.3.5 (CVS
> as of this weekend), when I do:
> 
> guile -s test.scm
> 
> I get the completely unintuitive and unhelpful:
> 
> ERROR: Unbound variable: a
> 
> Which is completely impossible to figure out since if I look at uses of
> `a', they are in a module that does the proper include.  A better error
> message here would be *much* appreciated.  Ideal something that
> describes the circular dependence relationship.
> 
> Though this example makes it seem like it'd be completely obvious when
> one has a circular dependency, it's definitely not-- I introduced one in
> a mesh of dozens of use-module in Scwm and struggled for a while to try
> to understand why I had an unbound variable warning.
> 
> Incidentally, the warnings when loading modules *with* real errors are
> also in need of improvement, IMO.
> 
> Thanks,
> Greg

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]