You are looking at historical revision 31172 of this page. It may differ significantly from its current revision.

Rationale

Scheme lists are mutable and untyped. The list types produced with the only exported symbol of this module, a giant macro, are typed and immutable.

Concerning mutability, Scheme's authors, G. J. Sussman and G. L. Steele jr. in their paper "The First Report on Scheme Revisited", Higher-Order and Symbolic Computation, 11, 399-404 (1998) argued:

"We also now believe that Carl Hewitt was right: we would have been better off to have introduced cells as a separate, primitive kind of object, rather than allowing assignment to any and every lambda-bound variable"

Well, cells -- or boxes, if you prefer -- exist as modules, so restricted mutability can be provided by accepting cells -- or boxes -- as item types.

Typing of list arguments on the other hand improves security of the implemented functions on the one side, but are cumbersome to use on the other: After all, we don't want to write the same routines for lists of numbers, lists of strings, lists of symbols, ... over and over again. Macros come to the rescue, you guess it! Hence this module exports only one macro, define-list-type, which implements a long list of functions, which differ mostly only by a prefix, you provide, from standard list functions, an item type, you provide as well, and last but not least a user named documentation procedure, showing you the signatures of all the generated functions.

But note, that these typed lists don't pass the list? predicate. They are different creatures, created with define-datatype and accessed with cases from the datatype module.

Programming interface

define-list-type

<macro>(define-list-type name

                        documentation: docu
                        item-predicate: ok?
                        item-equality: equ?
                        procedure-prefix: pre)</macro>

