On May 5, 2009, at 8:16 AM, Michele Simionato wrote:
When I first heard that non-used modules are not imported in Ikarus
my gut reaction was negative. I saw various issues with that approach.
All imported modules *are* imported. Ikarus imports them before it
goes on to doing anything.
The first issue is that what I write is not what I get: if I write
(import (x)) I expect the module x to be imported and I do not want
the compiler to lie to me.
How it it lying to you?
The second issue is that a programmer reading the import line will
assume that something comes from module x (even if the module is not
actually used)
Yes. Imported identifiers do come from such modules. They enter
into the importing scope and affect visible bindings and captured
environments.
and will waste time studying module x before realizing
that all of its exported bindings are not used.
True that studying dependencies by eyeballing is a waste of time.
Since the expander already does such analysis and records actual
dependencies, it might make sense to expose this information to
the user. I'll have to think about it.
Importing a module which is not used 99% of the times is a consequence
of refactoring: the dependency was used in the first version of the
script, or was used during development, and you forgot to drop it from
the import list.
This is a consequence of the fact that R6RS requires all imports
to be global to the library. I advocate local imports whenever I
can. If a library is used only in a small scope, say, a lambda
expression, then stick a (import (foo)) in that scope only. This
way, if said procedure is refactored such that (foo) is no longer
needed, the local import can be dropped without affecting the rest
of the library.
This happens to me all the time in Python, and I
solve the issue by using pylint, a tool that warns me about unused
modules.
It's more complicated in Scheme due to macros of course. :-)
In general, I think the right thing to do with unused modules is to
print a compiler warning and to import them anyway.
Should the following give a warning:
(library (FOO)
(export foo)
(import (rnrs) (BAR) #| exports bar |#)
(define-syntax foo
(syntax-rules ()
[(_) bar])))
(FOO) here does not reference any of the bindings of (BAR). It
would be absurd to print a warning, no?
If you silently ignore unused modules, and people rely on this
feature, the risk is to litter many programs with unused imports
which will just confuse your readers.
We agree that leaving unused imports in library code is a bad
idea. Forcing such libraries to be invoked makes the problem
worse, since you would come to expect that even libraries from
which you import nothing, i.e., (import (only (foo))), should
be invoked. Now you not only have to think about whether foo
is used, but whether that import can be dropped or not based
on whatever side effects (foo) has.
Finally, there the issue of modules which are just imported for
side effects. This happens 1% of the times, is tricky, I did not think
of it and I realized only yesterday the consequences (basically, it
makes it harder to use Matthew Flatt's trick to manage side-effects
at compile time).
For 90% of these 1% of programs, there is probably another
solution to the problem that does not involve side effects
and forced evaluations.
Aziz,,,