aboutsummaryrefslogtreecommitdiff
path: root/module/c/zipper.scm
blob: 65cea2110b42e175d2fae8b7b7c24f600c16c535 (plain)
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
;;; Commentary:
;; Zipper data structure. Could be moved to (hnh util), but would then need to
;; be at least slightly more thorough.
;;; Code:

(define-module (c zipper)
  :use-module (srfi srfi-88)
  :use-module (hnh util object)
  :export (list-zipper
           list-zipper?
           left focused right
           zip-left
           zip-right
           zip-find-right
           list->zipper
           zipper->list
           rezip))

(define-type (list-zipper)
  (left type: list?)
  focused
  (right type: list?))

;; Move zipper one step to the left
(define (zip-left zipper)
  (if (null? (left zipper))
      zipper
      (list-zipper left: (cdr (left zipper))
                   right: (cons (focused zipper) (right zipper))
                   focused: (car (left zipper)))))

;; Move zipper one step to the right
(define (zip-right zipper)
  (if (null? (right zipper))
      zipper
      (list-zipper left: (cons (focused zipper) (left zipper))
                   right: (cdr (right zipper))
                   focused: (car (right zipper)))))

;; find first element matching predicate, going right
(define (zip-find-right predicate zipper)
  (cond ((null? (right zipper)) zipper)
        ((predicate (focused zipper)) zipper)
        (else (zip-find-right predicate (zip-right zipper)))))

(define (list->zipper list)
  (list-zipper left: '()
               focused: (car list)
               right: (cdr list)))


(define (rezip zipper)
  (if (null? (left zipper))
      zipper
      (rezip (zip-left zipper))))

(define (zipper->list zipper)
  (let ((z (rezip zipper)))
    (cons (focused z)
          (right z))))