This is the mail archive of the guile@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] |
Modules---The Straw Man Attacks: This is some philosophy and a few proposals about semantic aspects of modules. To avoid mixing issues, I will say little about implementation. The intention is that the semantics should be clear, and implementable, using an arbitrary mixture of interpreter, compiler, and moby grokker. A module is not a run time object. This is hell on a compiler. Rather, a Scheme program may be broken into several files linked together by (load "filename") calls. These separate files are called modules. The meaning of the set of modules is given by describing how they can be patched together into a single Scheme program. Various kinds of pre-processing may be done to make the result more efficient, but that has no effect on the meaning. Problems of installation are handled by making sure the Guile system finds the right files. This is important, but it is not a semantic issue, and so is outside the scope. The expression (load "abc") has the same meaning as the expression (begin <contents of file "abc">) in the same context. Note that, according to R4RS section 5.2, definitions leak out of a begin. Putting a (load ..) form inside a binding form is perverse. There is no agreement on what it means, and I hope these proposals work without doing that. On the other hand, the following programs work as expected, and if variable p has a value known at compile time, then so does variable a. (if p (define a 1) (define a 0)) (if p (load "defa1") (load "defa0")) (Where the named files contain the obvious definitions.) Non-terminal syntactic variables used but not defined below are in R4RS. If there are N problems there should be N solutions. --------------- Problem: Avoid accidental identifier clashes Proposal: (with-prefix <identifier> <expression or definition>*) This special form is equivalent to (begin <expression or definition>*) but with every identifier that is defined by definitions in the list replaced by a new identifier. The new identifier is made by prefixing the original with the given <identifier> and a colon. This replacement is done to both the defining occurrence of the identifier and all applied occurrences. Example: guile> (with-prefix mapping (define (zip a b) (map cons a b)) (define (vadd x y)(map + (zip x y))) ) guile> (mapping:zip '(a b c) '(1 2 3)) ((a . 1)(b . 2)(c . 3)) guile> (with-prefix gnu (load "file-utilities")) guile> (gnu:ls "/") ("usr" "bin" "etc") The first expression is equivalent to (define (mapping:zip a b) (map cons a b)) (define (mapping:vadd x y) (map + (mapping:zip x y))) Rational: If you want to load two modules that might have clashing variable names you can systematically rename before loading them. If you have several mutually recursive definitions you can use short names when defining them but have them known globally by longer names that show that they are related. I think this all works without making the colon "special" in any way, but it may help the implementation to know that prefixes are possible only with a colon. ------------------- Problem: Limit the amount of text that must be read to know whether a particular variable is ever assigned to. Proposal: <variable-list or identifier> ::= <variable list> | <identifier> <variable-list> ::= ( <variable>* > (never-set <variable-list or identifier>*) This has no effect whatsoever on the meaning of the program, if the program remains correct. If the program containing this special form also contains any form like (set! <variable> ..), where the <variable> also occurs in the <variable list> of the (never-set ..) form, then the program is incorrect. Whether the ensuing error message is attached to the set! or the never-set is not specified. Certain pre-defined identifiers are equivalent in this context to a particular list of variables. For example, the identifier r4rs is equivalent to a list of all variables in the index of the forth Revised Report. Note that (never-set (x)) (define x (string #\a #\b #\c)) is compatible with (string-set! x 1 #\w) but not with (set! x "awc") There is an obvious definition for (never-string-set ..), but no hope of doing it at compile time. Example: A file containing the following: (never-set r4rs (f)) (define (f a b) (+ (* b b) (* a a))) can be compiled to make f into instructions to the compiler to substitute arithmetic operations in-line, but it can never be loaded into a program that sets f, +, or *. (But who knows what that might be intended to mean?) On the other hand: (never-set r4rs (x y z)) (load "goofy") will give an error message if the goofy file contains (set! + string-append). ----------------------- Problem: Load a *.o file produced elsewhere. Proposal: A <filename>.c file that is to be compiled and loaded into Guile must contain a procedure called <filename>_init. This procedure must contain calls to gh_new_procedure and its ilk to define all Scheme accessable variables. The (load "<filename>") call must arrange that the prefix set up by surrounding (with-prefix ..) forms be made available to gh_new_procedure, which will add the prefix to each definition. It must then call <filename>_init in the <filename>.o file. -- --Keith This mail message sent by GNU emacs and Linux. Power to the people. Linux is here. Food, Shelter, Source code.