mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-04-30 03:40:34 +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:
parent
aa44035ee8
commit
03d4a3b5df
3 changed files with 47 additions and 32 deletions
|
@ -772,37 +772,6 @@ SCM_DEFINE (scm_srfi1_partition_x, "partition!", 2, 0, 0,
|
|||
}
|
||||
#undef FUNC_NAME
|
||||
|
||||
SCM_DEFINE (scm_srfi1_remove, "remove", 2, 0, 0,
|
||||
(SCM pred, SCM list),
|
||||
"Return a list containing all elements from @var{list} which do\n"
|
||||
"not satisfy the predicate @var{pred}. The elements in the\n"
|
||||
"result list have the same order as in @var{list}. The order in\n"
|
||||
"which @var{pred} is applied to the list elements is not\n"
|
||||
"specified.")
|
||||
#define FUNC_NAME s_scm_srfi1_remove
|
||||
{
|
||||
SCM walk;
|
||||
SCM *prev;
|
||||
SCM res = SCM_EOL;
|
||||
SCM_VALIDATE_PROC (SCM_ARG1, pred);
|
||||
SCM_VALIDATE_LIST (2, list);
|
||||
|
||||
for (prev = &res, walk = list;
|
||||
scm_is_pair (walk);
|
||||
walk = SCM_CDR (walk))
|
||||
{
|
||||
if (scm_is_false (scm_call_1 (pred, SCM_CAR (walk))))
|
||||
{
|
||||
*prev = scm_cons (SCM_CAR (walk), SCM_EOL);
|
||||
prev = SCM_CDRLOC (*prev);
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
#undef FUNC_NAME
|
||||
|
||||
|
||||
SCM_DEFINE (scm_srfi1_remove_x, "remove!", 2, 0, 0,
|
||||
(SCM pred, SCM list),
|
||||
"Return a list containing all elements from @var{list} which do\n"
|
||||
|
|
|
@ -37,7 +37,6 @@ SCM_INTERNAL SCM scm_srfi1_length_plus (SCM lst);
|
|||
SCM_INTERNAL SCM scm_srfi1_lset_difference_x (SCM equal, SCM lst, SCM rest);
|
||||
SCM_INTERNAL SCM scm_srfi1_partition (SCM pred, SCM list);
|
||||
SCM_INTERNAL SCM scm_srfi1_partition_x (SCM pred, SCM list);
|
||||
SCM_INTERNAL SCM scm_srfi1_remove (SCM pred, SCM list);
|
||||
SCM_INTERNAL SCM scm_srfi1_remove_x (SCM pred, SCM list);
|
||||
|
||||
SCM_INTERNAL void scm_register_srfi_1 (void);
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue