by Peter McGoron
Submitted as SRFI 274.
For editor's use only. Please do not edit this section.
??? the draft/final/withdrawn status of the SRFI, information on how to subscribe to its mailing list, and important dates in its history. The editor will add this section.
A set of modest extensions to list conversion and list copying procedures is proposed that aligns them with other conversion and copying procedures and allows for some operations on improper and circular lists. Authors of further SRFIs that include list conversion procedures are encouraged to align their behavior with the behavior in this SRFI.
In the R7RS, procedures
such as vector-copy and string->list received
optional start and end arguments. These arguments
allow one to copy segments of the string/vector without having to write
an explicit loop for it.
The procedures that operate on lists, such as list-copy
and list->string, however, do not have these extensions.
The start and end arguments are arguably more
useful for lists, because they allow for conversion of circular lists
to other data types without explicit loops or intermediate allocations.
By allowing a selection of a portion of a list, the start and end arguments run into specification issues when passed dotted lists. How should they be handled?
Finite improper lists are an artefact of the representation of lists as cons cells. They are odd corner cases that many procedures will probably struggle with. But they have their uses, particularly for lazy computation, such as hygienic context propagation and odd sequences.
The common implementation of many procedures, such as
list-ref, list-tail, and map
(when operating on certain sets of multiple arguments),
work fine with improper lists. Critical here is that these procedures
only inspect a portion of a linked list: they don't care if list is
proper after those elements. An example of this behavior is the
“implementation responsibilities” section of many procedures in the
R6RS, which include
statements like
The implementation must check that list is a chain of pairs whose length is at least k. It should not check that it is a chain of pairs beyond this length.
This SRFI imposes a consistent method of dealing with improper lists for copying and conversion procedures. When end is supplied as an argument to a procedure, a dotted list is treated as if it was a proper list: it is treated as if its final cdr was the empty list, and not some non-list object. This treatment does not extend to situations where end is not supplied. For example:
(list->vector '(1 2 3 4 5 . 6))⇒ error(list->vector '(1 2 3 4 5 . 6) 2)⇒ error(list->vector '(1 2 3 4 5 . 6) 2 5)⇒ #(3 4 5)(list->vector '(1 2 3 4 5) 2 5)⇒ #(3 4 5)
This SRFI does not extend this behavior to all list procedures, only the procedures where it makes sense to add an explicit end argument. With the behavior described above, a simple higher-order procedure can convert a one-argument list conversion procedure into the type described by this SRFI:
(define (convert proc)
(case-lambda
((lst) (proc lst))
((lst start) (proc (drop lst start)))
((lst start end) (proc (take (drop lst start)
(- end start))))))
where drop and take are from
SRFI 1.
Implementations are encouraged to implement these procedures without
the extra allocations entailed by drop.
An improper list is a sequence of zero or more cons cells that do not end in an empty list. The elements of an improper list are the cars of the pairs of that sequence of cons cells. The length of an improper list is the number of cons cells before the final cdr. This number may be infinity. Note that if the final cdr is replaced with the empty list, then the length of the improper list is equal to the length of a proper list.
Any non-pair and non-null object is a zero-length improper list. For clarity, the term im-list is used in argument lists when an argument is a possibly improper list.
The procedures in this SRFI all take optional start and end arguments. For each procedure taking an argument im-list, it is an error if start and end are not exact integers, and it is an error if the following formula is not satisfied:
0 ≤ start ≤ end ≤ length
where length is the length of im-list.
The index start is always inclusive and the index end is always exclusive.
Unless otherwise specified, it is an error to pass an improper
list to a procedure without an explicit end argument.
(In this SRFI, the only exception is list-copy.)
Each procedure in this SRFI is associated with two libraries: the
library that contains the original specification of the procedure,
and the library specific to this SRFI. Implementations are encouraged
to have the same implementation from procedures exported from both
libraries: for example, list-copy from
(scheme base) should be the same as the one exported
from (srfi ### base).
Square brackets [] are used to denote a group of arguments that are optional, but all arguments must be present or absent. If one pair of square brackets are nested in another pair, then the nested pair is optional even when the other arguments are supplied.
(list-copy
im-list
[start
[end]])
If neither start or end are supplied, then this procedure returns an newly allocated copy of the sequence of pairs at the start of im-list. If im-list is an improper list, so is the result, and the final cdrs are the same in the sense of eqv?. An im-list which is not a list is returned unchanged. It is an error if im-list is circular.
If start but not end is supplied, this procedure
is equivalent to (list-copy (list-tail im-list start)).
If both start and end are supplied, then the startth pair to the endth pair are copied, and the list is terminated with an empty list.
In any case, only the pairs themselves are copied; the cars of the
pairs in the result are the same (in the sense of eqv?) as
the cars of the corresponding pairs that were copied from im-list.
(list->string
im-list
[start
[end]])
It is an error if the elements of im-list are not characters.
Returns a newly allocated string formed from the elements of
im-list between start and end.
Order is preserved. This procedure and string->list
are inverses in the following sense for each appropriate
string, list, start, and
end:
(equal? (list->string (string->list string
start
end))
(substring string start end)) ⇒ #t
(equal? (string->list (list->string list
start
end))
(list-copy list start end)) ⇒ #t
(list->vector
im-list
[start
[end]])
Returns a newly created vector initialized to the elements of im-list between start and end.
(list->vector '(dah dah didah) 1 2) ⇒ #(dah)
These procedures are exported from SRFI libraries that are included
in R7RS-Large.
If an implementation does not support a certain SRFI, then the
corresponding (srfi ###) sublibrary is not required.
(list->stream
im-list
[start
[end]])
(list->deque
im-list
[start
[end]])
(list->generator
im-list
[start
[end]])
(list->⟨type⟩vector
im-list
[start
[end]])
(list->bitvector
im-list
[start
[end]])
A portable R7RS is available in the SRFI repository. Implementations are encouraged to use the definitions here instead of the definitions in other SRFIs or in the Reports: they are all backwards-compatible.
Thanks to those in Working Group 2 for discussing the semantics of these procedures.
© 2026 Peter McGoron.
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 (including the next paragraph) 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.