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

Re: SRFI 0 philosophy



Marc writes:
> So I send a plea to everyone: if you have a view on this subject now
> is the time to voice it.

A summary of my view:

  * Neither the original or alternate SRFI 0 proposal addresses the
    real problem.

  * The real problem is modularity. 

  * Although it sounds hard, maybe we can solve the modularity problem
    --- in the restricted context of SRFIs -- by pursuing a simple,
    external configuration language (similar to Kelsey's refinement of
    the alternate proposal).

To elaborate, I'll start at the beginning...


What are SRFIs for? I see two reasonable answers (both within the scope
of the existing documents that try to answer this question):

 1. To allow an individual programmer to produce code that executes in
    many different Scheme implementations.

 2. To allow many programmers (using many Scheme implementations) to
    share code that relies on more than the minimal language specified
    in RnRS.

There's a significant difference in focus between these two goals. The
first might be a useful goal, but I think that the second is a far more
important one (and one that SRFIs can achieve).


What is SRFI 0 for? If SRFI 0 is meant as a foundation for using SRFIs,
I see two answers, in parallel to the above:

 1. To define a how programmer writes source code that can adapt to
    different programming languages (i.e., languages with different
    built-in features).

 2. To define how a programmer writes source code in a well-specified
    language (bigger than RnRS) so that other programmers can use the
    code.

The original SRFI 0 addresses #1. The alternate SRFI 0 proposal (and
Kelsey's extralinguistic refinement) comes closer to addressing #2.
But, as Donovan has pointed out, even the alternate proposal provides
no mechanism that allows parts of a program to use different SRFIs. If
reuse is the ultimate goal, we must address the fact that code from
multiple programmers will likely depend on different, possibly
conflicting, SRFIs.

This line of reasoning brings us to modules, of course.


Mike writes:
> - Module system: 
>   Unfortunately, a general module system is far away.

Are we sure? I'd like to test this hypothesis. 

Perhaps it's just a question of how general is "general". I wonder
whether we can pin down a configuration language (outside of Scheme)
that will enable modular SRFIs and sharable code. If we can, then I
believe that we should push a module foundation in SRFI 0, rather than
an #if-like construct. At the very least, I'd like to explore the
possibility.

Below is a sketch for a simple configation language. It closely
resembles Ada or Modula-3. It is less than the module language I want
to program with, but it is enough to write useful programs and to
support modular SRFIs. It is easy mapped to existing module languages
in various Scheme implementations (I think).


-----------------------------------------------------------------------

The configuration language provides three first-order constructs:

 * Interfaces - An interface is a set of variable names (and an
   implied contract for the variables' use).

    <interface-decl> = (define-interface <i-name> (<identifier> ...))

 * Modules - A module is a set of definitions and expressions, closed
   with respect to some basis language (e.g. R4RS or R4RS + SRFI-3) and
   a set of imported variables (imported from specific other modules).
   Some of the defined variables are exported.

   A module exports and imports run-time variables, not values or
   macros.

   The body of a module is in a separate file, to avoid messy reader
   issues, such as case-sensitivity.

     <module-decl> = (define-module <m-name> <module-body>)

     <module-body> = (body <file>)
                      (syntax <language> ...)
                      (export <i-name> ...)
                      (import <m-name> ...)

     <language> = r4rs | r5rs | srfi-<n> | ...

 * Generic modules - A generic module is a module that is parameterized
   over (some of) the modules that provide its imports. Combining a
   generic module with specific imported modules defines a new module.

    <gen-decl> = (define-generic (<g-name> <m-name> ...) <module-body>)
               | (define-module (<g-name> <m-name> ...))

A program is a sequence of <config-decl>s

    <program> = <config-decl> ...

where a <config-decl> is an interface, module, or generic module
declaration, or an include declaration for textually substituting a
file:

    <config-decl> = <interface-decl>
                  | <module-decl>
                  | <gen-decl>
                  | (include <file>)

A program must define a set of modules that are closed over the import
relation. Running the program evaluates each definition and expression
of the program's modules, sequentially within each module and
sequentially across modules in the order of the module declarations.

-----------------------------------------------------------------------


I've omitted some details above (because it's just a sketch), but
certain aspects of the sketch are important:

  * Support for components - Linking among modules is hardwired into
    each module, which makes modules good for expressing an individual
    program, but unsuitable as units for sharing code. Generic modules
    are units for sharing code (and they are intended as compilation
    units).

  * First-order and extralinguistic configuration - If necessary, a
    particular configuration can be implemented by renaming variables
    within modules, then concatenating all modules expressions to form
    a sequence of top-level expressions (although this strategy
    prohibits separate compilation of generics).

Certain aspects are unimportant:

  * Terminology - I chose "module", "interface", and "generic" because
    they seem to be the most commonly used terms.

  * Keywords and placement of parentheses (obviously).

Certain issues are not addressed:

  * <file> specification - The language should define <file> so that a
    configuration can refer to standard library files (such as a
    component implementing SRFI 1) as well as files relative to the
    configuraiton file.

  * How to get SRFI N (perhaps based on SRFI M) into implementation X -
    I don't beleive that this is the interesting problem for SRFI 0.

  * Hierarchical components - I'd like to have hierarchical components,
    but I couldn't make them simple enough to fit into the sketch, so
    they're probably too complicated to be worthwhile for now.



With the above sketch, I'm hoping to learn how "far away" we are from a
SRFI-friendly module system. More concretely, I ask the following
question of each of you: how far is the above sketch from an acceptable
module system?


Matthew