This SRFI is currently in final status. Here is an explanation of each status that a SRFI can hold. To provide input on this SRFI, please send email to srfi133@nospamsrfi.schemers.org
. To subscribe to the list, follow these instructions. You can access previous messages via the mailing list archive.
vectorunfold!
)vectorcumulate
from (vectorcumulate f vec knil)
to
(vectorcumulate f knil vec)
to match the
argument order of vectorfold
.)vectorpartition
.)elt=?
argument be consistent with eq?
.)vectormap!
.
Clarified the second return value
of vectorpartition
in the case that all elements satisfy pred?.)Postfinalization note: The finalized version of this
SRFI required the equality operator used by the
vector=
procedure to be consistent with
eq?
. However, =
is not consistent
with eq?
in a Scheme which provides NaN values and
IEEE semantics for them, as (eq? +nan.0 +nan.0)
may
return either #t
or #f
but (=
+nan.0 +nan.0)
must return #f.
This means
that the expected semantics of =
when used with
vector=
are violated. Therefore, the requirement
for consistency has been removed from this version, and the
sample implementation adjusted accordingly.
This SRFI proposes a comprehensive library of vector operations accompanied by a freely available and complete reference implementation. The reference implementation is unencumbered by copyright, and useable with no modifications on any Scheme system that is R5RScompliant. It also provides several hooks for implementationspecific optimization as well.
R5RS provides very few listprocessing procedures, for which reason SRFI 1 exists. However, R5RS provides even fewer vector operations — while it provides mapping, appending, et cetera operations for lists, it specifies only nine vector manipulation operations:
vector?
makevector
vector
vectorlength
vectorref
vectorset!
vector>list
list>vector
vectorfill!
R7RSsmall added support for
start and end arguments to vector>list
,
list>vector
and vectorfill!
. It also
provided seven additional vector procedures, bringing vectors
and lists to approximate parity:
SRFI 43 standardized more vector procedures,
all of which are included in this SRFI. Unfortunately, R7RSsmall
and SRFI 43 placed irreconcileable requirements on the procedures
invoked by vectormap
and vectorforeach
.
This SRFI resolves that issue by changing these SRFI 43
procedures as well as vectormap!
, vectorfold
,
vectorfoldright
, and vectorcount
to leave
out the index argument that is passed under SRFI 43's
definition.
In addition, the version of vectorcopy
in this SRFI
does not require support for a fill argument, which
makes it equivalent to the R7RSsmall definition.
This SRFI also provides the following new procedures (some from Python, some from other sources):
It should be noted that no vector sorting procedures are provided by this SRFI, because there already are several SRFIs for that purpose.
Here is an index of the procedures provided by this package. Those marked by italics are also provided in R7RSsmall.
makevector
vector
vectorunfold
vectorunfoldright
vectorcopy
vectorreversecopy
vectorappend
vectorconcatenate
vectorappendsubvectors
vector?
vectorempty?
vector=
vectorref
vectorlength
vectorfold
vectorfoldright
vectormap
vectormap!
vectorforeach
vectorcount
vectorcumulate
vectorindex
vectorindexright
vectorskip
vectorskipright
vectorbinarysearch
vectorany
vectorevery
vectorpartition
vectorset!
vectorswap!
vectorfill!
vectorreverse!
vectorcopy!
vectorreversecopy!
vectorunfold!
vectorunfoldright!
vector>list
reversevector>list
list>vector
reverselist>vector
vector>string
string>vector
In this section containing specifications of procedures, the following notation is used to specify parameters and return values:
f
takes the parameters
arg_{1} arg_{2}
...
and returns a value of the
type something
. If something
is unspecified
, then f
returns a single
implementationdependent value; this SRFI does not specify what it
returns, and in order to write portable code, the return value
should be ignored.
vector?
.
exact?
, integer?
and either
zero?
or positive?
. The third case of it
indicates the index at which traversal begins; the fourth case
of it indicates the size of a vector.
exact?
, integer?
and
either zero?
or positive?
. This indicates the index directly before
which traversal will stop — processing will occur until
the the index of the vector is end
. It is the
closed right side of a range.
something
is an optional
argument; it needn't necessarily be applied.
Something
needn't necessarily be one thing; for
example, this usage of it is perfectly valid:
[start [end]]
something
s are
allowed to be arguments.
something
must be
arguments.
n
will be used later in the
procedure description.
It should be noted that all of the procedures that iterate across
multiple vectors in parallel stop iterating and produce the final
result when the end of the shortest vector is reached. The sole
exception is vector=
, which
automatically returns #f
if the vectors' lengths vary.
size
.
If fill is specified, all the elements of the vector
are initialized to fill. Otherwise, their contents
are indeterminate.
(makevector 5 3)
#(3 3 3 3 3)
x ...
.
(vector 0 1 2 3 4)
#(0 1 2 3 4)
length
and iterates across each index
k
between 0
and
length
, applying f
at each
iteration to the current index and current seeds, in that
order, to receive n + 1
values: first, the
element to put in the k
th slot of the new
vector and n
new seeds for the next iteration.
It is an error for the number of seeds to vary between
iterations. Note that the termination condition is different from
the unfold
procedure of SRFI 1.
(vectorunfold (λ (i x) (values x ( x 1)))
10 0)
#(0 1 2 3 4 5 6 7 8 9)
n
).
(vectorunfold values n
)
#(0 1 2 ... n2 n1)
vector
.
(vectorunfold (λ (i) (vectorref vector i))
(vectorlength vector))
vectorunfold
, but
it uses f
to generate elements from
righttoleft, rather than lefttoright.
The first index used is length  1.
Note that the termination condition is different from
the unfoldright
procedure of SRFI 1.
(vectorunfoldright (λ (i x) (values (cons i x) (+ x 1))) 5 0)
#((0 . 4) (1 . 3) (2 . 2) (3 . 1) (4 . 0))
vector
.
(vectorunfoldright (λ (i x)
(values (vectorref vector x)
(+ x 1)))
(vectorlength vector)
0)
end 
start
and fills it with elements from
vec
, taking elements from vec
starting at index start
and stopping at index
end
. Start
defaults to
0
and end
defaults to the value of
(vectorlength
vec)
.
SRFI 43 provides an optional fill argument to supply
values if end is greater than the length of vec.
Neither R7RSsmall nor this SRFI requires support for this argument.
(vectorcopy '#(a b c d e f g h i))
#(a b c d e f g h i)
(vectorcopy '#(a b c d e f g h i) 6)
#(g h i)
(vectorcopy '#(a b c d e f g h i) 3 6)
#(d e f)
vectorcopy
, but it
copies the elements in the reverse order from
vec
.
(vectorreversecopy '#(5 4 3 2 1 0) 1 5)
#(1 2 3 4)
vec
...
.
(vectorappend '#(x) '#(y))
#(x y)
(vectorappend '#(a) '#(b c d))
#(a b c d)
(vectorappend '#(a #(b)) '#(#(c)))
#(a #(b) #(c))
listofvectors
. This
is equivalent to:
(apply vectorappend
listofvectors)
(vectorconcatenate '(#(a b) #(c d)))
#(a b c d)
vectorappend
.
(vectorappendsubvectors '#(a b c d e) 0 2 '#(f g h i j) 2 4)
#(a b h i)
#t
if x
is a
vector, and #f
if otherwise.
(vector? '#(a b c))
#t
(vector? '(a b c))
#f
(vector? #t)
#f
(vector? '#())
#t
(vector? '())
#f
#t
if vec
is empty, i.e. its
length is 0
, and #f
if not.
(vectorempty? '#(a))
#f
(vectorempty? '#(()))
#f
(vectorempty? '#(#()))
#f
(vectorempty? '#())
#t
a
and
b
are considered equal by vector=
iff
their lengths are the same, and for each respective element
E_{a}
and
E_{b}
, (elt=? E_{a}
E_{b})
returns a true value.
Elt=?
is always applied to two arguments.
#t
is
automatically returned. The dynamic order in which comparisons
of elements and of vectors are performed is left completely
unspecified; do not rely on a particular order.
(vector= eq? '#(a b c d) '#(a b c d))
#t
(vector= eq? '#(a b c d) '#(a b d c))
#f
(vector= = '#(1 2 3 4 5) '#(1 2 3 4))
#f
(vector= = '#(1 2 3 4) '#(1 2 3 4))
#t
(vector= eq?)
#t
(vector= eq? '#(a))
#t
eq?
.
(vector= eq? (vector (vector 'a)) (vector (vector 'a)))
#f
(vector= equal? (vector (vector 'a)) (vector (vector 'a)))
#t
vec
at
i
is mapped to in the store. Indexing is based
on zero. I
must be within the range [0,
(vectorlength
vec)
).
(vectorref '#(a b c d) 2)
c
vec
, the number of
locations reachable from vec
. (The careful
word 'reachable' is used to allow for 'vector slices,' whereby
vec
refers to a larger vector that contains
more locations that are unreachable from vec
.
This SRFI does not define vector slices, but later SRFIs may.)
(vectorlength '#(a b c))
3
Kons
is
iterated over each value in all of the vectors, stopping at the
end of the shortest; kons
is applied as
(kons state
(vectorref
vec_{1} i)
(vectorref
vec_{2} i)
...)
where state
is the current state value —
the current state value begins with knil
, and
becomes whatever kons
returned on the
previous iteration —, and i
is the
current index.
vectorofstrings
.
(vectorfold (λ (len str)
(max (stringlength str) len))
0 vectorofstrings)
vec
.
(vectorfold (λ (tail elt) (cons elt tail))
'() vec)
vec
.
(vectorfold (λ (counter n)
(if (even? n) (+ counter 1) counter))
0 vec)
vectorfold
, but
it iterates right to left instead of left to right.
(vectorfoldright (λ (tail elt)
(cons elt tail))
'() '#(a b c d))
(a b c d)
i
of the new
vector is mapped from the old vectors by
(f (vectorref
vec_{1}
i)
(vectorref
vec_{2}
i)
...)
.
The dynamic order of application of f
is
unspecified.
(vectormap (λ (x) (* x x))
(vectorunfold
(λ (i x) (values x (+ x 1)))
4 1))
#(1 4 9 16)
(vectormap (λ (x y) (* x y))
(vectorunfold
(λ (x) (values x (+ x 1)))
5 1)
(vectorunfold
(λ (x) (values x ( x 1)))
5 5))
#(5 8 9 8 5)
(let ((count 0))
(vectormap (λ (ignoredelt)
(set! count (+ count 1))
count)
'#(a b)))
#(1 2) OR #(2 1)
vectormap
, but
rather than mapping the new elements into a new vector, the new
mapped elements are destructively inserted into
vec_{1}
. Again, the dynamic order of
application of f
unspecified, so it is
dangerous for f
to apply either
vectorref
or
vectorset!
to
vec_{1}
in f
. It is
an error if vec_{1}
contains more
elements than any other vec
.
f
to
the corresponding list of parallel elements
from vec_{1} vec_{2}
...
in the range [0, length
), where
length
is the length of the smallest vector
argument passed,
In contrast with
vectormap
, f
is reliably applied to each subsequent element, starting at
index 0, in the vectors.
(vectorforeach (λ (x) (display x) (newline))
'#("foo" "bar" "baz" "quux" "zot"))
foo bar baz quux zot
pred?
, which is applied, for each index
i
in the range [0, length
)
where length
is the length of the
smallest vector argument, to each
parallel element in the vectors, in order.
(vectorcount even?
'#(3 1 4 1 5 9 2 5 6))
3
(vectorcount <
'#(1 3 6 9) '#(2 4 6 8 10 12))
2
new
with the same length as vec
.
Each element i of new is set to the result of invoking
f
on new
_{i1}
and vec
_{i},
except that for the first call on f, the first argument is
knil. The new vector is returned.
Note that the order of arguments to vectorcumulate
was changed by errata3
on 20160902.
(vectorcumulate + 0 '#(3 1 4 1 5 9 2 5 6))
#(3 4 8 9 14 23 25 30 36)
vec_{1} vec_{2}
...
that satisfy
pred?
. If no matching element is found by the
end of the shortest vector, #f
is returned.
(vectorindex even? '#(3 1 4 1 5 9))
2
(vectorindex < '#(3 1 4 1 5 9 2 5 6) '#(2 7 1 8 2))
1
(vectorindex = '#(3 1 4 1 5 9 2 5 6) '#(2 7 1 8 2))
#f
vectorindex
, but it
searches righttoleft, rather than lefttoright, and all of
the vectors must have the same length.
vec_{1} vec_{2}
...
that do not satisfy
pred?
. If all the values in the vectors
satisfy pred?
until the end of the shortest
vector, this returns #f
. This is equivalent to:
(vectorindex
(λ (x_{1} x_{2}
...)
(not (pred? x_{1}
x_{1}
...)))
vec_{1} vec_{2}
...)
(vectorskip number? '#(1 2 a b 3 4 c d))
2
vectorskip
, but it
searches for a nonmatching element righttoleft, rather than
lefttoright, and it is an error if all of the vectors do not
have the same length. This is equivalent to:
(vectorindexright
(λ (x_{1} x_{2}
...)
(not (pred? x_{1}
x_{1}
...)))
vec_{1} vec_{2}
...)
Similar to vectorindex
and
vectorindexright
,
but instead of searching left to right or right to left, this
performs a binary search.
If there is more than one element of vec that matches
value in the sense of cmp,
vectorbinarysearch
may return the index of any of them.
cmp
should be a
procedure of two arguments and return a negative integer, which
indicates that its first argument is less than its second,
zero, which indicates that they are equal, or a positive
integer, which indicates that the first argument is greater
than the second argument. An example cmp
might
be:
(λ (char_{1} char_{2})
(cond ((char<? char_{1}
char_{2})
1)
((char=? char_{1}
char_{2})
0)
(else 1)))
vec_{1} vec_{2}
...
for which
pred?
returns a true value. If such a parallel
set of elements exists, vectorany
returns the value
that pred?
returned for that set of elements.
The iteration is strictly lefttoright.
i
between 0 and the length
of the shortest vector argument, the set of elements
(vectorref vec_{1}
i)
(vectorref vec_{2}
i)
...
satisfies pred?
, vectorevery
returns
the value that pred?
returned for the last
set of elements, at the last index of the shortest vector. The
iteration is strictly lefttoright.
vec
is newly allocated
and filled with all the elements of vec
that
satisfy pred?
in their original order followed
by all the elements that do not satisfy pred?
,
also in their original order.
pred?
.
i
in
vec
to value
.
vec
at i
&
j
.
vec
between start
, which defaults to 0
and
end
, which defaults to the length of
vec
, to fill
.
vec
between start
and end
. Start
defaults to
0
and end
defaults to the length of
vec
. Note that this does not deeply reverse.
from
between start
and end
to vector to
, starting at at
.
The order in which elements
are copied is unspecified, except that if the source and destination
overlap, copying takes place as if the source is first
copied into a temporary vector and then into the destination.
This can be achieved without allocating storage by
making sure to copy in the correct direction in such circumstances.
vectorcopy!
, but
the elements appear in to
in reverse order.
vectorunfold
, but
the elements are copied into the vector vec starting
at element start rather than into a newly allocated vector.
Terminates when endstart elements have been generated.
vectorunfold!
, but the
elements are copied in reverse order into the vector vec
starting at the index preceding end.
vec
between start
, which defaults to 0
,
and end
, which defaults to the length of
vec
.
vector>list
,
but the resulting list contains the elements in reverse of
vec
.
properlist
.
list>vector
,
but the resulting vector contains the elements in reverse of
properlist
.
string
between start
, which defaults to 0
,
and end
, which defaults to the length of
string
.
vec
between start
, which defaults to 0
,
and end
, which defaults to the length of
vec
. It is an error if the elements are not characters.
The sample implementation is in the repository of this SRFI.
It has only one nonR5RS dependency:
SRFI 23's error
procedure,
which is also provided by R7RSsmall.
It is in the public domain, or alternatively under the same copyright
as this SRFI. The following files are provided:
vectorsimpl.scm

a modified version of the implementation of SRFI 43vectors.scm

a Chicken library showing what to export for an R5RS implementationvectors.sld

an R7RS library that excludes what R7RSsmall already providesvectorstest.scm

tests using the Chicken test egg (also available on Chibi)These acknowledgements are copied from SRFI 43.
Thanks to Olin Shivers for his wonderfully complete
list and string
packages; to all the members of the
#scheme
IRC
channel on Freenode
who nitpicked a great deal, but also helped quite a lot in
general, and helped test the reference implementation in various
Scheme systems; to Michael Burschik for his numerous comments; to
Sergei Egorov for helping to narrow down the procedures; to Mike
Sperber for putting up with an extremely overdue draft; to
Felix Winkelmann for continually bugging me about finishing up the
SRFI so that it would be only overdue and not withdrawn; and to
everyone else who gave questions, comments, thoughts, or merely
attention to the SRFI.
error
) for
reporting that an error occurred, written by Stephan Houben.
Copyright (C) Taylor Campbell (2003). All rights reserved.
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.