On Tue, 2009-09-22 at 11:23 -0400, John Cowan wrote:
> R6RS (and I presume large Scheme) mandates the whole tower.  Should small
> Scheme?  I don't know.  My thoughts, which don't amount to a proposal
> yet, are that fixnum-only Schemes are just toys, and that the following
> types are reasonable alternatives for a small Scheme:

I think that the absolute minimum requirement for numerics 
should probably be limited-precision integers, because in 
terms of limited precision integers, you can implement the 
semantics (though not the syntax) of all the other numbers 
as portable libraries.  

The syntax of numbers, however, cannot be implemented in a 
library and imported.  Identifier-syntax is far too weak 
to be adequate.  (indeed, it was a big stroke against R6
IMO; why bother with it at all if it's too weak to do 
what you need it for??)

People have talked here about providing a means of creating 
new disjoint types.  I've been thinking about that, and here 
are my thoughts. 

A data type has several important features.  Abstractly, 
we think about the operations we want defined on data of 
that type, and those are the first important feature.  

More concretely, we think about the representation of 
that type.  For example, a cons pair whose car and cdr 
are both real numbers contains all the information we 
need to represent a complex number (in rectangular or 
polar coordinates).  

Next, we want a "wrapper" allowing us to make the new 
type distinct from extant types.  (Note, "distinct" is 
not the same as "disjoint."  For example, the new type 
of complex numbers should be distinct from pairs and 
other numbers (PAIR? and INTEGER? should return #f), 
but still answer #t when queried with the NUMBER? 
predicate.

That necessitates a corresponding "unwrapper" which allows 
us to get at the original representation (ie, get the cons 
cell back, or create a cons cell that points at the same
two values as the original cons cell). We need this in 
order to implement our basic operations such as addition,
subtraction, multiplication, etc. 

Finally, if the new type is supposed to have a read-write 
syntax, we need to define read/write hooks: routines that 
read the syntax and construct the values, and routines 
that take the values and write the syntax.  When the READ 
and WRITE routines encounter something they don't "normally" 
understand, they need to call all of these hooks that have 
been defined.  If exactly one of them is successful, READ 
or WRITE can continue.  If none, or more than one, is 
successful, it's an error. 

So at some level, our type constructor needs these arguments: 

Type (a name to be uniquely associated with a typetag or predicate)
Constructor (a routine that takes some lisp datastructure 
             (pair, vector, list, whatever) that uniquely
             specifies a value of the new type, and returns 
             the specified "wrapped" value)

Unwrapper (a routine that takes a value of the type and 
           returns the corresponding "unwrapped" data 
           structure so you can implement primitive operations)

Read Hook (a routine that takes an unrecognized lexical 
           token or lexical delimited expression and either 
           returns an object of the new type, or detects and 
           signals that it was the wrong read hook for that 
           token.  This routine will be called automatically
           by READ.)

Write Hook (a routine that takes an object of the new type and 
           returns a string acceptable to the corresponding 
           read hook.  This routine will be called automatically
           by WRITE.)

And can use an optional argument:

Display Hook (renders the datum in human-readable form.  If 
           not supplied, the write hook should be used instead.)

This doesn't address the management of preexisting predicates that 
should be replaced by versions that return #t for objects of the new
type (such as NUMBER? if you're implementing complex numbers).
Presumably, in the default case, the new type is assumed to be 
disjoint from extant types.

This also doesn't address preexisting operators that need to 
acquire new semantics for dealing with the new data type, such as 
+ - / * (and quite a few more) in the case of complex numbers, 
nor how to register routines that do automatic type coercion 
(eg, of integers to complex numbers, or pairs to vectors, or 
whatever) in order to facilitate the use of such "generic functions"
without a combinatorial explosion of implementation bodies.

But by the time the things in the above two paragraphs *are* 
fully addressed, you have CLOS or its moral equivalent, and I 
think we're officially out of scope for WG1. 

                                Bear



_______________________________________________
r6rs-discuss mailing list
[email protected]
http://lists.r6rs.org/cgi-bin/mailman/listinfo/r6rs-discuss

Reply via email to