Re: when GC is permitted Marc Feeley 15 Jan 2004 02:45 UTC

> >>>>> "Marc" == Marc Feeley <xxxxxx@IRO.UMontreal.CA> writes:
> Marc> But cond-expand is a portable 35 line R5RS macro.  How can you say it
> Marc> is difficult to implement in any reasonable Scheme system?  I know
> Marc> that you don't want to implement it in Scheme 48 because you disagree
> Marc> with the philosophy behind it, and I respect that, but that is very
> Marc> different from saying that it is technically difficult.
> You misunderstand.  While it probably is also a matter of philosophy,
> it's first and foremost a technical issue.  Indeed, implementing
> SRFI 0 in Scheme 48 would be technically trivial, but the result would
> be useless: in Scheme 48, lots of features exist, but none are
> available in the sense of SRFI 0.  Essentially the same holds for PLT
> Scheme.

I got a similar reply from Richard Kelsey, and I feel I must answer
because I just simply don't understand what the problem is.  I'm CCing
to the SRFI-0 mailing list since this should be archived there.

SRFI-0 does not assume that all available SRFIs (i.e. "features") are
built-in.  It says so explicitly in the SRFI document.  "cond-expand"
simply tests for the presence of a feature.  An implementation of
Scheme may choose to make all available SRFIs built-in, or to have
another mechanism (such as a module system) to do this.  In fact an
implementation of Scheme may have some features that must be requested
through the module system and some others built-in (either because the
system implements extensions to Scheme, like a thread system, that are
available all the time, or because a particular feature can only be
built-in, such as the char->integer/integer->char procedures obeying
the Unicode encoding and allowing Unicode characters in Scheme

To implement the interaction between the module system and
"cond-expand", the module system could maintain a "feature"
environment or extend the cond-expand macro for the body of the
module.  So if the module does (require foo) and (require bar), then
both "foo" and "bar" are recognized by cond-expand as available
features for the body of the module (this is just to give the
idea... it might be better to have the foo and bar modules explicitly
indicate which features they provide, with a (provide foo) form, and
only these features would be added to the available features for the
body of the module).

The need for "cond-expand" does not disappear when a module system is
available.  Here is an example.  Suppose I write a web-server in
Scheme using threads.  The web-server needs basic thread primitives
like those in SRFI-18 (Multithreading support).  However, real-time
response of the web-server can be improved by using the
"thread-priority-boost-set!" procedure that is only available in
SRFI-21 (Real-time multithreading support).  This is the only feature
of SRFI-21 that is useful; all other thread operations are from
SRFI-18 (note that SRFI-21 is a strict superset of SRFI-18).  Moreover
assume that these thread SRFIs are not built-in.  So the source-code
of the web-server will look something like this:

(module web-server

  (require (or srfi-21 srfi-18))

  (cond-expand (srfi-18
                (define (thread-priority-boost-set! thread boost) #f)) ; noop
                ; thread-priority-boost-set! exists in srfi-21


  (define (respond-to request)
    (let ((t (make-thread (lambda () (process request)))))
      (thread-priority-boost-set! t 10)
      (thread-start! t)))


The "require" form used here is hypothetical.  I use the "or" to indicate
that the system tries to locate the modules in order and the first that
is found prevents the search for the other modules.  The nice thing with
the module expressed with a "cond-expand" is that it adapts to the
features that are available.  The author of the web-server has designed
the module so that it can work in either context.

Unfortunately, the Scheme module systems I have seen don't support
this form of "require".  The "require" form usually means that this
and only this module will do.  So in such systems the web-server would
probably be written like this:

(module web-server

  (require srfi-21) ;;; if you do not have srfi-21 available it is OK
                    ;;; to replace this line with (require srfi-18)

  (cond-expand (srfi-18 ...))


Here the author has left a comment that allows the user of the
web-server to make a simple change to the code if srfi-21 is not
available (this is not great, but it is better than having to read,
understand, and modify the source code so that it does not use
thread-priority-boost-set!, and so can be used with srfi-18).  It is
also better (in my view) than creating two web-server modules (one for
srfi-21 and one for srfi-18) that only differ in a few places, or that
use "include" forms to factor the common parts.