read
と write
手続き、および、プログラム パーサでサポートしなければならない外部表現についても規定する
(すなわち、プログラム中に一様ベクタのリテラル表現を記述することができる)。
リストと同様に、Scheme のベクタは異種混合が可能であり、要素のデータ型に制限を加えることはない。 しかし、すべての要素が同じデータ型をもつアプリケーションでは、この汎用性は不要なものである。 このようなアプリケーションにとっては Scheme のベクタは理想的ではない。 気の利いた静的解析を行うコンパイラがない場合、ベクタは要素を何らかの方法でまとめて管理するが、 その方法はメモリ効率が悪く、要素へのアクセス速度も遅いものになる。 さらに、一様ベクタは低レベル ライブラリ (たとえば、バイナリ ブロック入出力) と連携する場合や、 一様ベクタをサポートする外部言語と相互運用する場合に便利である。 また、一様ベクタを使用することにより、ある種のエラーを早い段階で検出することが可能になる。
この SRFI では、いくつかの一様ベクタ データ型を定義する。要素が数値型 (正確整数 (exact integer) または不正確実数 (inexact real)) で、その精度と表現が現在のほとんどのコンピュータ アーキテクチャのハードウェアで効率よく実装できるような、 最も実用的なケースをカバーする (符号付きおよび符号なしの 8、16、32、64 ビット整数、32 ビットおよび 64 ビットの浮動小数点数)。
データ型 | 要素の型 | |
s8vector | 符号付き正確整数。値の範囲は -(2^7) ~ (2^7)-1 | |
u8vector | 符号なし正確整数。値の範囲は 0 ~ (2^8)-1 | |
s16vector | 符号付き正確整数。値の範囲は -(2^15) ~ (2^15)-1 | |
u16vector | 符号なし正確整数。値の範囲は 0 ~ (2^16)-1 | |
s32vector | 符号付き正確整数。値の範囲は -(2^31) ~ (2^31)-1 | |
u32vector | 符号なし正確整数。値の範囲は 0 ~ (2^32)-1 | |
s64vector | 符号付き正確整数。値の範囲は -(2^63) ~ (2^63)-1 | |
u64vector | 符号なし正確整数。値の範囲は 0 ~ (2^64)-1 |
データ型 | 要素の型 | |
f32vector | 不正確実数 | |
f64vector | 不正確実数 |
f64vector
が少なくとも f32vector
の精度と同じだけの精度を保証するという点だけである (詳細については「実装」のセクションを参照せよ)。
この SRFI に準拠する Scheme システムは、上記すべての一様ベクタ型をサポートする必要はない。
しかし、Scheme システムが Scheme の不正確実数をサポートしているのであれば (その精度については問わない)、f32vector
と f64vector
をサポートしなければならない。
また、Scheme システムの正確整数型が、特定の整数ベクタの要素の値を保持できるほど大きいのであれば、その整数ベクタをサポートしなければならない。
したがって、多倍長整数 (bignum) をサポートする Scheme システムはすべての整数ベクタ型を実装しなければならず、値の範囲が -(2^29) ~ (2^29)-1 の小さな整数のみをサポートするシステムでは s8vector
、u8vector
、s16vector
、u16vector
だけを実装すればよい (このようなケースは、整数を 32 ビット固定長で扱い、そのうちの 2 ビットをタグ用に使用するシステムで有り得ることである) 。
Scheme システムがどの数値型をサポートするかを検査するには、string->number
手続きを使用することができる (たとえば (string->number "0.0")
は、不正確実数をサポートしていなければ #f
を返す) 。
各一様ベクタ型は、read
と write
手続きおよびプログラム パーサでサポートされる外部表現をもつ。
また各一様ベクタ型は、Scheme の非一様ベクタで利用可能な手続きと同様の定義済み手続きを利用できる。
TAG
を {
s8
, u8
,
s16
, u16
,
s32
, u32
,
s64
, u64
,
f32
, f64
} のいずれかとする。データ型 TAGvector
がサポートされている場合:
TAGvector
のインスタンスの外部表現は #TAG(
...elements... )
とする。
たとえば、#u8(0 #e1e2 #xff)
は長さ 3 の u8vector
で、0、100、255 を含む。
#f64(-1.5)
は長さ 1 の f64vector
で、-1.5 を含む。
標準 Scheme では #f32()
を #f
、32
、()
の 3 つのオブジェクトとして解釈するので、浮動ベクタの構文は、標準 Scheme と競合することになる。
この理由から、この SRFI に準拠することは標準 Scheme に少し違反することになる。
この外部表現はプログラムのソース コードに記述することもできる。たとえば、(set! x '#u8(1 2 3))
と記述すると、x
にオブジェクト #u8(1 2 3)
を設定することになる。
一様ベクタのリテラルは、非一様ベクタのリテラルと同様にクォートする必要がある。一様ベクタは擬似クォート (quasiquote) の中に現れることはできるが、unquote
または unquote-splicing
フォームを含んではいけない (つまり、`(,x #u8(1 2))
は正しいが、`#u8(1 ,x 2)
は不正である) 。
この制約は、プログラムをパースするために read
手続きを使用する多くの Scheme システムに適合するためのものである。
(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
は任意の Scheme オブジェクト、n
は非負の正確整数、i
はベクタの長さより小さい非負の正確整数、TAGvect
は TAGvector
データ型のインスタンス、TAGvalue
は TAGvector
データ型の要素として格納できる数値、TAGlist
は TAGvector
データ型の要素として格納できる数値のリストである。
TAGvalue
が TAGvector
データ型の要素と同じ型でなければエラーである
(たとえば、正確整数を f64vector
に渡した場合) 。
埋め合わせる初期値を指定しない場合、ベクタの内容は規定されないが、
ベクタの個々の値はそのベクタ型の値の範囲を超えないことが保証される。
f32vector
と f64vector
データ型はともに 64 ビット浮動小数点数として実装することがあり得る。)
一様ベクタの定義済み手続きのポータブルな実装として、Scheme の非一様ベクタをベースにすることができる。
以下に例として s8vector
の実装を示すが、ここではエラー検査は省略している。
(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)))))))一様ベクタの外部表現を処理するために、Scheme システムの
read
と write
手続きおよびプログラム パーサも拡張する必要がある。
read
手続きおよびプログラム パーサが #s8
や #f32
などのプレフィックスを認識しなければならないことを除けば、その実装は非一様ベクタの実装に非常に近いものとなる。
(これは次のようにして検査できる。シャープ記号の次にシンボル先頭に許される文字が現れたときに、そのシンボルが t
、f
、s8
、f32
などであるか検査し、一様ベクタのプレフィックスである場合は、次の文字が開き丸括弧であるかを検査する)。
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.