[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: logical operations in if-implements
Sorry for the long wait but only now am I catching up on the mail
concerning SRFI-0. Here goes:
Per Bothner <bothner@xxxxxxxxxx> noted the analogy between the
if-implements form and C's #ifdef and #if preprocessor directives, and
suggested that if-implements be generalized to permit either:
1) and, or and not combinations such as (if-implements (and SRFI-3 SRFI-5) A B)
2) a Scheme side-effect free expression as the if-implements predicate
which would be evaluated at macro expansion time (in a special
The first part of this proposal adds no power, just convenience for
the user. This convenience could also be provided by a macro (defined
in another SRFI?) which expands into if-implements forms. I don't
actually see much of a need for it (except for "not" but please supply
compelling examples to convince me otherwise) and I don't like
overloading "and", "or" and "not".
The second part of this proposal is too hairy for my taste. How do
you define precisely the sublanguage of Scheme which constitutes
"side-effect free" expressions? Can you use set! on local variables?
eq?? delay? call-with-current-continuation? exceptions? Before you
know it you have to be so restrictive that you are left with a
crippled, probably ill-defined, unappealing sublanguage that needs its
own interpreter. Also for this to work:
(if-implements (and SRFI-123 (= foo-version 200)) work-around)
this sublanguage must treat unbound variables (such as the SRFI-123)
specially so that they evaluate to #f. Yuck!
Let me repeat myself... it is important that the if-implements form
have a clear, unambiguous semantics. This will allow all of us to
build on top of it instead of around it. Also I think the
if-implements form should be easy to implement so that it doesn't add
much to the interpreter's or compiler's size (I'm thinking of an
interpreter/compiler which checks the syntax of the if-implements form
and reports appropriate error messages...).
Dave, Mike, and Shriram (The SRFI Editors) have come up with a counter
proposal which allows the program to request that a specific feature
be available and allows the program to test that a feature is
available (using COND-IMPLEMENTS a multiway if-implements). The feature
requested can affect the reader's syntax (IMPORT-READER-SYNTAX) and/or
the macro syntax and environment bindings (IMPORT-IMPLEMENTATION).
Three forms are proposed:
(COND-IMPLEMENTS (<feature-test> <body>)... (ELSE <body>))
where <feature-test> is a <feature-id> or a combination with "and",
"or", "not". COND-IMPLEMENTS is *not* analogous to COND because it
can choose any of the clauses for which a <feature-test> checks out.
I just don't see how this non-determinism can actually be helpful in
real programs. There is not even the guarantee that identical
COND-IMPLEMENTS expressions will take the same branch. Please provide
some convincing examples... Apart from this peculiarity the
COND-IMPLEMENTS form could be built on top of the if-implements form
as a macro.
An important question for the IMPORT-IMPLEMENTATION and
IMPORT-READER-SYNTAX forms is their "execution time" with respect to
the test performed by the COND-IMPLEMENTS form. Consider:
(COND-IMPLEMENTS (SRFI-123 foo))
For this to work, the interpreter/compiler must process the
IMPORT-IMPLEMENTATION form before the COND-IMPLEMENTS form. Because
IMPORT-IMPLEMENTATION can only appear at toplevel this apparently can
be done easily in a processing phase that is between "reading" and
"macro-expansion" which just checks toplevel forms. But what is
really meant by "toplevel"... which of these would be OK if found at
1) (begin (define x 1) (IMPORT-IMPLEMENTATION SRFI-100))
2) (include "foo.scm") ; if "foo.scm" contains (IMPORT-IMPLEMENTATION SRFI-100)
3) (my-import SRFI-100) ; if my-import is a macro that expands to an
; IMPORT-IMPLEMENTATION form.
4) (COND-IMPLEMENTS (SRFI-200 (IMPORT-IMPLEMENTATION SRFI-100)))
The problem is that all of these require that macro-expansion be done
*before* IMPORT-IMPLEMENTATION forms can be processed. So either
these uses of IMPORT-IMPLEMENTATION are disallowed (which I find to be
inelegant) or an iterative process, similar to one for finding
fixpoints, is used (which I find to be difficult to specify and
Moreover what happens if there are two *separately* compiled files and
one contains an (IMPORT-IMPLEMENTATION SRFI-100) and the other a
(COND-IMPLEMENTS (SRFI-100 foo))... Either
1) the "compiler" basically does nothing... it reads the source and
delays macro-expansion, code-generation, etc to link time (where a
"real" global compilation is done), the advantage here is that
the COND-IMPLEMENTS tests are globally consistent.
2) the COND-IMPLEMENTS tests are only consistent on a file by file
basis, which is not very elegant.
The IMPORT-READER-SYNTAX has similar binding-time problems, and
additionally some systems already treat the first datum of a file
specially. For example, for Gambit-C, if the first datum of a file is
the "script object" #! (as in: #! /usr/local/bin/gambit) then the file
is treated as a Scheme script (the first line is ignored and the
command line arguments visible to the script are computed specially
from the command line arguments).
The question I ask is why should all of this be in SRFI-0? Why not
leave it to some other SRFI, so that SRFI-0 can be lean and simple.
In particular, I see lots of overlap in functionality between
IMPORT-IMPLEMENTATION/IMPORT-READER-SYNTAX and a module system, so its
probably best to work on a general module system SRFI than on the
relatively crippled IMPORT-IMPLEMENTATION/IMPORT-READER-SYNTAX.