Package name

RANGE-OBJECT

1. Package documentation

A range object implementation for Common Lisp.

A range object is an immutable sequence-like object whose values are retrievable using an algorithm. This library is based closely on SRFI 196, an implementation of range objects in Scheme, created by John Cowan and Wolfgang Corcoran-Mathe.

See below for the API. The following sections give an overview of the provided functions.

1.1. Constructors

make-range is the basic constructor, taking a length and an indexer function. The indexer is the algorithmic representation of the range: it maps an integer in [0,length) to the required range value.

Specialist constructors are available to construct ranges from numbers or existing sequences: these include numeric-range, iota-range, string-range and vector-range.

Two further functions construct new ranges from existing ranges: range-append and range-reverse.

Conversion to-from sequences is supported with range-to-list, range-to-string, range-to-vector, string-to-range and vector-to-range.

For example:

* (range-to-list (range-append (iota-range 10) (numeric-range 10 20)))
(0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19)

1.2. Accessor

range-elt provides direct access to each element in the range.

* (range-elt (vector-range #(3 9 1)) 1)
9

range-subseq returns a new range over a subrange; it takes arguments the same as subseq on sequences.

* (range-to-list (range-subseq (numeric-range 10 50) 5 10))
(15 16 17 18 19)

The following functions in this subsection are taken from SRFI 196 and separate ranges into smaller ranges. The most basic is range-split-at, which separates a range at a given index point into two ranges, returned as two values.

* (multiple-value-bind (ra rb) (range-object:range-split-at (range-object:iota-range 10) 3) (range-object:range-to-list ra))
(0 1 2)

range-segment instead creates a list of ranges, each of a required length:

* (length (range-segment (iota-range 18 10) 5))
4
* (range-to-list (fourth (range-segment (iota-range 18 10) 5)))
(25 26 27)

The group of drop/take functions either take a count or, in the drop-while/take-while form, a predicate to find a point to split the range. All accept a :from-end keyword to support operating from the right.

* (range-to-list (range-drop (numeric-range 0 10) 5))
(5 6 7 8 9)
* (range-to-list (range-drop (numeric-range 0 10) 5 :from-end t))
(0 1 2 3 4)
* (range-to-list (range-take-while #'(lambda (x) (< x 10)) (numeric-range 5 15)))
(5 6 7 8 9)

1.3. Sequence-Like Iteration

A number of functions are provided analogous to those available on general sequences. These accept the same keywords and have similar semantics.

These include the conditionals range-every range-some range-notany range-notevery which all take a predicate and one or more ranges or sequences. Range elements are accessed using range-elt and sequence elements using elt. Results and behaviour are the same as with the sequence function equivalents.

For example:

* (range-some #'evenp (numeric-range 0 10))
T
* (range-notevery #'< (vector-range #(1 2 3)) (vector-range #(3 3 3)))
T

For iteration, analogues of count find and position are provided, along with their higher-order variants: these are range-count range-find range-position with the usual keyword arguments :start :end :from-end :key :test.

For example:

* (range-count-if #'evenp (numeric-range 0 10) :end 5)
3

In addition range-reduce works like reduce for sequences, supporting the standard :start :end :test :initial-value :key keyword options.

* (range-reduce #'+ (numeric-range 0 10))
45

dorange and range-mapc support direct iteration over the items in a range. e.g. to print the items in a range:

(dorange (i (numeric-range 20 30))
   (print i))

1.4. Unimplemented Functions

Some functions in SRFI 196 or from Lisp’s sequences are not supported. These include mutation functions and those where the SRFI implementation results in an internal representation being a vector. Hence, no map equivalent, except for range-mapc, which is equivalent to Scheme’s for-each.

1.5. Install

To install range-object, download the latest release and make the code available to the asdf system; on quicklisp or similar, place the code in "quicklisp/local-projects".

This package has no dependencies.

1.6. MIT Licence

Copyright © 2024 Peter Lane

Copyright © 2020 Wolfgang Corcoran-Mathe - SRFI 196 Scheme implementation

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.

2. Functions

IOTA-RANGE
Lambda list

iota-range ( len &optional (start 0) (step 1) )

Documentation

Returns a range-object instance with numeric elements.

MAKE-RANGE
Lambda list

make-range ( len indexer )

Documentation

Returns a range-object instance with given algorithmic representation.

NUMERIC-RANGE
Lambda list

numeric-range ( start end &optional (step 1) )

Documentation

Returns a range-object instance with numeric elements.

RANGE-APPEND
Lambda list

range-append ( range-a range-b )

Documentation

Returns a new range-object instance based on following items in the first range followed by the second.

RANGE-COUNT
Lambda list

range-count ( item range &key from-end start end key test test-not )

Documentation

Returns count of item in given range bounded by start and end satisfying given test.

RANGE-COUNT-IF
Lambda list

range-count-if ( pred range &key from-end start end key )

Documentation

Returns count of items satisfying predicate within given bounds.

RANGE-COUNT-IF-NOT
Lambda list

range-count-if-not ( pred range &key from-end start end key )

Documentation

Returns count of items not satisfying predicate within given bounds.

RANGE-DROP
Lambda list

range-drop ( range n &key from-end )

Documentation

Returns a new range containing all but the first/last n items of range.

RANGE-DROP-WHILE
Lambda list

range-drop-while ( pred range &key from-end )

Documentation

Returns a range which omits leading/trailing elements of range that satisfy pred, up to the first one that does not.

RANGE-ELT
Lambda list

range-elt ( range index )

Documentation

Return item at given index of range.

RANGE-EQUALP
Lambda list

range-equalp ( range-a range-b &key (test #'eql) )

Documentation

Two ranges are equal if their elements are equal.

RANGE-EVERY
Lambda list

range-every ( pred range-1 &rest ranges )

Documentation

Return t if given predicate returns t for all elements across ranges.

RANGE-FIND
Lambda list

range-find ( item range &key from-end test test-not start end key )

Documentation

Returns item in range which satisfies test with provided item within given bounds.

RANGE-FIND-IF
Lambda list

range-find-if ( pred range &key from-end start end key )

Documentation

Returns item in range which satisfies given predicate within given bounds.

RANGE-FIND-IF-NOT
Lambda list

range-find-if-not ( pred range &key from-end start end key )

Documentation

Returns item in range which does not satisfy given predicate within given bounds.

RANGE-FIRST
Lambda list

range-first ( range )

Documentation

Return first item in range.

RANGE-LAST
Lambda list

range-last ( range )

Documentation

Return last item in range.

RANGE-LENGTH
Lambda list

range-length ( range )

Documentation

Returns the length of the given range.

RANGE-MAPC
Lambda list

range-mapc ( op range )

Documentation

Applies given operation to each item in the range in turn.

RANGE-NOTANY
Lambda list

range-notany ( pred range-1 &rest ranges )

Documentation

Return t if given predicate returns nil for all elements across ranges.

RANGE-NOTEVERY
Lambda list

range-notevery ( pred range-1 &rest ranges )

Documentation

Return t if given predicate returns nil for at least one element across ranges.

RANGE-POSITION
Lambda list

range-position ( item range &key from-end test test-not start end key )

Documentation

Returns index in range which satisfies test with provided item within given bounds.

RANGE-POSITION-IF
Lambda list

range-position-if ( pred range &key from-end start end key )

Documentation

Returns index in range which satisfies given predicate within given bounds.

RANGE-POSITION-IF-NOT
Lambda list

range-position-if-not ( pred range &key from-end start end key )

Documentation

Returns index in range which does not satisfy given predicate within given bounds.

RANGE-REDUCE
Lambda list

range-reduce ( op r &key start end from-end key (initial-value 'range-reduce-undeclared) )

Documentation

Reduce for ranges.

RANGE-REVERSE
Lambda list

range-reverse ( range )

Documentation

Returns a new range object instance whose values are the same as range but indexed in reverse.

RANGE-SEGMENT
Lambda list

range-segment ( range len )

Documentation

Returns a list of subranges of range, each of length len.

RANGE-SOME
Lambda list

range-some ( pred range-1 &rest ranges )

Documentation

Return t if given predicate returns t for at least one element across ranges.

RANGE-SPLIT-AT
Lambda list

range-split-at ( range index )

Documentation

Returns as values two ranges, one < index and one >= index.

RANGE-SUBSEQ
Lambda list

range-subseq ( range start &optional end )

Documentation

Returns a new range which is a subsequence of the given range.

RANGE-TAKE
Lambda list

range-take ( range n &key from-end )

Documentation

Returns a new range containing only the first/last n items of range.

RANGE-TAKE-WHILE
Lambda list

range-take-while ( pred range &key from-end )

Documentation

Returns a range which contains leading/trailing elements of range that satisfy pred, up to the first one that does not.

RANGE-TO-LIST
Lambda list

range-to-list ( range )

Documentation

Returns a list from the given range.

RANGE-TO-STRING
Lambda list

range-to-string ( range )

Documentation

Returns a string from the given range.

RANGE-TO-VECTOR
Lambda list

range-to-vector ( range )

Documentation

Returns a vector from the given range.

RANGEP
Lambda list

rangep ( range )

Documentation

Return t if given object is a range object.

STRING-RANGE
Lambda list

string-range ( str )

Documentation

Returns a range-object instance with elements across given string.

STRING-TO-RANGE
Lambda list

string-to-range ( str )

Documentation

Returns a range object from the given string.

VECTOR-RANGE
Lambda list

vector-range ( vec )

Documentation

Returns a range-object instance with elements across given vector.

VECTOR-TO-RANGE
Lambda list

vector-to-range ( vec )

Documentation

Returns a range object from the given vector.

3. Macros

DORANGE
Lambda list

dorange ( (var range &optional result) &body body )

Documentation

Sets var to each value in range in turn before executing body. Returns result or nil.