1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798 |
- (library (list-helpers)
- (export remove-consecutive-duplicates
- take-indices
- take-range
- unique)
- (import (except (rnrs base) error)
- (only (guile)
- lambda* λ
- sort)
- ;; lists
- (srfi srfi-1)
- ;; function contracts
- (contract)
- (ice-9 exceptions))
- (define-with-contract remove-consecutive-duplicates
- (require (pair? lst)
- (procedure? eq-test))
- (ensure (pair? <?>))
- (lambda* (lst #:key (eq-test eq?))
- "Remove consecutive duplicates with regards to EQ-TEST from LST."
- (cons (car lst)
- (let iter ([lst° (cdr lst)] [prev (car lst)])
- (cond
- [(null? lst°) '()]
- [(eq-test (car lst°) prev)
- (iter (cdr lst°) prev)]
- [else
- (cons (car lst°)
- (iter (cdr lst°)
- (car lst°)))])))))
- (define-with-contract unique
- (require (pair? lst)
- (procedure? less))
- (ensure (pair? lst))
- (lambda* (lst #:key (eq-test eq?) (less <))
- "Return a list of unique elements of LST. Depends on LESS being
- suitable to compare elements of LST to sort LST, before duplicates are
- removed from it. EQ-TEST can be specified to check, whether elements
- are equal."
- (remove-consecutive-duplicates (sort lst less)
- #:eq-test eq-test)))
- (define-with-contract take-indices
- (require (>= (car indices) 0)
- (integer? (car indices)))
- (ensure (or (null? <?>)
- (pair? <?>)))
- (λ (lst indices)
- "Take elements at the indices INDICES from LST and return them as a
- new list."
- (let iter ([lst° lst]
- [indices° (unique indices #:eq-test = #:less <)]
- [index° 0])
- (cond
- [(null? indices°) '()]
- [(= (car indices°) index°)
- (cons (car lst°)
- (iter (cdr lst°)
- (cdr indices°)
- (+ index° 1)))]
- [else
- (iter (cdr lst°)
- indices°
- (+ index° 1))]))))
- (define-with-contract take-range
- (require (integer? start)
- (integer? end)
- (>= start 0)
- (<= start end)
- (or (null? lst)
- (pair? lst)))
- (ensure (or (null? <?>)
- (pair? <?>)))
- (λ (lst start end)
- "Take a range of elements from LST. The range starts at index START
- and ends at index END."
- (let iter ([lst° lst] [index° 0])
- (cond
- [(null? lst) '()]
- [(= index° start)
- (guard (con [(eq? (exception-kind con) 'wrong-type-arg)
- (raise-exception
- (make-exception
- (make-exception-with-message "out of bounds index")
- (make-exception-with-irritants (list lst start end))
- (make-exception-with-origin 'take-range)))])
- (take lst° (+ (- end start) 1)))]
- [else
- (iter (cdr lst°)
- (+ index° 1))])))))
|