274: Extended List Conversion Procedures

by Peter McGoron

Status

This SRFI is currently in draft status. Here is an explanation of each status that a SRFI can hold. To provide input on this SRFI, please send email to srfi-274@nospamsrfi.schemers.org. To subscribe to the list, follow these instructions. You can access previous messages via the mailing list archive.

Abstract

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.

Issues

None at present.

Rationale

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, 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. But 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 were a proper list: it is treated as if its final cdr were 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.

Specification

Improper lists

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. If the final cdr of an improper list is replaced with the empty list, then the length of the resulting proper list is equal to the length of the improper 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 start and end arguments

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 ≤ startendlength

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.)

Libraries

Each procedure in this SRFI is associated with multiple libraries: at least one is the library that contains the original specification of the procedure, and another is 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 274 base).

Editorial conventions

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.

Procedures

(scheme base)
(srfi 274 base)
procedure
(list-copy im-list [start [end]])

If neither start nor end is supplied, then this procedure returns a 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-copy '(1 2 3 4 5 . 6)) (1 2 3 4 5 . 6)
(list-copy '(1 2 3 4 5 . 6) 2) (3 4 5 . 6)
(list-copy '(1 2 3 4 5 . 6) 2 5) (3 4 5)
(list-copy '(1 2 3 4 5) 2 5) (3 4 5)
(list-copy #1='(1 2 #1#) 1 8)(2 1 2 1 2 1 2)
(scheme base)
(srfi 274 base)
procedure
(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
(scheme base)
(srfi 274 base)
procedure
(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)
(list->vector '(do be do be doo . dah) 2 5) #(do be doo)

R7RS Large SRFI procedures

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 274) sublibrary is not required.

Not all procedures that convert from list representations are included. Procedures that operate on assocation lists and lists that are treated as sets are excluded, because those lists are usually unordered.

(srfi 41)
(srfi 274 41)
procedure
(list->stream im-list [start [end]])
(srfi 134)
(srfi 274 134)
procedure
(list->ideque im-list [start [end]])
(srfi 158)
(srfi 274 158)
procedure
(list->generator im-list [start [end]])
(srfi 160 ⟨type⟩)
(srfi 160 base)
(srfi 274 160 ⟨type⟩)
(srfi 274 160 base)
procedure
(list->⟨type⟩vector im-list [start [end]])

Implementation

A portable R7RS is available in the SRFI repository It has been tested to work in Chibi Scheme 0.11.0. Implementers are encouraged to align the behavior of the list conversion procedures in all specified libraries.

Acknowledgements

Thanks to those in Working Group 2 for discussing the semantics of these procedures. Topics related to this SRFI were discussed on the R7RS Large issue tracker (#341, #206) and in meetings on April 30th, 2026 and May 19th, 2026.

© 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.


Editor: Arthur A. Gleckler