[plt-scheme] Re: cannot require 19.ss (srfi)
Hans Oesterholt-Dijkema wrote:
>> Since SRFI 19 defines names that conflict with primitives in the
>> mzscheme language, two modules are provided: srfi/19.ss provides the
>> names as defined in the SRFI document, srfi/19/time.ss provides `srfi:'
>> prefixed identifiers where clashes with mzscheme occur (eg.
>> srfi:make-date, srfi:date?, etc). 19.ss is meant to be used from the
>> top-level to write portable programs, whereas time.ss is convenient
>> to use when writing PLT modules.
>
>
> Since I've included 19.ss, and thus want these primitives, why doesn't
> 19.ss
> just override the existing primitives?
Suppose the module system did override conflicting names quietly.
Consider now the situation, where you
require the library A in order to use the function foo, and require the
library B in order to use bar. To your
great surprise something unexpected happens when using foo. What
happened? The library B incidently
also exported a function named foo (which you wasn't aware of, since it
was written by a friend), and
thus overrided the foo from A. Such a bug could be very time consuming
to find.
In order to squash this kind of bug, the module system demands that all
names inside a module
are defined only once. (Hm. I thought it was somewhere in chapter 12 of
the PLT MzScheme Langauge
Manual).
The most often occurence of conflicting names is when one requires
srfi-1 with (require (lib "srfi" "1.ss")).
The problem is that srfi-1 exports improved version of some of the
normal r5rs primitives, thus a
conflict arises with all the normal PLT languages.
E.g.:
(module foo mzscheme
(require (lib "1.ss" "srfi")))
will give the error
"module: identifier already imported (from a different source) in:
reverse!"
There are several solutions:
1. Import all of the srfi-1 except reverse! (and the other redefined
names),
then import the remaining names one at time, while renaming them.
(module foo mzscheme
(require
; import all from srfi-1 except the already defined names
(all-except (lib "1.ss" "srfi")
reverse! member map for-each assoc append!)
; import one name at a time from srfi-1, renaming at the same time
(rename (lib "1.ss" "srfi") srfi:reverse! reverse!)
(rename (lib "1.ss" "srfi")srfi:member member)
(rename (lib "1.ss" "srfi") srfi:for-each for-each)
(rename (lib "1.ss" "srfi") srfi:assoc assoc)
(rename (lib "1.ss" "srfi") srfi:append! append!))
; Now both functions can be used in the module body
(display (reverse! (list 1 2 3)))
(display (srfi:reverse! (list 1 2 3))))
Now (require foo) will display (3 2 1) (3 2 1)
NB: If you don't intend to use the conflicting names, then all you need is
to ban them with the (all-excpet ...). No need to rename them.
2. Use another language than mzscheme for your module.
; mini-mzscheme.scm
(module mini-mzscheme mzscheme
(provide
(all-from-except mzscheme
reverse! member map for-each assoc append!)))
; foo.scm
(module foo "mini-mzscheme.scm"
(require
; import all from srfi-1
(lib "1.ss" "srfi"))
; Now only the srfi-1 versions are availble
(display (reverse! (list 1 2 3))))
In the case of srfi-1 the PLT packaging provides "list.ss", which
exports the troublesome names with a s: -prefix:
(require (lib "list.ss" "srfi" "1"))
The above discussion also applies to srfi-19.
NOTE: Please move this line further up in the doc-page for srfi.
On a normal size screen the special info about srfi-1 doesn't
appear on the first page.
--
Jens Axel Søgaard