aboutsummaryrefslogtreecommitdiffstats
path: root/mcgoron.iterator.list.scm
blob: 3638614c7ebef33ed03ae6903adeb54a736f5b43 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
#| Copyright 2024 Peter McGoron
 |
 | Licensed under the Apache License, Version 2.0 (the "License");
 | you may not use this file except in compliance with the License.
 | You may obtain a copy of the License at
 |
 |     http://www.apache.org/licenses/LICENSE-2.0
 |
 | Unless required by applicable law or agreed to in writing, software
 | distributed under the License is distributed on an "AS IS" BASIS,
 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | See the License for the specific language governing permissions and
 | limitations under the License.
 |-------------------------------------------------------------------------
 | This is a list iterator that allows for mutation of the list.
 |
 | The list iterator is made up of
 | * the `signifier`: the head of the list.
 | * the `previous` values, which is a list of all cons cells prior to the
 |   current cons cell, in reverse.
 | * the index, which is the index of the current element in the list. This
 |   is updated internally but not used internally, so the root index does
 |   not have to be 0.
 | * the `next` list, which is either empty or has as it's car the current
 |   item.
 |#

(define (make-list-iterator signifier previous idx rest)
  (when (not (or (pair? rest) (null? rest)))
    (raise (improper-list-exception idx rest)))
  (make-iterator
   (lambda () (null? previous))
   (lambda () (null? rest))
   (lambda (num)
     (cond
       ((not (integer?))
        (raise (non-integer-movement-exception spaces)))
       ((negative? num)
        (let loop ((cntr (- num))
                   (previous previous)
                   (rest rest))
          (cond
            ((= num 0) (make-list-iterator signifier
                                           previous
                                           (+ total num)
                                           rest))
            ((null? previous) #f)
            (else (loop (- cntr 1)
                        (cdr previous)
                        (car previous))))))
       (else
        (let loop ((cntr num)
                   (previous previous)
                   (rest rest))
          (cond
            ((= num 0) (make-list-iterator signifier
                                           previous
                                           (+ total num)
                                           rest))
            ((null? rest) #f)
            (else (loop (- 1 num)
                        (cons rest previous)
                        (cdr rest))))))))
   (lambda ()
     (if (null? rest)
         (error "cannot ref end of list" previous rest)
         (car rest)))
   (lambda (predicate? other-iterators)
     (let ((cmp (make-default-comparator)))
       (iteratively-apply-predicate
        (lambda (x y)
          (predicate? cmp (get-private x) (get-private y)))
        idx
        other-iterators)))
   idx))

(define (list-iterator-start rest)
  (make-list-iterator rest '() 0 rest))

(define (list-iterator-to-end itr)
  (if (iterator-end? itr)
      itr
      (list-iterator-to-end (iterator-advance itr 1))))

(define (list-iterator-end lst)
  (list-iterator-to-end (list-iterator-start lst)))