1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-06-15 08:10:17 +02:00

srfi-1 remove: move from C to Scheme

The Scheme implementation is an adapted version of the approach used by
delete-duplicates, which allows sharing any common tail.

* libguile/srfi-1.c (scm_srfi1_remove): delete.
* libguile/srfi-1.h (scm_srfi1_remove): delete.
* module/srfi/srfi-1.scm: add remove.
This commit is contained in:
Rob Browning 2024-07-20 15:53:00 -05:00
parent aa44035ee8
commit 03d4a3b5df
3 changed files with 47 additions and 32 deletions

View file

@ -735,6 +735,53 @@ the list returned."
(apply f l)
(lp (map cdr l)))))))
;;; Filtering & partitioning
(define (list-prefix-and-tail lst stop)
(when (eq? lst stop)
(error "Prefix cannot be empty"))
(let ((rl (list (car lst))))
(let lp ((lst (cdr lst)) (tail rl))
(if (eq? lst stop)
(values rl tail)
(let ((new-tail (list (car lst))))
(set-cdr! tail new-tail)
(lp (cdr lst) new-tail))))))
(define (remove pred lst)
"Return a list containing all elements from @var{list} which do not
satisfy the predicate @var{pred}. The elements in the result list have
the same order as in @var{list}. The order in which @var{pred} is
applied to the list elements is not specified, and the result may share
a common tail with @{list}."
;; Traverse the lst, keeping the tail of it, in which we have yet to
;; find a duplicate, in last-kept. Share that tail with the result
;; (possibly the entire original lst). Build the result by
;; destructively appending unique values to its tail, and henever we
;; find a duplicate, copy the pending last-kept prefix into the result
;; and move last-kept forward to the current position in lst.
(if (null? lst)
lst
(let ((result (list #f)))
(let lp ((lst lst)
(last-kept lst)
(tail result))
(if (null? lst)
(begin
(set-cdr! tail last-kept)
(cdr result))
(let ((item (car lst)))
(if (pred item)
(if (eq? last-kept lst)
(lp (cdr lst) (cdr lst) tail)
(call-with-values
(lambda () (list-prefix-and-tail last-kept lst))
(lambda (prefix new-tail)
(set-cdr! tail prefix)
(lp (cdr lst) (cdr lst) new-tail))))
(lp (cdr lst) last-kept tail))))))))
;;; Searching