1. Rationale
    1. API
      1. make-sas-callable
      2. callable-sas?
      3. make-ras-callable
      4. callable-ras?
      5. sequence?
      6. sequence-constructors
      7. make-callable
      8. callable?
      9. callable-null?
      10. callable-flat?
      11. callable-length
      12. callable-nil
      13. callable-data
      14. callable-indices
      15. callable-copy
      16. callable-map
      17. callable-for-each
      18. callable-filter
      19. callable-reverse
      20. callable-append
      21. callable-data*
      22. callable-map*
      23. make-callable*
      24. callable-sequences
    2. Examples
  2. Requirements
  3. Last update
  4. Author
  5. License
  6. Version history

Rationale

This is a variant of Mario's callable-datastructures. But contrary to that egg, I don't consider hash-tables, but only ordered sequences. So it makes sense, to define slices. Moreover, I'll consider nested sequences as well.

Central to this module is a generic procedure, sequence-constructors, which stores a local database initially supporting lists, pseudolists, vectors and strings. But this database can be enhanced, by adding generic constructors, make-sas-callable or make-ras-callable for sequential or random access sequences respectively, the former following the list pattern, the latter the vector pattern.

Based on this, the most important procedure is make-callable, which transforms an ordinary into a callable-sequence, i.e. a procedure of zero, one or two arguments. With no argument, this returns i.a. the encapsulated sequence, with one, an index, the value of that sequence at the index and with two a slice between its two index arguments, in either direction, the first included, the second excluded. For convenience, the argument #f is allowed in slices, representing the length.