defines a new list type, name, whose items must pass the ok? predicate and are compared by equ?, and a documentation procedure, docu, by implementing a long list of functions, most of them prefixed by the prefix pre. Exceptions of this prefix rule are the constructor and type predicate for the list, named name as well or name with an appended question mark. The list of generated functions are given by a call to docu without arguments, the signature of such a function by the call (docu 'function).

Note that most of the functions are prefixed versions of standard list functions, some of them with changed order of arguments. The reason for that is consistency: The list arguments are always the last ones.

Examples


(require-library typed-lists cells)
(import typed-lists cells)

(define-list-type lon
                  documentation: nlists
                  item-predicate: (lambda (x)
                                    (or (number? x)
                                        ((cell-of? number?) x)))
                  item-equality: (lambda (x y)
                                   (or (and (number? x)
                                            (number? y)
                                            (= x y))
                                       (and (cell? x)
                                            (cell? y)
                                            (= (cell-ref x)
                                               (cell-ref y)))))
                  procedure-prefix: n)

(define nnil (nnull))
(lon? nnil) ; -> #t
(nnull? nnil) ; -> #t
(null? nnil) ; -> #f
(define nls (ncons 1 nnil))
(lon? nls) ; -> #t
(define nlst (lon 0 1 (cell 2) 3 4))
(lon? nlst) ; -> #t
(list? nlst) ; -> #f
(napply + 1 2 (lon 3 4 5)) ; ->15
(nrepeat 5 0) ; -> '#,(lon 0 0 0 0 0)
(nequal? (niterate-times 5 add1 0) (lon 0 1 2 3 4)) ; -> #t
(niterate-while (lambda (x) (< x 5)) add1 0) ; -> '#,(lon 0 1 2 3 4))
(niterate-until (lambda (x) (= x 5)) add1 0) ; -> '#,(lon 0 1 2 3 4)
(nzip (lon 1 2 3 4 5) (lon 10 20 30)) ; -> '#,(lon 1 10 2 20 3 30 4 5)
(ninterpose 10 (lon 1 2 3 4 5)) ; -> '#,(lon 1 10 2 10 3 10 4 10 5)
(ncdddr nlst) ; -> '#,(lon 3 4)
(ncadddr nlst) ; -> 3
(nequal? (ndrop 3 nlst) (lon 3 4)) ; -> #t
(nequal? (ndrop-while odd? (lon 1 3 2 4 5))
         (lon 2 4 5)) ; -> #t
(nequal? (ntake-while odd? (lon 1 3 2 4 5))
         (lon 1 3)) ; -> #t
(receive (head tail) (nsplit-with even? (lon 1 3 2 4 5))
  (and (nequal? head (lon 1 3))
       (nequal? tail (lon 2 4 5)))) ; -> #t
(ntake 2 nlst) ; -> (lon 0 1)
(lon? (nnull)) ; -> #t
(nnull? (nnull)) ; -> #t
(nnull? nls) ; -> #f
(lon? '(1 2)) ; -> #f
(nnull? (ncdr nls)) ; -> #t
(ncar nlst) ; -> 0
(lon? (nreverse nlst)) ; -> #t
(nreverse nlst) '#,(lon 4 3 !2! 1 0)
(equal? (lon->list nlst)
        (list 0 1 (cell 2) 3 4)) ; -> #t
(equal? (nref 2 nlst) (cell 2)) ; -> #t
(cell-set! (nref 2 nlst) 20)
(equal? (nref 2 nlst) (cell 20)) ; -> #t
(cell-ref (nref 2 nlst)) ; -> 20
(nlength nlst) ; -> 5
(nequal? (nsublist 2 4 nlst)
         (lon (cell 20) 3)) ; -> #t
(nequal?
  (nappend (lon 0 1 2 3)
           (lon 4 5 6))
  (lon 0 1 2 3 4 5 6)) ; -> #t
(nequal?
  (nappend (lon 0)
           (lon 1)
           (lon 2)
           (lon 3 4)
           (lon 5 6 7)
           (lon 8))
  (lon 0 1 2 3 4 5 6 7 8)) ; -> #t
(nequal?
  (nmap add1
        (lon 0 1 2 3))
  (lon 1 2 3 4)) ; -> #t
(nequal?
  (nmap +
        (lon 1 2 3)
        (lon 10 20 30 40))
  (lon 11 22 33)) ; -> #t
(nfold-right ncons (nnull) (lon 0 1 2 3 4)) ; -> '#,(lon 0 1 2 3 4))
(nfold-left + 0 (lon 1 2 3) (lon 10 20 30)) ; -> 66
(nfold-left cons '(100) (lon 1 2 3 4)) ; -> '(((((100) . 1) . 2) . 3) . 4)
(equal?
  (call-with-values
    (lambda () (nreverse* (lon 1 2 3) (lon 10 20 30)))
    list)
  (list (lon 3 2 1) (lon 30 20 10))) ; -> #t
(nremove 0 (lon 1 0 2 0 3 0 4)) ; -> '#,(lon 1 2 3 4)
(nmerge < (lon 2 4 5 7 8) (lon 1 3 6 9 10)) ; -> '#,(lon 1 2 3 4 5 6 7 8 9 10))
(condition-case (nmerge < (nnull) (lon 1 3 2))
       ((exn) #f)) ; -> #f
(nevery? odd? (lon 1 3 5)) ; -> #t
(nevery? odd? (lon)) ; -> #t
(nsome odd? (lon 2 3 5)) ; -> 3
(nsome odd? (lon 2 4 6)) ; -> #f
(nnot-every? odd? (lon 1 2 3)) ; -> #t
(nnot-any? odd? (lon 2 4 6)) ; -> #t
(lon->set (lon 1 2 1 3 2 3)) ; -> '#,(lon 1 2 3)
(lon? (lon 1 2 3)) ; -> #t
(nset? (lon 1 2 3)) ; -> #t
(nset? (lon 1 2 2 3)) ; -> #f
(nin? 2 (lon 1 2 3)) ; -> #t
(nsubset? (lon 1 2) (lon 1 2 3 4)) ; -> #t
(nset-equal? (lon 1 2 3) (lon 2 1 3)) ; -> #t
(nsubset? (nset 1 2) (nset 1 2 3 4)) ; -> #t
(nadjoin 0 (nset 1 2 3)) ; -> '#,(lon 0 1 2 3)
(nadjoin 2 (nset 1 2 3)) ; -> '#,(lon 0 1 2 3)
(nset 0 1 1 0 2 3 2) ; -> '#,(lon 0 1 2 3)
(ndifference (nset 0 2 1 3) (nset 1 1)) ; -> '#(lon 0 2 3)
(nunion (nset 1 2) (nset 2 3) (nset 3 4))
 ; -> '#(lon 1 2 3 4)
(nintersection (nset 1 2 3 4) (nset 2 3 5) (nset 3 4))
 ; -> '#(lon 3)

(define-list-type lol
                  documentation: lols
                  item-predicate: list?
                  item-equality: equal?
                  procedure-prefix: l)
(lequal?
  (lappend (lol '(a) '(b))
           (lol '(c)))
  (lol '(a) '(b) '(c)))

Requirements

datatype

Last update

Aug 02, 2014

Author

Juergen Lorenz

License

Copyright (c) 2014, Juergen Lorenz
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:

Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.

Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
Neither the name of the author nor the names of its contributors may be
used to endorse or promote products derived from this software without
specific prior written permission. 
  
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

Version History

0.1
initial import