mailto:srfi-58@srfi.schemers.org
.
See instructions
here to subscribe to the list. You can access previous messages via the
archive of the mailing list.
prototype procedure | exactness | element type | prefix (rank = n) |
---|---|---|---|
vector | any | #nA
| |
ac64 | inexact | IEEE 64.bit floating point complex | #nAc64
|
ac32 | inexact | IEEE 32.bit floating point complex | #nAc32
|
ar64 | inexact | IEEE 64.bit floating point real | #nAr64
|
ar32 | inexact | IEEE 32.bit floating point real | #nAr32
|
as64 | exact | 64.bit integer | #nAs64
|
as32 | exact | 32.bit integer | #nAs32
|
as16 | exact | 16.bit integer | #nAs16
|
as8 | exact | 8.bit integer | #nAs8
|
au64 | exact | 64.bit nonnegative integer | #nAu64
|
au32 | exact | 32.bit nonnegative integer | #nAu32
|
au16 | exact | 16.bit nonnegative integer | #nAu16
|
au8 | exact | 8.bit nonnegative integer | #nAu8
|
string | char | #nA\
| |
at1 | bool | #nAt
|
1
" in the
"#1A
" prefix to be elided. That exception has been
removed.
Type names from Scheme foreign-function and foreign-data interfaces were suggested; but these names are confusing or even misleading to those unfamiliar with C or Java.
The Scheme reports are amply descriptive using their succinct vocabulary; so I rewrote this SRFI to use Scheme terminology.
The results in Table-1 are compact, mnemonic, and do not reach outside of the Scheme language, except for Z for the integers.
#*
" followed by a sequence of ones and zeros;
"1
" for "#t
", "0
" for
"#f
". Common-Lisp's bit-array accessor functions
return "1
" and "0
"; but SRFI-47's
"array-ref
" returns "#t
" or "#f
".
I don't think that difference invalidates this notation for
Scheme, but others may.
#nA
" followed by the list-decomposition of
the array, is the same as the Common-Lisp read-syntax for arrays.
SRFI-47, "Array", incorporates all the uniform vector types from SFRI-4 "Homogeneous numeric vector datatypes", and adds a boolean array type, shorter and longer floating-point numbers, decimal floating-point reals, and array types of complex numbers composed of two floating-point numbers. Multi-dimensional arrays subsume homogeneous vectors as the one-dimensional case, obviating the need for SRFI-4.
Implementations are required to accept all of the type denotations.
Uniform types of matching sizes which the platform supports will be
used; the others will be represented as the next larger format of the
same type implemented. If there is no larger format of the same type
and there is a bignum format for that element type, then the array
format defaults to vector
; otherwise the largest uniform
format of that type is used. This arrangement has platforms
supporting uniform array types using them, with less capable platforms
using vectors; both from the same source code.
The rank and dimension of the literal array can be specified several ways.
#
and A
;
*
after
A
; or
*
after
#
.
Both rank and dimensions can be supplied on opposite sides of
A
.
Aliases for the array-prototype-procedures of SRFI-47 are defined
whose identifiers are the #nA:typename
prefix sans the #n
. Having the
array-prototype-procedure names match the array prefixes reduces the
memory load for users.
By list-decomposition is meant rank nestings of lists of the elements where the most nested list has length equal to the last dimension of the array and at top level has length equal to the first dimension of the array. Vectors may substitute for lists at any nesting depth.
Rank 0 arrays have one element; that element appears after the prefix (perhaps with intervening whitespace) with no additional parenthesis.
Rank 1 heterogeneous arrays which are not subarrays
write
and display
as Scheme vectors.
The prefix syntax is:
array-prefix :: rank `A' [ dimensions ] [ `:' type-specifier ] | [ `A' ] dimensions [ `:' type-specifier ] dimensions :: dimension | dimensions `*' dimension dimension :: nonnegative-integer rank :: positive-integer type-specifier :: `flo' { `c' | `r' } flowidth `b' | `fix' { `z' | `n' } fixwidth `b' | `flo' `r' decwidth `d' flowidth :: `16' | `32' | `64' | `128' fixwidth :: `8' | `16' | `32' | `64' decwidth :: `32' | `64' | `128'
prototype procedure | exactness | element type | type specifier |
---|---|---|---|
vector | any |
| |
A:floc128b | inexact | 128.bit binary flonum complex | floc128b
|
A:floc64b | inexact | 64.bit binary flonum complex | floc64b
|
A:floc32b | inexact | 32.bit binary flonum complex | floc32b
|
A:floc16b | inexact | 16.bit binary flonum complex | floc16b
|
A:flor128b | inexact | 128.bit binary flonum real | flor128b
|
A:flor64b | inexact | 64.bit binary flonum real | flor64b
|
A:flor32b | inexact | 32.bit binary flonum real | flor32b
|
A:flor16b | inexact | 16.bit binary flonum real | flor16b
|
A:flor128d | exact | 128.bit decimal flonum real | flor128d
|
A:flor64d | exact | 64.bit decimal flonum real | flor64d
|
A:flor32d | exact | 32.bit decimal flonum real | flor32d
|
A:fixz64 | exact | 64.bit binary fixnum | fixz64b
|
A:fixz32 | exact | 32.bit binary fixnum | fixz32b
|
A:fixz16 | exact | 16.bit binary fixnum | fixz16b
|
A:fixz8 | exact | 8.bit binary fixnum | fixz8b
|
A:fixn64 | exact | 64.bit nonnegative binary fixnum | fixn64b
|
A:fixn32 | exact | 32.bit nonnegative binary fixnum | fixn32b
|
A:fixn16 | exact | 16.bit nonnegative binary fixnum | fixn16b
|
A:fixn8 | exact | 8.bit nonnegative binary fixnum | fixn8b
|
A:bool | boolean | bool
|
A two-by-three array of nonnegative 16.bit integers can be written several ways:
#2A:fixn16b((0 1 2) (3 5 4)) #2A2*3:fixn16b((0 1 2) (3 5 4)) #A2*3:fixn16b((0 1 2) (3 5 4)) #2*3:fixn16b((0 1 2) (3 5 4))
Note that these are external representations of an array, not expressions evaluating to arrays. Like vector constants, array constants must be quoted:
'#2a:FIXN16b((0 1 2) (3 5 4)) ==> #2A:fixn16b((0 1 2) (3 5 4))
Rank 0 arrays:
#0a sym #0A:flor32b 237.0
(array-dimensions '#2A:fixn16b((0 1 2) (3 5 4))) ==> (2 3)
An equivalent array could have been created by
(define ra (make-array (A:fixn16b) 2 3)) (array-set! ra 0 0 0) (array-set! ra 1 0 1) (array-set! ra 2 0 2) (array-set! ra 3 1 0) (array-set! ra 5 1 1) (array-set! ra 4 1 2) ra ==> #2A2*3:fixn32b((0 1 2) (3 5 4))
In this example, the uniform type returned is wider than requested due to implementation restrictions.
Literal array constants are immutable objects. It is an error to attempt to store a new value into a location that is denoted by an immutable object.
The following equivalences will be defined to alias SRFI-47 names to the new ones. SRFI-47 should be replaced to make these be the array-prototype-procedures:
(define A:floc128b ac64) (define A:floc64b ac64) (define A:floc32b ac32) (define A:floc16b ac32) (define A:flor128b ar64) (define A:flor64b ar64) (define A:flor32b ar32) (define A:flor16b ar32) (define A:flor128d ac64) (define A:flor64d ac64) (define A:flor32d ac32) (define A:fixz64b as64) (define A:fixz32b as32) (define A:fixz16b as16) (define A:fixz8b as8) (define A:fixn64b au64) (define A:fixn32b au32) (define A:fixn16b au16) (define A:fixn8b au8) (define A:bool at1)
read:sharp
is called from read
when a
#\#
is read. Its first argument is the character after
#\#
; the second argument is the input port; the third
argument is the procedure to call for recursive reading.
list->uniform-array
converts the list-decomposition
returned by read
into the uniform array of the specified
type (or the next larger compatible type).
;;; Read integer up to first non-digit (define (read:try-number port . ic) (define chr0 (char->integer #\0)) (let loop ((arg (and (not (null? ic)) (- (char->integer (car ic)) chr0)))) (let ((c (peek-char port))) (cond ((eof-object? c) #f) ((char-numeric? c) (loop (+ (* 10 (or arg 0)) (- (char->integer (read-char port)) chr0)))) (else arg))))) (define (read-array-type port) (define (bomb pc wid) (error 'array 'syntax? (symbol-append "#" rank "A" pc wid))) (case (char-downcase (peek-char port)) ((#\:) (read-char port) (let ((typ (let loop ((arg '())) (if (= 4 (length arg)) (string->symbol (list->string (reverse arg))) (let ((c (read-char port))) (and (not (eof-object? c)) (loop (cons (char-downcase c) arg)))))))) (define wid (and typ (not (eq? 'bool typ)) (read:try-number port))) (define (check-suffix chrs) (define chr (read-char port)) (if (and (char? chr) (not (memv (char-downcase chr) chrs))) (error 'array-type? (symbol-append ":" typ wid chr)))) (define prot (assq typ '((floc (128 . +64.0i) (64 . +64.0i) (32 . +32.0i) (16 . +32.0i)) (flor (128 . 64.0) (64 . 64.0) (32 . 32.0) (16 . 32.0)) (fixz (64 . -64) (32 . -32) (16 . -16) (8 . -8)) (fixn (64 . 64) (32 . 32) (16 . 16) (8 . 8)) (bool . #t)))) (if prot (set! prot (cdr prot))) (cond ((pair? prot) (set! prot (assv wid (cdr prot))) (if (pair? prot) (set! prot (cdr prot))) (if wid (check-suffix (if (and (inexact? prot) (real? prot)) '(#\b #\d) '(#\b))))) (prot) (else (check-suffix '()))) prot)) (else #f))) ;;; We come into read:array with number or #f for RANK. (define (read:array rank dims port reader) ;ignore reader (let loop ((dims dims)) (define dim (read:try-number port)) (if dim (loop (cons dim dims)) (case (peek-char port) ((#\*) (read-char port) (loop dims)) ((#\:) (let ((typ (read-array-type port))) (list->uniform-array (or rank (length dims)) typ (read port)))) (else (list->uniform-array (or rank (length dims)) #f (read port))))))) (define (read:sharp c port read) (case c ((#\a #\A) (read:array #f '() port read)) ((#\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9) (let* ((num (read:try-number port c)) (chr (peek-char port))) (case chr ((#\a #\A) (read-char port) (read:array num '() port read)) ((#\*) (read-char port) (read:array #f (list num) port read)) (else (read:array 1 (list num) port read))))) (else (error "unknown # object" c))))
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.