SRFI-47 -- types and declarations. bear 12 Nov 2003 02:19 UTC

SRFI-47:  Array

I have one minor issue (syntax) and one major issue (design).

The syntax issue is, can you clarify why you chose the argument
order you did?  I seem to recall existing work that this is
gratuitously incompatible with, as another poster has already
pointed out.

The design issue, though, is that I'm not entirely sure that
the prototype idea is a clean one.

The issue of types and representation types hasn't been well
addressed in scheme yet.  This SRFI is building on a presumed
infrastructure of type names and ranges that hasn't yet been
discussed, and I think that it's dubious in its extensibility
and generality.

To start with, we're beginning to talk about representation
types as distinct from values.  I'm going to make a case below
that representation types should be separated from values and
functions in a clean way using optional declarations rather than
multiplying arbitrarily the number of functions and names in
the language.

Rather than introducing some kind of explicitly typed array, I
think we should have multidimensional arrays (a la SRFI-25)
enhanced with optional type declarations that allow compilers
aware of them to produce optimized code -- but still have
arrays be conceptually untyped.

This means that someone can write the code and get it working,
using untyped arrays -- and go back and add declarations, in
an orthogonal way later, to increase its performance once the
semantics are debugged.

I think that declarations are a powerful idea, and should have
their own syntax, not folded into the specification of vectors,
arrays, and strings as such but capable of existing as an
enclosing form with a lexical scope.

So, rather than many different functions like ac64, I propose
that it would be better to simply have arrays, and if/when
performance is an issue, we can promise the compiler that
we'll never store anything except numbers representable as
ac64's in them by saying

(declare (
   (foo (array-of ac64))
   (bar (array-of ac64)))

   (define foo (make-array ...))
   (define bar (make-array ...))


instead of

(define foo (make-array ...))
(define bar (make-array ...))

This means that special forms for types don't get in user's
faces until they're useful to users solving performance problems,
which drastically reduces the cognitive load of learning the
language and simplifies the job of teaching it.

It also means that performance tweaks can be applied, easily, to
code that's been already written without messing up its semantics;
you're simply promising the compiler that something will always
be the case; if your promise is true it harms nothing.

It leaves implementors free to use the information to optimize,
but requires them to do nothing other than provide a syntax-rules
one-liner to ignore the declaration form if they don't.

It provides a way to detect implementation problems; you can simply
turn the declarations off and see if the problem recurs, or a
debugging implementation could create debug builds that halt with
appropriate errors the instant the promises made to the compiler are

And it makes heavily-optimized code portable, with semantics intact,
across all implementations even if the optimizations themselves aren't
portable across all implementations.