You are looking at historical revision 31195 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 two types, typed lists and typed sets (the latter being implemented as equivalence classes of the former), as well as a long list of functions, which are all prefixed with the prefix of the list type.
Moreover, a documentation procedure is generated, whose name can be supplied as a keyword parameter to define-list-type, it defaults to the plural form of the list type name. Called as a thunk, this procedure shows the list of generated functions, called with one of those functions' name, it shows its signature.
Two obligatory keyword parameters must be supplied, the item-predicate and the item-equality procedures.
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
[syntax] (define-list-type name [documentation: docu] item-predicate: ok? item-equality: equ?)defines a new list type, name, usually a combination of a prefix and the symbol list, whose items must pass the ok? predicate and are compared by equ?, and a documentation procedure, docu, which defaults to the plural of name. Exports two types and a long list of functions, all prefixed by the prefix of name. The list of generated functions is shown by a call to docu without arguments, the signature of such a function by the call (docu 'function).
For example, the call
(define-list-tye numlist item-predicate: number? item-equality: =)
generates the two types numlist and numset with type predicates numlist? and numset? respectively, a documentation procedure numlists and a bag of procedures all prefixed with num, most of them prefixed versions of standard list procedures, but 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 nlist 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))))) (define nnil (nnull)) (nlist? nnil) ; -> #t (nnull? nnil) ; -> #t (null? nnil) ; -> #f (define nls (ncons 1 nnil)) (nlist? nls) ; -> #t (define nlst (nlist 0 1 (cell 2) 3 4)) (nlist? nlst) ; -> #t (list? nlst) ; -> #f (napply + 1 2 (nlist 3 4 5)) ; ->15 (nrepeat 5 0) ; -> '(0 0 0 0 0) (nequal? (niterate-times 5 add1 0) (nlist 0 1 2 3 4)) ; -> #t (niterate-while (lambda (x) (< x 5)) add1 0) ; -> '(0 1 2 3 4)) (niterate-until (lambda (x) (= x 5)) add1 0) ; -> '(0 1 2 3 4) (nzip (nlist 1 2 3 4 5) (nlist 10 20 30)) ; -> '(1 10 2 20 3 30 4 5) (ninterpose 10 (nlist 1 2 3 4 5)) ; -> '(1 10 2 10 3 10 4 10 5) (ncdddr nlst) ; -> '(3 4) (ncadddr nlst) ; -> 3 (nequal? (ndrop 3 nlst) (nlist 3 4)) ; -> #t (nequal? (ndrop-while odd? (nlist 1 3 2 4 5)) (nlist 2 4 5)) ; -> #t (nequal? (ntake-while odd? (nlist 1 3 2 4 5)) (nlist 1 3)) ; -> #t (receive (head tail) (nsplit-with even? (nlist 1 3 2 4 5)) (and (nequal? head (nlist 1 3)) (nequal? tail (nlist 2 4 5)))) ; -> #t (ntake 2 nlst) ; -> '(0 1) (nlist? (nnull)) ; -> #t (nnull? (nnull)) ; -> #t (nnull? nls) ; -> #f (nlist? '(1 2)) ; -> #f (nnull? (ncdr nls)) ; -> #t (ncar nlst) ; -> 0 (nlist? (nreverse nlst)) ; -> #t (nreverse nlst) '(4 3 !2! 1 0) (equal? (nlist->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) (nlist (cell 20) 3)) ; -> #t (nequal? (nappend (nlist 0 1 2 3) (nlist 4 5 6)) (nlist 0 1 2 3 4 5 6)) ; -> #t (nequal? (nappend (nlist 0) (nlist 1) (nlist 2) (nlist 3 4) (nlist 5 6 7) (nlist 8)) (nlist 0 1 2 3 4 5 6 7 8)) ; -> #t (nequal? (nmap add1 (nlist 0 1 2 3)) (nlist 1 2 3 4)) ; -> #t (nequal? (nmap + (nlist 1 2 3) (nlist 10 20 30 40)) (nlist 11 22 33)) ; -> #t (nfold-right ncons (nnull) (nlist 0 1 2 3 4)) ; -> '(0 1 2 3 4)) (nfold-left + 0 (nlist 1 2 3) (nlist 10 20 30)) ; -> 66 (nfold-left cons '(100) (nlist 1 2 3 4)) ; -> '(((((100) . 1) . 2) . 3) . 4) (equal? (call-with-values (lambda () (nreverse* (nlist 1 2 3) (nlist 10 20 30))) list) (list (nlist 3 2 1) (nlist 30 20 10))) ; -> #t (nremove 0 (nlist 1 0 2 0 3 0 4)) ; -> '(1 2 3 4) (nmerge < (nlist 2 4 5 7 8) (nlist 1 3 6 9 10)) ; -> '(1 2 3 4 5 6 7 8 9 10)) (condition-case (nmerge < (nnull) (nlist 1 3 2)) ((exn) #f)) ; -> #f (nequal? (nsort <= (nlist 2 0 1 4 3)) (nlist 0 1 2 3 4)) (not (nsorted? <= (nlist 2 0 1 4 3))) (nsorted? <= (nlist 0 1 2 3 4)) (nevery? odd? (nlist 1 3 5)) ; -> #t (nevery? odd? (nlist)) ; -> #t (nsome odd? (nlist 2 3 5)) ; -> 3 (nsome odd? (nlist 2 4 6)) ; -> #f (nnot-every? odd? (nlist 1 2 3)) ; -> #t (nnot-any? odd? (nlist 2 4 6)) ; -> #t (nlist->set (nlist 1 2 1 3 2 3)) ; -> '{1 2 3} (nlist? (nlist 1 2 3)) ; -> #t (nset? (nlist 1 2 3)) ; -> #f (nset? (nset 1 2 2 3)) ; -> #t (nset-in? 2 (nset 1 2 3)) ; -> #t (nsubset? (nset 2 1 2) (nset 1 2 3 4)) ; -> #t (nset-equal? (nset 1 2 3) (nset 2 1 3)) ; -> #t (nsubset? (nset 1 2) (nset 1 2 3 4)) ; -> #t (nset-add 0 (nset 1 2 3)) ; -> '{0 1 2 3} (nset-add 2 (nset 1 2 3)) ; -> '{1 2 3} (nset 0 1 1 0 2 3 2) ; -> '{0 1 2 3} (nset-difference (nset 0 2 1 3) (nset 1 1)) ; -> '{0 2 3} (nset-union (nset 1 2) (nset 2 3) (nset 3 4)) ; -> '{1 2 3 4} (nset-intersection (nset 1 2 3 4) (nset 2 3 5) (nset 3 4)) ; -> '{3} (nsubset odd? (nset 1 2 2 1 3 4)) ; -> '{1 3} (define-list-type llist item-predicate: list? item-equality: equal?) (lequal? (lappend (llist '(a) '(b)) (llist '(c))) (llist '(a) '(b) '(c)))
Requirements
datatype
Last update
Aug 03, 2014
Author
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