chicken-users
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Chicken-users] The point of 'provide'


From: John Cowan
Subject: Re: [Chicken-users] The point of 'provide'
Date: Sun, 3 Jan 2010 14:18:09 -0500
User-agent: Mutt/1.5.13 (2006-08-11)

Peter Bex scripsit:

> I had a problem today which I already had before: when you define a
> module, you cannot (use ) it unless you also (provide ) the extension:
> 
> #;1> (module foo (bar) (import chicken scheme) (define (bar) (print "bar")))
> ; loading /usr/pkg/lib/chicken/4/chicken.import.so ...
> ; loading /usr/pkg/lib/chicken/4/scheme.import.so ...
> #;2> (use foo)
> Error: (require) cannot load extension: foo

That is because 'use' does a 'require' (which calls 'provided?', and
if it returns #f, calls 'load').  If you define the module in this way,
you want to use 'import' rather than 'use'.

>  ....
> 
> To fix this:
> 
> #;2> (provide 'foo)

Here you have faked out 'provided?', and so the 'use' will succeed.
The proper procedure is to use 'import', though.

> #;3> (use foo)
> #;4> (bar)
> bar
> 
> 
> However, when you stick the module inside a file, other strange things
> happen:
> 
> #;1> (use foo)
> Error: (import) during expansion of (import ...) - cannot import from 
> undefined module: foo

There's a bug here, as shown by the traceback:

(##core#begin (##sys#require (quote foo)) (import foo))

This is an attempt to require *and then* import, but it cannot work,
because import is a macro and does its work at macroexpansion time,
whereas ##sys#require is a procedure and does its work at runtime.

> #;1> (load "foo.scm")
> ; loading foo.scm ...
> ; loading /usr/pkg/lib/chicken/4/chicken.import.so ...
> ; loading /usr/pkg/lib/chicken/4/scheme.import.so ...

Here you have loaded the file foo, bypassing the require/provide mechanism
completely.  The module foo now exists but is not imported.

> #;2> (use foo)
> ; loading ./foo.scm ...

This time, use foo works: it loads foo again because the previous load
did not affect 'provided?', and then imports it.  The bug is not tickled
because the module foo is already imported, so the macro call '(import
foo)' just vanishes.

> #;3> (bar)
> bar
> 
> Note the fact that first it can't find foo.scm (as the current working
> dir is not in the path searched by USE).  However, after loading it,
> suddenly USE can find the file and it _reloads_ the file.

That's because the module 'foo' is now known because you have done the
'load'.  Note the distinction: the module is known to the module system,
but the file is not known to the require/provide system.

> Reloading the file is wrong behaviour, IMHO, because the file is already
> loaded, and reloading it will wreak havoc if the module defines global
> variables to keep track of things: those are reset.  It will also rerun
> any side-effects that are caused by forms on the module's toplevel.

You are always going to get this behavior if you mix load and require.
You can bypass the bug in 'use' by doing (require 'foo) followed by
(import foo).

> I understand that I can fix this by putting the (provide 'foo) in
> foo.scm, or in the file that LOADs it, so afterwards it can be USEd
> safely.  What I don't understand is why this can't be handled
> automatically by the MODULE form.  In fact, _something_ registers the
> fact that that module comes from this loaded file.  Since this is
> registered, the system should also already know that this can only be
> because the module's code is already loaded.  Why the reload upon USE?

Because files and modules are orthogonal: a module may exist without a
file (as in your first example) and a file need not contain a module.

-- 
Where the wombat has walked,            John Cowan <address@hidden>
it will inevitably walk again.          http://www.ccil.org/~cowan




reply via email to

[Prev in Thread] Current Thread [Next in Thread]