read
and write
procedures and by the program
parser (i.e. programs can contain references to literal homogeneous
vectors).
datatype | type of elements | |
s8vector | signed exact integer in the range -(2^7) to (2^7)-1 | |
u8vector | unsigned exact integer in the range 0 to (2^8)-1 | |
s16vector | signed exact integer in the range -(2^15) to (2^15)-1 | |
u16vector | unsigned exact integer in the range 0 to (2^16)-1 | |
s32vector | signed exact integer in the range -(2^31) to (2^31)-1 | |
u32vector | unsigned exact integer in the range 0 to (2^32)-1 | |
s64vector | signed exact integer in the range -(2^63) to (2^63)-1 | |
u64vector | unsigned exact integer in the range 0 to (2^64)-1 |
datatype | type of elements | |
f32vector | inexact real | |
f64vector | inexact real |
f64vector
s preserve at least as much precision as
f32vector
s (see the implementation section for details).
A Scheme system that conforms to this SRFI does not have to support
all of these homogeneous vector datatypes. However, a Scheme system
must support f32vector
s and f64vector
s if it
supports Scheme inexact reals (of any precision). A Scheme system
must support a particular integer vector datatype if the system's
exact integer datatype contains all the values that can be stored in
such an integer vector. Thus a Scheme system with bignum support must
implement all the integer vector datatypes and a Scheme system may
only support s8vector
s, u8vector
s,
s16vector
s and u16vector
s if it only
supports small integers in the range -(2^29) to (2^29)-1 (which would
be the case if they are represented as 32 bit fixnums with two bits
for tag). Note that it is possible to test which numeric datatypes
the Scheme system supports by calling the
string->number
procedure (e.g.
(string->number "0.0")
returns #f
if the
Scheme system does not support inexact reals).
Each homogeneous vector datatype has an external representation which
is supported by the read
and write
procedures and by the program parser. Each datatype also has a set of
associated predefined procedures analogous to those available for
Scheme's heterogeneous vectors.
For each value of TAG
in {
s8
, u8
,
s16
, u16
,
s32
, u32
,
s64
, u64
,
f32
, f64
}, if the datatype TAGvector
is supported, then
TAGvector
is #TAG(
...elements... )
.
For example, #u8(0 #e1e2 #xff)
is an
u8vector
of length 3 containing 0, 100 and 255;
#f64(-1.5)
is an f64vector
of length 1
containing -1.5.
Note that the syntax for float vectors conflicts with Standard Scheme
which parses #f32()
as 3 objects: #f
,
32
and ()
. For this reason, conformance to
this SRFI implies this minor nonconformance to Standard Scheme.
This external representation is also available in program source code.
For example, (set! x '#u8(1 2 3))
will set x
to the object #u8(1 2 3)
. Literal homogeneous vectors
must be quoted just like heterogeneous vectors must be. Homogeneous
vectors can appear in quasiquotations but must not contain
unquote
or unquote-splicing
forms
(i.e. `(,x #u8(1 2))
is legal but `#u8(1 ,x
2)
is not). This restriction is to accomodate the many Scheme
systems that use the read
procedure to parse programs.
(TAGvector? obj)
(make-TAGvector n [ TAGvalue ])
(TAGvector TAGvalue...)
(TAGvector-length TAGvect)
(TAGvector-ref TAGvect i)
(TAGvector-set! TAGvect i TAGvalue)
(TAGvector->list TAGvect)
(list->TAGvector TAGlist)
obj
is any Scheme object, n
is a
nonnegative exact integer, i
is a nonnegative exact
integer less than the length of the vector, TAGvect
is an
instance of the TAGvector
datatype, TAGvalue
is a number of the type acceptable for elements of the
TAGvector
datatype, and TAGlist
is a proper
list of numbers of the type acceptable for elements of the
TAGvector
datatype.
It is an error if TAGvalue
is not the same type as the
elements of the TAGvector
datatype (for example if an
exact integer is passed to f64vector
). If the fill
value is not specified, the content of the vector is unspecified
but individual elements of the vector are guaranteed to be in the
range of values permitted for that type of vector.
f32vector
and
f64vector
datatypes could be represented the same way
with 64 bit floating point numbers).
A portable implementation of the homogeneous vector predefined
procedures can be based on Scheme's heterogeneous vectors.
Here is for example an implementation of s8vector
s
which is exempt of error checking:
(define s8vector? #f) (define make-s8vector #f) (define s8vector #f) (define s8vector-length #f) (define s8vector-ref #f) (define s8vector-set! #f) (define s8vector->list #f) (define list->s8vector #f) (let ((orig-vector? vector?) (orig-make-vector make-vector) (orig-vector vector) (orig-vector-length vector-length) (orig-vector-ref vector-ref) (orig-vector-set! vector-set!) (orig-vector->list vector->list) (orig-list->vector list->vector) (orig-> >) (orig-eq? eq?) (orig-+ +) (orig-null? null?) (orig-cons cons) (orig-car car) (orig-cdr cdr) (orig-not not) (tag (list 's8))) (set! s8vector? (lambda (obj) (and (orig-vector? obj) (orig-> (orig-vector-length obj) 0) (orig-eq? (orig-vector-ref obj 0) tag)))) (set! make-s8vector (lambda (n . opt-fill) (let ((v (orig-make-vector (orig-+ n 1) (if (orig-null? opt-fill) 123 (orig-car opt-fill))))) (orig-vector-set! v 0 tag) v))) (set! s8vector (lambda s8list (orig-list->vector (orig-cons tag s8list)))) (set! s8vector-length (lambda (s8vect) (orig-+ (orig-vector-length s8vect) -1))) (set! s8vector-ref (lambda (s8vect i) (orig-vector-ref s8vect (orig-+ i 1)))) (set! s8vector-set! (lambda (s8vect i s8value) (orig-vector-set! s8vect (orig-+ i 1) s8value))) (set! s8vector->list (lambda (s8vect) (orig-cdr (orig-vector->list s8vect)))) (set! list->s8vector (lambda (s8list) (orig-list->vector (orig-cons tag s8list)))) (set! vector? (lambda (obj) (and (orig-vector? obj) (orig-not (and (orig-> (orig-vector-length obj) 0) (orig-eq? (orig-vector-ref obj 0) tag)))))))The Scheme system's
read
and write
procedures and the program parser also need to be extended to handle
the homogeneous vector external representations. The implementation
is very similar to heterogeneous vectors except that read
and the program parser must recognize the prefixes #s8
,
#f32
, etc. (this can be done by checking if the sharp
sign is followed by a character that can start a symbol, and if this
is the case, parse a symbol and check if it is t
,
f
, s8
, f32
, and so on, and in
the case of a homogeneous vector prefix, check if the next character
is an opening parenthesis).
This document and translations of it may be copied and furnished to others, and derivative works that comment on or otherwise explain it or assist in its implementation may be prepared, copied, published and distributed, in whole or in part, without restriction of any kind, provided that the above copyright notice and this paragraph are included on all such copies and derivative works. However, this document itself may not be modified in any way, such as by removing the copyright notice or references to the Scheme Request For Implementation process or editors, except as needed for the purpose of developing SRFIs in which case the procedures for copyrights defined in the SRFI process must be followed, or as required to translate it into languages other than English.
The limited permissions granted above are perpetual and will not be revoked by the authors or their successors or assigns.
This document and the information contained herein is provided on an "AS IS" basis and THE AUTHOR AND THE SRFI EDITORS DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.