So, for example, if vec is (make-callable #(0 1 2 3 4 5)), then (vec 1 4) or (vec 4 1) are callable-sequences encapsulating #(1 2 3) or #(4 3 2) respectively, and (vec 3 #f) or (vec #f 3) encapsulate #(3 4 5) or #(5 4) respectively.

API

make-sas-callable

[procedure] (make-sas-callable seq seq-cons seq-car seq-cdr seq-null?)

sequential access constructor with arguments similar to lists

callable-sas?

[procedure] (callable-sas? xpr)

evaluates xpr to a sequential access callable-sequence?

make-ras-callable

[procedure] (make-ras-callable seq make-seq seq-ref seq-set! seq-length)

random access constructor with arguments similar to vectors

callable-ras?

[procedure] (callable-ras? xpr)

evaluates xpr to a random access callable-sequence?

sequence?

[procedure] (sequence? xpr)

evaluates xpr to a sequence type, initially a list, pseudolist, vector or string. To be updated, if new sequence types are added.

sequence-constructors

[procedure] (sequence-constructors)
[procedure] (sequence-constructors seq)
[procedure] (sequence-constructors sym)

the first resets the internal database and the sequence? predicate, the second selects and returns the constructor corresponding to the sequence argument, and the third adds a new sequential-access or random-access constructor, according to the symbol 'sas or 'ras. sequence? is updated as well.

make-callable

[procedure] (make-callable seq)

makes the sequence seq callable

callable?

[procedure] (callable? xpr)

evaluates xpr to a callable sequence

callable-null?

[procedure] (callable-null? clb)

is the callable-sequence clb empty?

callable-flat?

[procedure] (callable-flat? clb)

is the callable sequence clb flat?

callable-length

[procedure] (callable-length clb)

returns the length of the callable sequence clb

callable-nil

[procedure] (callable-nil clb)

returns an empty callable sequence of the same type as clb

callable-data

[procedure] (callable-data clb)

returns the encapsulated sequence of the flat callable-sequence clb

callable-indices

[procedure] (callable-indices ok? clb)

returns the list of indices, k, for which (clb k) passes the ok? test

callable-copy

[procedure] (callable-copy clb)

returns a callable sequence which is a copy of the initial one

callable-map

[procedure] (callable-map fn clb)

maps the callable-sequence, clb, via procedure fn

callable-for-each

[procedure] (callable-for-each fn clb)

executes fn for each item of clb

callable-filter

[procedure] (callable-filter ok? clb)

returns two callable sequences filtering items of clb via ok? or not-ok? respectively

callable-reverse

[procedure] (callable-reverse clb)
[procedure] (callable-reverse clb clb1)

returns a callable sequence which is the reverse of the first argument appended to the second one which defaults to callable-nil, if not given

callable-append

[procedure] (callable-append clb . clbs)

returns the callable sequence appending encapsulated sequences of same type

callable-data*

[procedure] (callable-data* clb)

nested version of callable-data

callable-map*

[procedure] (callable-map* fn clb)

nested version of callable-map, i.e. maps a nested callable-sequence

make-callable*

[procedure] (make-callable* seq)

nested version of make-callable, i.e. creates a nested callable-sequence from a nested ordinary sequence

callable-sequences

[procedure] (callable-sequences)
[procedure] (callable-sequences sym)

with sym: documentation of exported symbol without sym: list of exported symbols

Examples


(import callable-sequences)

(callable-length pls)
;-> 6

(callable-length lst)
;-> 6

(callable-length str)
;-> 6

(callable-length vec)
;-> 6

(callable-null? str)
;-> #f

(callable-flat? vec)
;-> #t

(lst 0)
;-> 0

(lst 3)
;-> 3

(vec 3)
;-> 3

(str 3)
;-> 3

(lst 5)
;-> 5

(condition-case (lst (callable-length lst)) ((exn) #f))
;-> #f

(condition-case (vec (callable-length vec)) ((exn) #f))
;-> #f

(condition-case (str (callable-length str)) ((exn) #f))
;-> #f

(callable-data (lst 2 4))
;-> (quote (2 3))

(callable-data (lst 0 3))
;-> (quote (0 1 2))

(callable-length (lst 0 3))
;-> 3

(callable-data (pls 0 3))
;-> (quote (0 1 2 . 6))

((pls 0 0))
;-> 6

(callable-data (pls 0 0))
;-> 6

(callable-null? (pls 3 3))
;-> #t

(callable-null? (vec 1 2))
;-> #f

(callable-data (pls 3 0))
;-> (quote (3 2 1 . 6))

(callable-data (vec 0 3))
;-> #(0 1 2)

(callable-data (str 0 3))
;-> 012

(callable-data (lst 3 0))
;-> (quote (3 2 1))

(callable-data (vec 3 0))
;-> #(3 2 1)

(callable-data (str 3 0))
;-> 321

(callable-data (pls 0 #f))
;-> (quote (0 1 2 3 4 5 . 6))

(callable-data (pls 0 (callable-length pls)))
;-> (quote (0 1 2 3 4 5 . 6))

(callable-data (lst 0 6))
;-> (quote (0 1 2 3 4 5))

(callable-data (vec 0 #f))
;-> #(0 1 2 3 4 5)

(callable-data (str 0 #f))
;-> 012345

(condition-case (lst 0 7) ((exn) #f))
;-> #f

(condition-case (vec 0 7) ((exn) #f))
;-> #f

(condition-case (str 0 7) ((exn) #f))
;-> #f

(callable-data (lst 0 #f))
;-> (quote (0 1 2 3 4 5))

(callable-data (vec 0 #f))
;-> #(0 1 2 3 4 5)

(callable-data (str 0 #f))
;-> 012345

(callable-data (lst #f -1))
;-> (quote (5 4 3 2 1 0))

(callable-data (lst (- (callable-length lst) 1) -1))
;-> (quote (5 4 3 2 1 0))

(callable-data (callable-reverse lst))
;-> (quote (5 4 3 2 1 0))

(callable-data (vec #f -1))
;-> #(5 4 3 2 1 0)

(callable-data (vec (- (callable-length vec) 1) -1))
;-> #(5 4 3 2 1 0)

(callable-data (vec #f -1))
;-> #(5 4 3 2 1 0)

(callable-data (str #f -1))
;-> 543210

(callable-data (str (- (callable-length str) 1) -1))
;-> 543210

(callable-data (lst 3 1))
;-> (quote (3 2))

(callable-data (vec 3 1))
;-> #(3 2)

(callable-data (str 3 1))
;-> 32

(callable? str)
;-> #t

(callable-sas? lst)
;-> #t

(callable-ras? lst)
;-> #f

(callable? lst)
;-> #t

(callable? vec)
;-> #t

(callable? (lst 1 4))
;-> #t

(callable? (vec 1 4))
;-> #t

(callable-ras? (str 1 4))
;-> #t

(callable-sas? (str 1 4))
;-> #f

(callable? (str 1 4))
;-> #t

(callable? car)
;-> #f

(callable? '(0 1 2 3))
;-> #f

(callable? #(0 1 2 3))
;-> #f

(sequence? #(0 1 2 3))
;-> #t

(callable? "0123")
;-> #f

(sequence? "0123")
;-> #t

(sequence? #f)
;-> #f

(callable? pls)
;-> #t

(callable? '())
;-> #f

(callable-null? vec)
;-> #f

(callable-null? (callable-nil vec))
;-> #t

(callable-flat? vec)
;-> #t

(callable-data (callable-nil vec))
;-> #()

(callable-nil pls)
;-> 6

(callable-data (callable-reverse lst lst))
;-> (quote (5 4 3 2 1 0 0 1 2 3 4 5))

(callable-data (callable-reverse str str))
;-> 543210012345

(callable-data (callable-reverse str))
;-> 543210

(callable-indices even? vec)
;-> (quote (0 2 4))

(callable-indices odd? pls)
;-> (quote (1 3 5))

(callable-data (callable-copy lst))
;-> (quote (0 1 2 3 4 5))

(callable-data (callable-copy vec))
;-> #(0 1 2 3 4 5)

(callable-data (callable-map add1 vec))
;-> #(1 2 3 4 5 6)

(callable-data (callable-map add1 pls))
;-> (quote (1 2 3 4 5 6 . 6))

(callable-for-each print vec)
;-> (if #f #f)

(callable-data (callable-filter odd? vec))
;-> #(1 3 5)

(receive (yes no) (callable-filter odd? vec) (list (yes) (no)))
;-> (quote (#(1 3 5) #(0 2 4)))

(callable-data (callable-append str str str))
;-> 012345012345012345

(callable-data (callable-append str str str str))
;-> 012345012345012345012345

(callable-data* pl*)
;-> (quote (a (b . c)))

(callable-data* lv**)
;-> (quote (a (b #(c d) e) f))

(callable-data* ns**)
;-> (quote (0 (1 #(2) 3) 4))

(callable-data* (callable-map* add1 ns**))
;-> (quote (1 (2 #(3) 4) 5))

(ls* 0)
;-> (quote a)

((ls* 1) 1)
;-> (quote c)

(callable-data ((ls* 1) 2 #f))
;-> (quote ())

(callable? ((ls* 1) 1 2))
;-> #t

(callable-data ((ls* 1) 1 2))
;-> (quote (c))

(callable? pl*)
;-> #t

(callable-data (pl* 1))
;-> (quote (b . c))

(callable? (pl* 1))
;-> #t

((pl* 1) 0)
;-> (quote b)

(callable? ((pl* 1) 1 #f))
;-> #t

(((pl* 1) 1 #f))
;-> (quote c)

(callable-data ((pl* 1) 1 #f))
;-> (quote c)

((lv* 1) 1)
;-> (quote c)

(callable-data ((lv* 1) 1 2))
;-> #(c)

((vp* 1) 0)
;-> (quote b)

(callable? (vp* 1))
;-> #t

(callable? ((vp* 1) 1 #f))
;-> #t

(((vp* 1) 1 #f))
;-> (quote c)

(callable-data ((vp* 1) 1 #f))
;-> (quote c)

((vs* 1) 0)
;-> b

((vs* 1) 1)
;-> c

(callable-data ((vs* 1) 2 #f))
;-> 

(lv** 0)
;-> (quote a)

((lv** 1) 0)
;-> (quote b)

(((lv** 1) 1) 0)
;-> (quote c)

(((lv** 1) 1) 1)
;-> (quote d)

(lv** 2)
;-> (quote f)

((lv** 1) 2)
;-> (quote e)

;; add a new sequence type, arrays
(import arrays)

((sequence-constructors 'ras)
 array?
 (lambda (k)
   (apply array
          (let loop ((i 0) (result '()))
            (if (= i k) result (loop (+ i 1) (cons #f result))))))
 (lambda (arr k) (array-at k arr))
 (lambda (arr k new) (array-update! k new arr))
 array-length)
;-> (if #f #f)

(sequence? (make-array))
;-> #t

(set! arr (make-callable (array 0 1 2 3)))
;-> (if #f #f)

(arr 2)
;-> 2

(array-equal? (callable-data (arr 1 3)) (array 1 2))
;-> #t

(array-equal? (callable-data (arr 3 #f)) (array 3))
;-> #t

(array-equal? (callable-data (arr 3 1)) (array 3 2))
;-> #t

(set! va* (make-callable* (vector 0 (array 1 2 3))))
;-> (if #f #f)

(set! mva* (callable-map* add1 va*))
;-> (if #f #f)

(mva* 0)
;-> 1

((mva* 1) 0)
;-> 2

(array-equal? (callable-data (mva* 1)) (array 2 3 4))
;-> #t

(sequence-constructors)
;-> (if #f #f)

(sequence? (make-array))
;-> #f

Requirements

None

Last update

Sep 3, 2020

Author

Juergen Lorenz

License

Copyright (c) 2020 , Juergen Lorenz, ju (at) jugilo (dot) de 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

1.2
some sequence operations added
1.1
make-callable* added, a recursive version of make-callable
1.0.0
initial version