• egg

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

returnstwo 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-collect

[syntax] (callable-collect item-xpr (var clb ok-xpr ...))
[syntax] (callable-collect item-xpr (var clb ok-xpr ...) (var1 clb1 ok-xpr1 ...) ...)

creates a new callable-sequence by binding var to each element of the callable-sequence clb in sequence, and if it passes the checks, ok-xpr ..., inserts the value of xpr into the resulting pseudolist. The qualifieres, (var clb ok-xpr ...), are processed sequentially from left to right, so that filters of a qualifier have access to the variables of qualifiers to its left.

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

((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

(newline)

(newline)

((callable-collect (add1 x) (x (make-callable '(0 1 2 3)))))
;-> (quote (1 2 3 4))

((callable-collect (add1 x) (x (make-callable '(0 1 2 3)))))
;-> (quote (1 2 3 4))

((callable-collect x (x (make-callable '(0 1 2 3 4 5)) (odd? x))))
;-> (quote (1 3 5))

((callable-collect x (x (make-callable '(0 1 2 3 4 5)) (odd? x))))
;-> (quote (1 3 5))

((callable-collect
(* 10 n)
(n (make-callable '(0 1 2 3 4 5)) (positive? n) (even? n))))
;-> (quote (20 40))

((callable-collect
(list c k)
(c (make-callable '(A B C)))
(k (make-callable '(1 2 3 4)))))
;-> (quote ((A 1) (A 2) (A 3) (A 4) (B 1) (B 2) (B 3) (B 4) (C 1) (C 2) (C 3) (C 4)))

(collect?)
```

None

Jan 22, 2021

Juergen Lorenz

## Repository

This egg is hosted on the CHICKEN Subversion repository:

https://anonymous@code.call-cc.org/svn/chicken-eggs/release/5/callable-sequences

If you want to check out the source code repository of this egg and you are not familiar with Subversion, see this page.

Copyright (c) 2020-2021 , 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.

1.3