This is the mail archive of the guile@sourceware.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]

SRFI package for guile, rscheme, and maybe stalin (minor questions).



I'm nearly finished with a package that'll support a few of the srfi's
(for anyone who doesn't know what an srfi is, see www.schemers.org) in
rscheme, guile, and (maybe later) stalin.

Right now, I've got it so that you use the native facilities to load
the various srfis.  You use "(use-modules (srfi srfi-1))" for guile,
",(use srfi-1)" for rscheme, etc.  I've also got srfi-0 working and
use cond-expand within the other srfi's to handle the various
implementations.  Right now I only have a few of the srfi's working,
but I'll be expanding that.

However I have a couple of concerns that I needed a little help with.
They are all implementation questions regarding srfi-0 -- thinking
about them has forced me to explore some of the darker corners of my
understanding of the macro evaluation process.

In the (naive) reference implementation of srfi-0 cond-expand bottoms
out in either a feature-id it knows about, or one it doesn't like
this:

    ((cond-expand (srfi-0 body ...) more-clauses ...)
       (begin body ...))
    ((cond-expand (feature-id body ...) more-clauses ...)
       (cond-expand more-clauses ...))))

This implementation requires that all of the available features are
known and ready to go at the time this cond-expand macro is loaded,
but if you're going to allow people to selectively load various
features (like the srfis) then this assumption is false.

What you want need is a way to "augment" cond-expand whenever a new
feature is loaded.  For example, before a (use-modules (srfi srfi-0)),
(cond-expand (srfi-0 #t) (else #f)) should evaluate to #f, but after,
it should evaluate to #t (presuming of course that "srfi-0" is the
feature-id for srfi-0).

One way to make this work right (this isn't the greatest solution, so
keep reading) would be to rewrite the macro like this:

    ((cond-expand (srfi-0 body ...) more-clauses ...)
       (begin body ...))
    ((cond-expand (feature-id body ...) more-clauses ...)
     (if (srfi-0-known-feature? (quote feature-id))
       (begin body ...)
       (cond-expand more-clauses ...)))

This would rely on keeping a global (dynamic) list of the currently
available features within the srfi module (or a non-user hidden helper
module) and allow other modules to add tokens to that list.

This isn't the most elegant solution since it means (among other
things) that cond-expand would, in non-top-level cases, be executing
code at runtime, not macroexpansion time.  Consider

  (define (foo)
    (cond-expand
      (guile some-thing)
      (rscheme some-other-thing)
      (else default-thing)))

This would get expanded to something like

  (define (foo)
    (cond-expand
      (if (srfi-0-known-feature 'guile)
        (begin some-thing)
        (if (srfi-0-known-feature 'rscheme)
          (begin some-other-thing)
          (begin default-thing)))))

If you follow the letter of srfi-0, this isn't strictly speaking, a
problem since srfi-0 only guarantees that cond-expand will DTRT for
top-level forms, but I still don't like this solution.  Among other
problems it also requires polluting the global namespace with the
srfi-0-known-feature function.

An alternate solution would be to require that srfi-0 know about all
possible features, but it wouldn't have to know about whether or not
they're loaded:

    ((cond-expand (srfi-0 body ...) more-clauses ...)
       (begin body ...))
    ((cond-expand (srfi-1 body ...) more-clauses ...)
       (cond-expand-handle-srfi-1 body ...) more-clauses ...)

cond-expand-handle-<feature> would be a macro and the the default for
cond-expand-handle-<feature> would be to act as if the feature wasn't
present, but if, for example, srfi-1 was loaded via (use-modules (srfi
srfi-1)), then cond-expand-handle-srfi-1 would be redefined to act as
the (begin body ...) case.

This solution is much nicer than the first one, but it relies on two
things that I'm not totally sure about.  The first thing is the
ability to redefine a macro on the fly, and the second is the ability
for a module, say (srfi srfi-1), to redefine a macro inside a
different module, here (srfi srfi-0)

Can anyone tell me if this is possible, or if there's a better way to
handle this whole issue?

Thanks.

-- 
Rob Browning <rlb@cs.utexas.edu> PGP=E80E0D04F521A094 532B97F5D64E3930

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]