Merge from emacs-24 branch; up to 2012-05-01T10:20:43Z!rgm@gnu.org
[bpt/emacs.git] / lisp / emacs-lisp / cl-seq.el
CommitLineData
bb3faf5b 1;;; cl-seq.el --- Common Lisp features, part 3 -*- lexical-binding: t -*-
fcd73769 2
acaf905b 3;; Copyright (C) 1993, 2001-2012 Free Software Foundation, Inc.
fcd73769
RS
4
5;; Author: Dave Gillespie <daveg@synaptics.com>
6;; Version: 2.02
7;; Keywords: extensions
bd78fa1d 8;; Package: emacs
fcd73769
RS
9
10;; This file is part of GNU Emacs.
11
d6cba7ae 12;; GNU Emacs is free software: you can redistribute it and/or modify
fcd73769 13;; it under the terms of the GNU General Public License as published by
d6cba7ae
GM
14;; the Free Software Foundation, either version 3 of the License, or
15;; (at your option) any later version.
fcd73769
RS
16
17;; GNU Emacs is distributed in the hope that it will be useful,
18;; but WITHOUT ANY WARRANTY; without even the implied warranty of
19;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20;; GNU General Public License for more details.
21
22;; You should have received a copy of the GNU General Public License
d6cba7ae 23;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
fcd73769 24
07b3798c 25;;; Commentary:
fcd73769
RS
26
27;; These are extensions to Emacs Lisp that provide a degree of
28;; Common Lisp compatibility, beyond what is already built-in
29;; in Emacs Lisp.
30;;
31;; This package was written by Dave Gillespie; it is a complete
32;; rewrite of Cesar Quiroz's original cl.el package of December 1986.
33;;
fcd73769
RS
34;; Bug reports, comments, and suggestions are welcome!
35
36;; This file contains the Common Lisp sequence and list functions
37;; which take keyword arguments.
38
39;; See cl.el for Change Log.
40
41
07b3798c 42;;; Code:
fcd73769 43
7c1898a7 44(require 'cl-lib)
fcd73769 45
bb3faf5b
SM
46;; Keyword parsing.
47;; This is special-cased here so that we can compile
48;; this file independent from cl-macs.
fcd73769 49
bb3faf5b 50(defmacro cl--parsing-keywords (kwords other-keys &rest body)
f291fe60 51 (declare (indent 2) (debug (sexp sexp &rest form)))
bb3faf5b
SM
52 `(let* ,(mapcar
53 (lambda (x)
54 (let* ((var (if (consp x) (car x) x))
55 (mem `(car (cdr (memq ',var cl-keys)))))
56 (if (eq var :test-not)
57 (setq mem `(and ,mem (setq cl-test ,mem) t)))
58 (if (eq var :if-not)
59 (setq mem `(and ,mem (setq cl-if ,mem) t)))
60 (list (intern
61 (format "cl-%s" (substring (symbol-name var) 1)))
62 (if (consp x) `(or ,mem ,(car (cdr x))) mem))))
63 kwords)
64 ,@(append
65 (and (not (eq other-keys t))
66 (list
67 (list 'let '((cl-keys-temp cl-keys))
68 (list 'while 'cl-keys-temp
69 (list 'or (list 'memq '(car cl-keys-temp)
70 (list 'quote
71 (mapcar
72 (function
73 (lambda (x)
74 (if (consp x)
75 (car x) x)))
76 (append kwords
77 other-keys))))
78 '(car (cdr (memq (quote :allow-other-keys)
79 cl-keys)))
80 '(error "Bad keyword argument %s"
81 (car cl-keys-temp)))
82 '(setq cl-keys-temp (cdr (cdr cl-keys-temp)))))))
83 body)))
84
85(defmacro cl--check-key (x) ;Expects `cl-key' in context of generated code.
f291fe60 86 (declare (debug edebug-forms))
bb3faf5b 87 `(if cl-key (funcall cl-key ,x) ,x))
fcd73769 88
bb3faf5b 89(defmacro cl--check-test-nokey (item x) ;cl-test cl-if cl-test-not cl-if-not.
f291fe60 90 (declare (debug edebug-forms))
bb3faf5b
SM
91 `(cond
92 (cl-test (eq (not (funcall cl-test ,item ,x))
93 cl-test-not))
94 (cl-if (eq (not (funcall cl-if ,x)) cl-if-not))
95 (t (eql ,item ,x))))
96
97(defmacro cl--check-test (item x) ;all of the above.
f291fe60 98 (declare (debug edebug-forms))
bb3faf5b 99 `(cl--check-test-nokey ,item (cl--check-key ,x)))
fcd73769 100
bb3faf5b 101(defmacro cl--check-match (x y) ;cl-key cl-test cl-test-not
f291fe60 102 (declare (debug edebug-forms))
bb3faf5b
SM
103 (setq x `(cl--check-key ,x) y `(cl--check-key ,y))
104 `(if cl-test
105 (eq (not (funcall cl-test ,x ,y)) cl-test-not)
106 (eql ,x ,y)))
fcd73769 107
fcd73769
RS
108(defvar cl-test) (defvar cl-test-not)
109(defvar cl-if) (defvar cl-if-not)
110(defvar cl-key)
111
323698cc 112;;;###autoload
7c1898a7 113(defun cl-reduce (cl-func cl-seq &rest cl-keys)
47bc4b3f
JB
114 "Reduce two-argument FUNCTION across SEQ.
115\nKeywords supported: :start :end :from-end :initial-value :key
116\n(fn FUNCTION SEQ [KEYWORD VALUE]...)"
bb3faf5b 117 (cl--parsing-keywords (:from-end (:start 0) :end :initial-value :key) ()
fcd73769 118 (or (listp cl-seq) (setq cl-seq (append cl-seq nil)))
7c1898a7 119 (setq cl-seq (cl-subseq cl-seq cl-start cl-end))
fcd73769 120 (if cl-from-end (setq cl-seq (nreverse cl-seq)))
64a4c526 121 (let ((cl-accum (cond ((memq :initial-value cl-keys) cl-initial-value)
bb3faf5b 122 (cl-seq (cl--check-key (pop cl-seq)))
fcd73769
RS
123 (t (funcall cl-func)))))
124 (if cl-from-end
125 (while cl-seq
bb3faf5b 126 (setq cl-accum (funcall cl-func (cl--check-key (pop cl-seq))
fcd73769
RS
127 cl-accum)))
128 (while cl-seq
129 (setq cl-accum (funcall cl-func cl-accum
bb3faf5b 130 (cl--check-key (pop cl-seq))))))
fcd73769
RS
131 cl-accum)))
132
323698cc 133;;;###autoload
7c1898a7 134(defun cl-fill (seq item &rest cl-keys)
fcd73769 135 "Fill the elements of SEQ with ITEM.
47bc4b3f
JB
136\nKeywords supported: :start :end
137\n(fn SEQ ITEM [KEYWORD VALUE]...)"
bb3faf5b 138 (cl--parsing-keywords ((:start 0) :end) ()
fcd73769
RS
139 (if (listp seq)
140 (let ((p (nthcdr cl-start seq))
141 (n (if cl-end (- cl-end cl-start) 8000000)))
142 (while (and p (>= (setq n (1- n)) 0))
143 (setcar p item)
144 (setq p (cdr p))))
145 (or cl-end (setq cl-end (length seq)))
146 (if (and (= cl-start 0) (= cl-end (length seq)))
147 (fillarray seq item)
148 (while (< cl-start cl-end)
149 (aset seq cl-start item)
150 (setq cl-start (1+ cl-start)))))
151 seq))
152
323698cc 153;;;###autoload
7c1898a7 154(defun cl-replace (cl-seq1 cl-seq2 &rest cl-keys)
fcd73769
RS
155 "Replace the elements of SEQ1 with the elements of SEQ2.
156SEQ1 is destructively modified, then returned.
47bc4b3f
JB
157\nKeywords supported: :start1 :end1 :start2 :end2
158\n(fn SEQ1 SEQ2 [KEYWORD VALUE]...)"
bb3faf5b 159 (cl--parsing-keywords ((:start1 0) :end1 (:start2 0) :end2) ()
fcd73769
RS
160 (if (and (eq cl-seq1 cl-seq2) (<= cl-start2 cl-start1))
161 (or (= cl-start1 cl-start2)
162 (let* ((cl-len (length cl-seq1))
163 (cl-n (min (- (or cl-end1 cl-len) cl-start1)
164 (- (or cl-end2 cl-len) cl-start2))))
165 (while (>= (setq cl-n (1- cl-n)) 0)
bb3faf5b 166 (cl--set-elt cl-seq1 (+ cl-start1 cl-n)
fcd73769
RS
167 (elt cl-seq2 (+ cl-start2 cl-n))))))
168 (if (listp cl-seq1)
169 (let ((cl-p1 (nthcdr cl-start1 cl-seq1))
170 (cl-n1 (if cl-end1 (- cl-end1 cl-start1) 4000000)))
171 (if (listp cl-seq2)
172 (let ((cl-p2 (nthcdr cl-start2 cl-seq2))
173 (cl-n (min cl-n1
174 (if cl-end2 (- cl-end2 cl-start2) 4000000))))
175 (while (and cl-p1 cl-p2 (>= (setq cl-n (1- cl-n)) 0))
176 (setcar cl-p1 (car cl-p2))
177 (setq cl-p1 (cdr cl-p1) cl-p2 (cdr cl-p2))))
178 (setq cl-end2 (min (or cl-end2 (length cl-seq2))
179 (+ cl-start2 cl-n1)))
180 (while (and cl-p1 (< cl-start2 cl-end2))
181 (setcar cl-p1 (aref cl-seq2 cl-start2))
182 (setq cl-p1 (cdr cl-p1) cl-start2 (1+ cl-start2)))))
183 (setq cl-end1 (min (or cl-end1 (length cl-seq1))
184 (+ cl-start1 (- (or cl-end2 (length cl-seq2))
185 cl-start2))))
186 (if (listp cl-seq2)
187 (let ((cl-p2 (nthcdr cl-start2 cl-seq2)))
188 (while (< cl-start1 cl-end1)
189 (aset cl-seq1 cl-start1 (car cl-p2))
190 (setq cl-p2 (cdr cl-p2) cl-start1 (1+ cl-start1))))
191 (while (< cl-start1 cl-end1)
192 (aset cl-seq1 cl-start1 (aref cl-seq2 cl-start2))
193 (setq cl-start2 (1+ cl-start2) cl-start1 (1+ cl-start1))))))
194 cl-seq1))
195
323698cc 196;;;###autoload
7c1898a7 197(defun cl-remove (cl-item cl-seq &rest cl-keys)
fcd73769
RS
198 "Remove all occurrences of ITEM in SEQ.
199This is a non-destructive function; it makes a copy of SEQ if necessary
200to avoid corrupting the original SEQ.
47bc4b3f
JB
201\nKeywords supported: :test :test-not :key :count :start :end :from-end
202\n(fn ITEM SEQ [KEYWORD VALUE]...)"
bb3faf5b 203 (cl--parsing-keywords (:test :test-not :key :if :if-not :count :from-end
fcd73769
RS
204 (:start 0) :end) ()
205 (if (<= (or cl-count (setq cl-count 8000000)) 0)
206 cl-seq
207 (if (or (nlistp cl-seq) (and cl-from-end (< cl-count 4000000)))
4735906a
SM
208 (let ((cl-i (cl--position cl-item cl-seq cl-start cl-end
209 cl-from-end)))
fcd73769 210 (if cl-i
7c1898a7 211 (let ((cl-res (apply 'cl-delete cl-item (append cl-seq nil)
fcd73769 212 (append (if cl-from-end
64a4c526
DL
213 (list :end (1+ cl-i))
214 (list :start cl-i))
fcd73769
RS
215 cl-keys))))
216 (if (listp cl-seq) cl-res
217 (if (stringp cl-seq) (concat cl-res) (vconcat cl-res))))
218 cl-seq))
219 (setq cl-end (- (or cl-end 8000000) cl-start))
220 (if (= cl-start 0)
221 (while (and cl-seq (> cl-end 0)
bb3faf5b 222 (cl--check-test cl-item (car cl-seq))
fcd73769
RS
223 (setq cl-end (1- cl-end) cl-seq (cdr cl-seq))
224 (> (setq cl-count (1- cl-count)) 0))))
225 (if (and (> cl-count 0) (> cl-end 0))
226 (let ((cl-p (if (> cl-start 0) (nthcdr cl-start cl-seq)
227 (setq cl-end (1- cl-end)) (cdr cl-seq))))
228 (while (and cl-p (> cl-end 0)
bb3faf5b 229 (not (cl--check-test cl-item (car cl-p))))
fcd73769
RS
230 (setq cl-p (cdr cl-p) cl-end (1- cl-end)))
231 (if (and cl-p (> cl-end 0))
7c1898a7 232 (nconc (cl-ldiff cl-seq cl-p)
fcd73769
RS
233 (if (= cl-count 1) (cdr cl-p)
234 (and (cdr cl-p)
7c1898a7 235 (apply 'cl-delete cl-item
fcd73769 236 (copy-sequence (cdr cl-p))
64a4c526
DL
237 :start 0 :end (1- cl-end)
238 :count (1- cl-count) cl-keys))))
fcd73769
RS
239 cl-seq))
240 cl-seq)))))
241
323698cc 242;;;###autoload
7c1898a7 243(defun cl-remove-if (cl-pred cl-list &rest cl-keys)
fcd73769
RS
244 "Remove all items satisfying PREDICATE in SEQ.
245This is a non-destructive function; it makes a copy of SEQ if necessary
246to avoid corrupting the original SEQ.
47bc4b3f
JB
247\nKeywords supported: :key :count :start :end :from-end
248\n(fn PREDICATE SEQ [KEYWORD VALUE]...)"
7c1898a7 249 (apply 'cl-remove nil cl-list :if cl-pred cl-keys))
fcd73769 250
323698cc 251;;;###autoload
7c1898a7 252(defun cl-remove-if-not (cl-pred cl-list &rest cl-keys)
fcd73769
RS
253 "Remove all items not satisfying PREDICATE in SEQ.
254This is a non-destructive function; it makes a copy of SEQ if necessary
255to avoid corrupting the original SEQ.
47bc4b3f
JB
256\nKeywords supported: :key :count :start :end :from-end
257\n(fn PREDICATE SEQ [KEYWORD VALUE]...)"
7c1898a7 258 (apply 'cl-remove nil cl-list :if-not cl-pred cl-keys))
fcd73769 259
323698cc 260;;;###autoload
7c1898a7 261(defun cl-delete (cl-item cl-seq &rest cl-keys)
fcd73769
RS
262 "Remove all occurrences of ITEM in SEQ.
263This is a destructive function; it reuses the storage of SEQ whenever possible.
47bc4b3f
JB
264\nKeywords supported: :test :test-not :key :count :start :end :from-end
265\n(fn ITEM SEQ [KEYWORD VALUE]...)"
bb3faf5b 266 (cl--parsing-keywords (:test :test-not :key :if :if-not :count :from-end
fcd73769
RS
267 (:start 0) :end) ()
268 (if (<= (or cl-count (setq cl-count 8000000)) 0)
269 cl-seq
270 (if (listp cl-seq)
271 (if (and cl-from-end (< cl-count 4000000))
272 (let (cl-i)
273 (while (and (>= (setq cl-count (1- cl-count)) 0)
4735906a
SM
274 (setq cl-i (cl--position cl-item cl-seq cl-start
275 cl-end cl-from-end)))
fcd73769
RS
276 (if (= cl-i 0) (setq cl-seq (cdr cl-seq))
277 (let ((cl-tail (nthcdr (1- cl-i) cl-seq)))
278 (setcdr cl-tail (cdr (cdr cl-tail)))))
279 (setq cl-end cl-i))
280 cl-seq)
281 (setq cl-end (- (or cl-end 8000000) cl-start))
282 (if (= cl-start 0)
283 (progn
284 (while (and cl-seq
285 (> cl-end 0)
bb3faf5b 286 (cl--check-test cl-item (car cl-seq))
fcd73769
RS
287 (setq cl-end (1- cl-end) cl-seq (cdr cl-seq))
288 (> (setq cl-count (1- cl-count)) 0)))
289 (setq cl-end (1- cl-end)))
290 (setq cl-start (1- cl-start)))
291 (if (and (> cl-count 0) (> cl-end 0))
292 (let ((cl-p (nthcdr cl-start cl-seq)))
293 (while (and (cdr cl-p) (> cl-end 0))
bb3faf5b 294 (if (cl--check-test cl-item (car (cdr cl-p)))
fcd73769
RS
295 (progn
296 (setcdr cl-p (cdr (cdr cl-p)))
297 (if (= (setq cl-count (1- cl-count)) 0)
298 (setq cl-end 1)))
299 (setq cl-p (cdr cl-p)))
300 (setq cl-end (1- cl-end)))))
301 cl-seq)
7c1898a7 302 (apply 'cl-remove cl-item cl-seq cl-keys)))))
fcd73769 303
323698cc 304;;;###autoload
7c1898a7 305(defun cl-delete-if (cl-pred cl-list &rest cl-keys)
fcd73769
RS
306 "Remove all items satisfying PREDICATE in SEQ.
307This is a destructive function; it reuses the storage of SEQ whenever possible.
47bc4b3f
JB
308\nKeywords supported: :key :count :start :end :from-end
309\n(fn PREDICATE SEQ [KEYWORD VALUE]...)"
7c1898a7 310 (apply 'cl-delete nil cl-list :if cl-pred cl-keys))
fcd73769 311
323698cc 312;;;###autoload
7c1898a7 313(defun cl-delete-if-not (cl-pred cl-list &rest cl-keys)
fcd73769
RS
314 "Remove all items not satisfying PREDICATE in SEQ.
315This is a destructive function; it reuses the storage of SEQ whenever possible.
47bc4b3f
JB
316\nKeywords supported: :key :count :start :end :from-end
317\n(fn PREDICATE SEQ [KEYWORD VALUE]...)"
7c1898a7 318 (apply 'cl-delete nil cl-list :if-not cl-pred cl-keys))
fcd73769 319
323698cc 320;;;###autoload
7c1898a7 321(defun cl-remove-duplicates (cl-seq &rest cl-keys)
fcd73769 322 "Return a copy of SEQ with all duplicate elements removed.
47bc4b3f
JB
323\nKeywords supported: :test :test-not :key :start :end :from-end
324\n(fn SEQ [KEYWORD VALUE]...)"
4735906a 325 (cl--delete-duplicates cl-seq cl-keys t))
fcd73769 326
323698cc 327;;;###autoload
7c1898a7 328(defun cl-delete-duplicates (cl-seq &rest cl-keys)
fcd73769 329 "Remove all duplicate elements from SEQ (destructively).
47bc4b3f
JB
330\nKeywords supported: :test :test-not :key :start :end :from-end
331\n(fn SEQ [KEYWORD VALUE]...)"
4735906a 332 (cl--delete-duplicates cl-seq cl-keys nil))
fcd73769 333
4735906a 334(defun cl--delete-duplicates (cl-seq cl-keys cl-copy)
fcd73769 335 (if (listp cl-seq)
bb3faf5b 336 (cl--parsing-keywords (:test :test-not :key (:start 0) :end :from-end :if)
fcd73769
RS
337 ()
338 (if cl-from-end
339 (let ((cl-p (nthcdr cl-start cl-seq)) cl-i)
340 (setq cl-end (- (or cl-end (length cl-seq)) cl-start))
341 (while (> cl-end 1)
342 (setq cl-i 0)
bb3faf5b 343 (while (setq cl-i (cl--position (cl--check-key (car cl-p))
4735906a 344 (cdr cl-p) cl-i (1- cl-end)))
fcd73769
RS
345 (if cl-copy (setq cl-seq (copy-sequence cl-seq)
346 cl-p (nthcdr cl-start cl-seq) cl-copy nil))
347 (let ((cl-tail (nthcdr cl-i cl-p)))
348 (setcdr cl-tail (cdr (cdr cl-tail))))
349 (setq cl-end (1- cl-end)))
350 (setq cl-p (cdr cl-p) cl-end (1- cl-end)
351 cl-start (1+ cl-start)))
352 cl-seq)
353 (setq cl-end (- (or cl-end (length cl-seq)) cl-start))
354 (while (and (cdr cl-seq) (= cl-start 0) (> cl-end 1)
bb3faf5b 355 (cl--position (cl--check-key (car cl-seq))
4735906a 356 (cdr cl-seq) 0 (1- cl-end)))
fcd73769
RS
357 (setq cl-seq (cdr cl-seq) cl-end (1- cl-end)))
358 (let ((cl-p (if (> cl-start 0) (nthcdr (1- cl-start) cl-seq)
359 (setq cl-end (1- cl-end) cl-start 1) cl-seq)))
360 (while (and (cdr (cdr cl-p)) (> cl-end 1))
bb3faf5b 361 (if (cl--position (cl--check-key (car (cdr cl-p)))
4735906a 362 (cdr (cdr cl-p)) 0 (1- cl-end))
fcd73769
RS
363 (progn
364 (if cl-copy (setq cl-seq (copy-sequence cl-seq)
365 cl-p (nthcdr (1- cl-start) cl-seq)
366 cl-copy nil))
367 (setcdr cl-p (cdr (cdr cl-p))))
368 (setq cl-p (cdr cl-p)))
369 (setq cl-end (1- cl-end) cl-start (1+ cl-start)))
370 cl-seq)))
4735906a 371 (let ((cl-res (cl--delete-duplicates (append cl-seq nil) cl-keys nil)))
fcd73769
RS
372 (if (stringp cl-seq) (concat cl-res) (vconcat cl-res)))))
373
323698cc 374;;;###autoload
7c1898a7 375(defun cl-substitute (cl-new cl-old cl-seq &rest cl-keys)
fcd73769
RS
376 "Substitute NEW for OLD in SEQ.
377This is a non-destructive function; it makes a copy of SEQ if necessary
378to avoid corrupting the original SEQ.
47bc4b3f
JB
379\nKeywords supported: :test :test-not :key :count :start :end :from-end
380\n(fn NEW OLD SEQ [KEYWORD VALUE]...)"
bb3faf5b 381 (cl--parsing-keywords (:test :test-not :key :if :if-not :count
fcd73769
RS
382 (:start 0) :end :from-end) ()
383 (if (or (eq cl-old cl-new)
384 (<= (or cl-count (setq cl-from-end nil cl-count 8000000)) 0))
385 cl-seq
4735906a 386 (let ((cl-i (cl--position cl-old cl-seq cl-start cl-end)))
fcd73769
RS
387 (if (not cl-i)
388 cl-seq
389 (setq cl-seq (copy-sequence cl-seq))
390 (or cl-from-end
bb3faf5b 391 (progn (cl--set-elt cl-seq cl-i cl-new)
fcd73769 392 (setq cl-i (1+ cl-i) cl-count (1- cl-count))))
7c1898a7 393 (apply 'cl-nsubstitute cl-new cl-old cl-seq :count cl-count
64a4c526 394 :start cl-i cl-keys))))))
fcd73769 395
323698cc 396;;;###autoload
7c1898a7 397(defun cl-substitute-if (cl-new cl-pred cl-list &rest cl-keys)
fcd73769
RS
398 "Substitute NEW for all items satisfying PREDICATE in SEQ.
399This is a non-destructive function; it makes a copy of SEQ if necessary
400to avoid corrupting the original SEQ.
47bc4b3f
JB
401\nKeywords supported: :key :count :start :end :from-end
402\n(fn NEW PREDICATE SEQ [KEYWORD VALUE]...)"
7c1898a7 403 (apply 'cl-substitute cl-new nil cl-list :if cl-pred cl-keys))
fcd73769 404
323698cc 405;;;###autoload
7c1898a7 406(defun cl-substitute-if-not (cl-new cl-pred cl-list &rest cl-keys)
fcd73769
RS
407 "Substitute NEW for all items not satisfying PREDICATE in SEQ.
408This is a non-destructive function; it makes a copy of SEQ if necessary
409to avoid corrupting the original SEQ.
47bc4b3f
JB
410\nKeywords supported: :key :count :start :end :from-end
411\n(fn NEW PREDICATE SEQ [KEYWORD VALUE]...)"
7c1898a7 412 (apply 'cl-substitute cl-new nil cl-list :if-not cl-pred cl-keys))
fcd73769 413
323698cc 414;;;###autoload
7c1898a7 415(defun cl-nsubstitute (cl-new cl-old cl-seq &rest cl-keys)
fcd73769
RS
416 "Substitute NEW for OLD in SEQ.
417This is a destructive function; it reuses the storage of SEQ whenever possible.
47bc4b3f
JB
418\nKeywords supported: :test :test-not :key :count :start :end :from-end
419\n(fn NEW OLD SEQ [KEYWORD VALUE]...)"
bb3faf5b 420 (cl--parsing-keywords (:test :test-not :key :if :if-not :count
fcd73769
RS
421 (:start 0) :end :from-end) ()
422 (or (eq cl-old cl-new) (<= (or cl-count (setq cl-count 8000000)) 0)
423 (if (and (listp cl-seq) (or (not cl-from-end) (> cl-count 4000000)))
424 (let ((cl-p (nthcdr cl-start cl-seq)))
425 (setq cl-end (- (or cl-end 8000000) cl-start))
426 (while (and cl-p (> cl-end 0) (> cl-count 0))
bb3faf5b 427 (if (cl--check-test cl-old (car cl-p))
fcd73769
RS
428 (progn
429 (setcar cl-p cl-new)
430 (setq cl-count (1- cl-count))))
431 (setq cl-p (cdr cl-p) cl-end (1- cl-end))))
432 (or cl-end (setq cl-end (length cl-seq)))
433 (if cl-from-end
434 (while (and (< cl-start cl-end) (> cl-count 0))
435 (setq cl-end (1- cl-end))
bb3faf5b 436 (if (cl--check-test cl-old (elt cl-seq cl-end))
fcd73769 437 (progn
bb3faf5b 438 (cl--set-elt cl-seq cl-end cl-new)
fcd73769
RS
439 (setq cl-count (1- cl-count)))))
440 (while (and (< cl-start cl-end) (> cl-count 0))
bb3faf5b 441 (if (cl--check-test cl-old (aref cl-seq cl-start))
fcd73769
RS
442 (progn
443 (aset cl-seq cl-start cl-new)
444 (setq cl-count (1- cl-count))))
445 (setq cl-start (1+ cl-start))))))
446 cl-seq))
447
323698cc 448;;;###autoload
7c1898a7 449(defun cl-nsubstitute-if (cl-new cl-pred cl-list &rest cl-keys)
fcd73769
RS
450 "Substitute NEW for all items satisfying PREDICATE in SEQ.
451This is a destructive function; it reuses the storage of SEQ whenever possible.
47bc4b3f
JB
452\nKeywords supported: :key :count :start :end :from-end
453\n(fn NEW PREDICATE SEQ [KEYWORD VALUE]...)"
7c1898a7 454 (apply 'cl-nsubstitute cl-new nil cl-list :if cl-pred cl-keys))
fcd73769 455
323698cc 456;;;###autoload
7c1898a7 457(defun cl-nsubstitute-if-not (cl-new cl-pred cl-list &rest cl-keys)
fcd73769
RS
458 "Substitute NEW for all items not satisfying PREDICATE in SEQ.
459This is a destructive function; it reuses the storage of SEQ whenever possible.
47bc4b3f
JB
460\nKeywords supported: :key :count :start :end :from-end
461\n(fn NEW PREDICATE SEQ [KEYWORD VALUE]...)"
7c1898a7 462 (apply 'cl-nsubstitute cl-new nil cl-list :if-not cl-pred cl-keys))
fcd73769 463
323698cc 464;;;###autoload
7c1898a7 465(defun cl-find (cl-item cl-seq &rest cl-keys)
47bc4b3f 466 "Find the first occurrence of ITEM in SEQ.
fcd73769 467Return the matching ITEM, or nil if not found.
47bc4b3f
JB
468\nKeywords supported: :test :test-not :key :start :end :from-end
469\n(fn ITEM SEQ [KEYWORD VALUE]...)"
7c1898a7 470 (let ((cl-pos (apply 'cl-position cl-item cl-seq cl-keys)))
fcd73769
RS
471 (and cl-pos (elt cl-seq cl-pos))))
472
323698cc 473;;;###autoload
7c1898a7 474(defun cl-find-if (cl-pred cl-list &rest cl-keys)
47bc4b3f
JB
475 "Find the first item satisfying PREDICATE in SEQ.
476Return the matching item, or nil if not found.
477\nKeywords supported: :key :start :end :from-end
478\n(fn PREDICATE SEQ [KEYWORD VALUE]...)"
7c1898a7 479 (apply 'cl-find nil cl-list :if cl-pred cl-keys))
fcd73769 480
323698cc 481;;;###autoload
7c1898a7 482(defun cl-find-if-not (cl-pred cl-list &rest cl-keys)
47bc4b3f
JB
483 "Find the first item not satisfying PREDICATE in SEQ.
484Return the matching item, or nil if not found.
485\nKeywords supported: :key :start :end :from-end
486\n(fn PREDICATE SEQ [KEYWORD VALUE]...)"
7c1898a7 487 (apply 'cl-find nil cl-list :if-not cl-pred cl-keys))
fcd73769 488
323698cc 489;;;###autoload
7c1898a7 490(defun cl-position (cl-item cl-seq &rest cl-keys)
47bc4b3f 491 "Find the first occurrence of ITEM in SEQ.
fcd73769 492Return the index of the matching item, or nil if not found.
47bc4b3f
JB
493\nKeywords supported: :test :test-not :key :start :end :from-end
494\n(fn ITEM SEQ [KEYWORD VALUE]...)"
bb3faf5b 495 (cl--parsing-keywords (:test :test-not :key :if :if-not
fcd73769 496 (:start 0) :end :from-end) ()
4735906a 497 (cl--position cl-item cl-seq cl-start cl-end cl-from-end)))
fcd73769 498
4735906a 499(defun cl--position (cl-item cl-seq cl-start &optional cl-end cl-from-end)
fcd73769
RS
500 (if (listp cl-seq)
501 (let ((cl-p (nthcdr cl-start cl-seq)))
502 (or cl-end (setq cl-end 8000000))
503 (let ((cl-res nil))
504 (while (and cl-p (< cl-start cl-end) (or (not cl-res) cl-from-end))
bb3faf5b 505 (if (cl--check-test cl-item (car cl-p))
fcd73769
RS
506 (setq cl-res cl-start))
507 (setq cl-p (cdr cl-p) cl-start (1+ cl-start)))
508 cl-res))
509 (or cl-end (setq cl-end (length cl-seq)))
510 (if cl-from-end
511 (progn
512 (while (and (>= (setq cl-end (1- cl-end)) cl-start)
bb3faf5b 513 (not (cl--check-test cl-item (aref cl-seq cl-end)))))
fcd73769
RS
514 (and (>= cl-end cl-start) cl-end))
515 (while (and (< cl-start cl-end)
bb3faf5b 516 (not (cl--check-test cl-item (aref cl-seq cl-start))))
fcd73769
RS
517 (setq cl-start (1+ cl-start)))
518 (and (< cl-start cl-end) cl-start))))
519
323698cc 520;;;###autoload
7c1898a7 521(defun cl-position-if (cl-pred cl-list &rest cl-keys)
47bc4b3f 522 "Find the first item satisfying PREDICATE in SEQ.
fcd73769 523Return the index of the matching item, or nil if not found.
47bc4b3f
JB
524\nKeywords supported: :key :start :end :from-end
525\n(fn PREDICATE SEQ [KEYWORD VALUE]...)"
7c1898a7 526 (apply 'cl-position nil cl-list :if cl-pred cl-keys))
fcd73769 527
323698cc 528;;;###autoload
7c1898a7 529(defun cl-position-if-not (cl-pred cl-list &rest cl-keys)
47bc4b3f 530 "Find the first item not satisfying PREDICATE in SEQ.
fcd73769 531Return the index of the matching item, or nil if not found.
47bc4b3f
JB
532\nKeywords supported: :key :start :end :from-end
533\n(fn PREDICATE SEQ [KEYWORD VALUE]...)"
7c1898a7 534 (apply 'cl-position nil cl-list :if-not cl-pred cl-keys))
fcd73769 535
323698cc 536;;;###autoload
7c1898a7 537(defun cl-count (cl-item cl-seq &rest cl-keys)
47bc4b3f
JB
538 "Count the number of occurrences of ITEM in SEQ.
539\nKeywords supported: :test :test-not :key :start :end
540\n(fn ITEM SEQ [KEYWORD VALUE]...)"
bb3faf5b 541 (cl--parsing-keywords (:test :test-not :key :if :if-not (:start 0) :end) ()
fcd73769
RS
542 (let ((cl-count 0) cl-x)
543 (or cl-end (setq cl-end (length cl-seq)))
544 (if (consp cl-seq) (setq cl-seq (nthcdr cl-start cl-seq)))
545 (while (< cl-start cl-end)
ca50d9e6 546 (setq cl-x (if (consp cl-seq) (pop cl-seq) (aref cl-seq cl-start)))
bb3faf5b 547 (if (cl--check-test cl-item cl-x) (setq cl-count (1+ cl-count)))
fcd73769
RS
548 (setq cl-start (1+ cl-start)))
549 cl-count)))
550
323698cc 551;;;###autoload
7c1898a7 552(defun cl-count-if (cl-pred cl-list &rest cl-keys)
47bc4b3f
JB
553 "Count the number of items satisfying PREDICATE in SEQ.
554\nKeywords supported: :key :start :end
555\n(fn PREDICATE SEQ [KEYWORD VALUE]...)"
7c1898a7 556 (apply 'cl-count nil cl-list :if cl-pred cl-keys))
fcd73769 557
323698cc 558;;;###autoload
7c1898a7 559(defun cl-count-if-not (cl-pred cl-list &rest cl-keys)
47bc4b3f
JB
560 "Count the number of items not satisfying PREDICATE in SEQ.
561\nKeywords supported: :key :start :end
562\n(fn PREDICATE SEQ [KEYWORD VALUE]...)"
7c1898a7 563 (apply 'cl-count nil cl-list :if-not cl-pred cl-keys))
fcd73769 564
323698cc 565;;;###autoload
7c1898a7 566(defun cl-mismatch (cl-seq1 cl-seq2 &rest cl-keys)
fcd73769
RS
567 "Compare SEQ1 with SEQ2, return index of first mismatching element.
568Return nil if the sequences match. If one sequence is a prefix of the
d22f8da4 569other, the return value indicates the end of the shorter sequence.
47bc4b3f
JB
570\nKeywords supported: :test :test-not :key :start1 :end1 :start2 :end2 :from-end
571\n(fn SEQ1 SEQ2 [KEYWORD VALUE]...)"
bb3faf5b 572 (cl--parsing-keywords (:test :test-not :key :from-end
fcd73769
RS
573 (:start1 0) :end1 (:start2 0) :end2) ()
574 (or cl-end1 (setq cl-end1 (length cl-seq1)))
575 (or cl-end2 (setq cl-end2 (length cl-seq2)))
576 (if cl-from-end
577 (progn
578 (while (and (< cl-start1 cl-end1) (< cl-start2 cl-end2)
bb3faf5b 579 (cl--check-match (elt cl-seq1 (1- cl-end1))
fcd73769
RS
580 (elt cl-seq2 (1- cl-end2))))
581 (setq cl-end1 (1- cl-end1) cl-end2 (1- cl-end2)))
582 (and (or (< cl-start1 cl-end1) (< cl-start2 cl-end2))
583 (1- cl-end1)))
584 (let ((cl-p1 (and (listp cl-seq1) (nthcdr cl-start1 cl-seq1)))
585 (cl-p2 (and (listp cl-seq2) (nthcdr cl-start2 cl-seq2))))
586 (while (and (< cl-start1 cl-end1) (< cl-start2 cl-end2)
bb3faf5b 587 (cl--check-match (if cl-p1 (car cl-p1)
fcd73769
RS
588 (aref cl-seq1 cl-start1))
589 (if cl-p2 (car cl-p2)
590 (aref cl-seq2 cl-start2))))
591 (setq cl-p1 (cdr cl-p1) cl-p2 (cdr cl-p2)
592 cl-start1 (1+ cl-start1) cl-start2 (1+ cl-start2)))
593 (and (or (< cl-start1 cl-end1) (< cl-start2 cl-end2))
594 cl-start1)))))
595
323698cc 596;;;###autoload
7c1898a7 597(defun cl-search (cl-seq1 cl-seq2 &rest cl-keys)
fcd73769
RS
598 "Search for SEQ1 as a subsequence of SEQ2.
599Return the index of the leftmost element of the first match found;
600return nil if there are no matches.
47bc4b3f
JB
601\nKeywords supported: :test :test-not :key :start1 :end1 :start2 :end2 :from-end
602\n(fn SEQ1 SEQ2 [KEYWORD VALUE]...)"
bb3faf5b 603 (cl--parsing-keywords (:test :test-not :key :from-end
fcd73769
RS
604 (:start1 0) :end1 (:start2 0) :end2) ()
605 (or cl-end1 (setq cl-end1 (length cl-seq1)))
606 (or cl-end2 (setq cl-end2 (length cl-seq2)))
607 (if (>= cl-start1 cl-end1)
608 (if cl-from-end cl-end2 cl-start2)
609 (let* ((cl-len (- cl-end1 cl-start1))
bb3faf5b 610 (cl-first (cl--check-key (elt cl-seq1 cl-start1)))
fcd73769
RS
611 (cl-if nil) cl-pos)
612 (setq cl-end2 (- cl-end2 (1- cl-len)))
613 (while (and (< cl-start2 cl-end2)
4735906a
SM
614 (setq cl-pos (cl--position cl-first cl-seq2
615 cl-start2 cl-end2 cl-from-end))
7c1898a7 616 (apply 'cl-mismatch cl-seq1 cl-seq2
64a4c526
DL
617 :start1 (1+ cl-start1) :end1 cl-end1
618 :start2 (1+ cl-pos) :end2 (+ cl-pos cl-len)
619 :from-end nil cl-keys))
fcd73769
RS
620 (if cl-from-end (setq cl-end2 cl-pos) (setq cl-start2 (1+ cl-pos))))
621 (and (< cl-start2 cl-end2) cl-pos)))))
622
323698cc 623;;;###autoload
7c1898a7 624(defun cl-sort (cl-seq cl-pred &rest cl-keys)
47bc4b3f
JB
625 "Sort the argument SEQ according to PREDICATE.
626This is a destructive function; it reuses the storage of SEQ if possible.
627\nKeywords supported: :key
628\n(fn SEQ PREDICATE [KEYWORD VALUE]...)"
fcd73769 629 (if (nlistp cl-seq)
7c1898a7 630 (cl-replace cl-seq (apply 'cl-sort (append cl-seq nil) cl-pred cl-keys))
bb3faf5b 631 (cl--parsing-keywords (:key) ()
fcd73769
RS
632 (if (memq cl-key '(nil identity))
633 (sort cl-seq cl-pred)
634 (sort cl-seq (function (lambda (cl-x cl-y)
635 (funcall cl-pred (funcall cl-key cl-x)
636 (funcall cl-key cl-y)))))))))
637
323698cc 638;;;###autoload
7c1898a7 639(defun cl-stable-sort (cl-seq cl-pred &rest cl-keys)
47bc4b3f
JB
640 "Sort the argument SEQ stably according to PREDICATE.
641This is a destructive function; it reuses the storage of SEQ if possible.
642\nKeywords supported: :key
643\n(fn SEQ PREDICATE [KEYWORD VALUE]...)"
7c1898a7 644 (apply 'cl-sort cl-seq cl-pred cl-keys))
fcd73769 645
323698cc 646;;;###autoload
7c1898a7 647(defun cl-merge (cl-type cl-seq1 cl-seq2 cl-pred &rest cl-keys)
fcd73769 648 "Destructively merge the two sequences to produce a new sequence.
47bc4b3f
JB
649TYPE is the sequence type to return, SEQ1 and SEQ2 are the two argument
650sequences, and PREDICATE is a `less-than' predicate on the elements.
651\nKeywords supported: :key
652\n(fn TYPE SEQ1 SEQ2 PREDICATE [KEYWORD VALUE]...)"
fcd73769
RS
653 (or (listp cl-seq1) (setq cl-seq1 (append cl-seq1 nil)))
654 (or (listp cl-seq2) (setq cl-seq2 (append cl-seq2 nil)))
bb3faf5b 655 (cl--parsing-keywords (:key) ()
fcd73769
RS
656 (let ((cl-res nil))
657 (while (and cl-seq1 cl-seq2)
bb3faf5b
SM
658 (if (funcall cl-pred (cl--check-key (car cl-seq2))
659 (cl--check-key (car cl-seq1)))
ca50d9e6
SM
660 (push (pop cl-seq2) cl-res)
661 (push (pop cl-seq1) cl-res)))
7c1898a7 662 (cl-coerce (nconc (nreverse cl-res) cl-seq1 cl-seq2) cl-type))))
fcd73769 663
323698cc 664;;;###autoload
7c1898a7 665(defun cl-member (cl-item cl-list &rest cl-keys)
fcd73769
RS
666 "Find the first occurrence of ITEM in LIST.
667Return the sublist of LIST whose car is ITEM.
47bc4b3f
JB
668\nKeywords supported: :test :test-not :key
669\n(fn ITEM LIST [KEYWORD VALUE]...)"
d9857e53 670 (declare (compiler-macro cl--compiler-macro-member))
fcd73769 671 (if cl-keys
bb3faf5b
SM
672 (cl--parsing-keywords (:test :test-not :key :if :if-not) ()
673 (while (and cl-list (not (cl--check-test cl-item (car cl-list))))
fcd73769
RS
674 (setq cl-list (cdr cl-list)))
675 cl-list)
676 (if (and (numberp cl-item) (not (integerp cl-item)))
677 (member cl-item cl-list)
678 (memq cl-item cl-list))))
d9857e53 679(autoload 'cl--compiler-macro-member "cl-macs")
fcd73769 680
323698cc 681;;;###autoload
7c1898a7 682(defun cl-member-if (cl-pred cl-list &rest cl-keys)
fcd73769
RS
683 "Find the first item satisfying PREDICATE in LIST.
684Return the sublist of LIST whose car matches.
47bc4b3f
JB
685\nKeywords supported: :key
686\n(fn PREDICATE LIST [KEYWORD VALUE]...)"
7c1898a7 687 (apply 'cl-member nil cl-list :if cl-pred cl-keys))
fcd73769 688
323698cc 689;;;###autoload
7c1898a7 690(defun cl-member-if-not (cl-pred cl-list &rest cl-keys)
fcd73769
RS
691 "Find the first item not satisfying PREDICATE in LIST.
692Return the sublist of LIST whose car matches.
47bc4b3f
JB
693\nKeywords supported: :key
694\n(fn PREDICATE LIST [KEYWORD VALUE]...)"
7c1898a7 695 (apply 'cl-member nil cl-list :if-not cl-pred cl-keys))
fcd73769 696
323698cc 697;;;###autoload
4735906a 698(defun cl--adjoin (cl-item cl-list &rest cl-keys)
bb3faf5b
SM
699 (if (cl--parsing-keywords (:key) t
700 (apply 'cl-member (cl--check-key cl-item) cl-list cl-keys))
fcd73769
RS
701 cl-list
702 (cons cl-item cl-list)))
703
323698cc 704;;;###autoload
7c1898a7 705(defun cl-assoc (cl-item cl-alist &rest cl-keys)
fcd73769 706 "Find the first item whose car matches ITEM in LIST.
47bc4b3f
JB
707\nKeywords supported: :test :test-not :key
708\n(fn ITEM LIST [KEYWORD VALUE]...)"
d9857e53 709 (declare (compiler-macro cl--compiler-macro-assoc))
fcd73769 710 (if cl-keys
bb3faf5b 711 (cl--parsing-keywords (:test :test-not :key :if :if-not) ()
fcd73769
RS
712 (while (and cl-alist
713 (or (not (consp (car cl-alist)))
bb3faf5b 714 (not (cl--check-test cl-item (car (car cl-alist))))))
fcd73769
RS
715 (setq cl-alist (cdr cl-alist)))
716 (and cl-alist (car cl-alist)))
717 (if (and (numberp cl-item) (not (integerp cl-item)))
718 (assoc cl-item cl-alist)
719 (assq cl-item cl-alist))))
d9857e53 720(autoload 'cl--compiler-macro-assoc "cl-macs")
fcd73769 721
323698cc 722;;;###autoload
7c1898a7 723(defun cl-assoc-if (cl-pred cl-list &rest cl-keys)
fcd73769 724 "Find the first item whose car satisfies PREDICATE in LIST.
47bc4b3f
JB
725\nKeywords supported: :key
726\n(fn PREDICATE LIST [KEYWORD VALUE]...)"
7c1898a7 727 (apply 'cl-assoc nil cl-list :if cl-pred cl-keys))
fcd73769 728
323698cc 729;;;###autoload
7c1898a7 730(defun cl-assoc-if-not (cl-pred cl-list &rest cl-keys)
fcd73769 731 "Find the first item whose car does not satisfy PREDICATE in LIST.
47bc4b3f
JB
732\nKeywords supported: :key
733\n(fn PREDICATE LIST [KEYWORD VALUE]...)"
7c1898a7 734 (apply 'cl-assoc nil cl-list :if-not cl-pred cl-keys))
fcd73769 735
323698cc 736;;;###autoload
7c1898a7 737(defun cl-rassoc (cl-item cl-alist &rest cl-keys)
fcd73769 738 "Find the first item whose cdr matches ITEM in LIST.
47bc4b3f
JB
739\nKeywords supported: :test :test-not :key
740\n(fn ITEM LIST [KEYWORD VALUE]...)"
fcd73769 741 (if (or cl-keys (numberp cl-item))
bb3faf5b 742 (cl--parsing-keywords (:test :test-not :key :if :if-not) ()
fcd73769
RS
743 (while (and cl-alist
744 (or (not (consp (car cl-alist)))
bb3faf5b 745 (not (cl--check-test cl-item (cdr (car cl-alist))))))
fcd73769
RS
746 (setq cl-alist (cdr cl-alist)))
747 (and cl-alist (car cl-alist)))
748 (rassq cl-item cl-alist)))
749
323698cc 750;;;###autoload
7c1898a7 751(defun cl-rassoc-if (cl-pred cl-list &rest cl-keys)
fcd73769 752 "Find the first item whose cdr satisfies PREDICATE in LIST.
47bc4b3f
JB
753\nKeywords supported: :key
754\n(fn PREDICATE LIST [KEYWORD VALUE]...)"
7c1898a7 755 (apply 'cl-rassoc nil cl-list :if cl-pred cl-keys))
fcd73769 756
323698cc 757;;;###autoload
7c1898a7 758(defun cl-rassoc-if-not (cl-pred cl-list &rest cl-keys)
fcd73769 759 "Find the first item whose cdr does not satisfy PREDICATE in LIST.
47bc4b3f
JB
760\nKeywords supported: :key
761\n(fn PREDICATE LIST [KEYWORD VALUE]...)"
7c1898a7 762 (apply 'cl-rassoc nil cl-list :if-not cl-pred cl-keys))
fcd73769 763
323698cc 764;;;###autoload
7c1898a7 765(defun cl-union (cl-list1 cl-list2 &rest cl-keys)
fcd73769 766 "Combine LIST1 and LIST2 using a set-union operation.
86361e1e 767The resulting list contains all items that appear in either LIST1 or LIST2.
fcd73769
RS
768This is a non-destructive function; it makes a copy of the data if necessary
769to avoid corrupting the original LIST1 and LIST2.
47bc4b3f
JB
770\nKeywords supported: :test :test-not :key
771\n(fn LIST1 LIST2 [KEYWORD VALUE]...)"
fcd73769
RS
772 (cond ((null cl-list1) cl-list2) ((null cl-list2) cl-list1)
773 ((equal cl-list1 cl-list2) cl-list1)
774 (t
775 (or (>= (length cl-list1) (length cl-list2))
776 (setq cl-list1 (prog1 cl-list2 (setq cl-list2 cl-list1))))
777 (while cl-list2
778 (if (or cl-keys (numberp (car cl-list2)))
7c1898a7 779 (setq cl-list1 (apply 'cl-adjoin (car cl-list2) cl-list1 cl-keys))
fcd73769 780 (or (memq (car cl-list2) cl-list1)
ca50d9e6
SM
781 (push (car cl-list2) cl-list1)))
782 (pop cl-list2))
fcd73769
RS
783 cl-list1)))
784
323698cc 785;;;###autoload
7c1898a7 786(defun cl-nunion (cl-list1 cl-list2 &rest cl-keys)
fcd73769 787 "Combine LIST1 and LIST2 using a set-union operation.
86361e1e 788The resulting list contains all items that appear in either LIST1 or LIST2.
fcd73769
RS
789This is a destructive function; it reuses the storage of LIST1 and LIST2
790whenever possible.
47bc4b3f
JB
791\nKeywords supported: :test :test-not :key
792\n(fn LIST1 LIST2 [KEYWORD VALUE]...)"
fcd73769 793 (cond ((null cl-list1) cl-list2) ((null cl-list2) cl-list1)
7c1898a7 794 (t (apply 'cl-union cl-list1 cl-list2 cl-keys))))
fcd73769 795
323698cc 796;;;###autoload
7c1898a7 797(defun cl-intersection (cl-list1 cl-list2 &rest cl-keys)
fcd73769 798 "Combine LIST1 and LIST2 using a set-intersection operation.
86361e1e 799The resulting list contains all items that appear in both LIST1 and LIST2.
fcd73769
RS
800This is a non-destructive function; it makes a copy of the data if necessary
801to avoid corrupting the original LIST1 and LIST2.
47bc4b3f
JB
802\nKeywords supported: :test :test-not :key
803\n(fn LIST1 LIST2 [KEYWORD VALUE]...)"
fcd73769
RS
804 (and cl-list1 cl-list2
805 (if (equal cl-list1 cl-list2) cl-list1
bb3faf5b 806 (cl--parsing-keywords (:key) (:test :test-not)
fcd73769
RS
807 (let ((cl-res nil))
808 (or (>= (length cl-list1) (length cl-list2))
809 (setq cl-list1 (prog1 cl-list2 (setq cl-list2 cl-list1))))
810 (while cl-list2
811 (if (if (or cl-keys (numberp (car cl-list2)))
bb3faf5b 812 (apply 'cl-member (cl--check-key (car cl-list2))
fcd73769
RS
813 cl-list1 cl-keys)
814 (memq (car cl-list2) cl-list1))
ca50d9e6
SM
815 (push (car cl-list2) cl-res))
816 (pop cl-list2))
fcd73769
RS
817 cl-res)))))
818
323698cc 819;;;###autoload
7c1898a7 820(defun cl-nintersection (cl-list1 cl-list2 &rest cl-keys)
fcd73769 821 "Combine LIST1 and LIST2 using a set-intersection operation.
86361e1e 822The resulting list contains all items that appear in both LIST1 and LIST2.
fcd73769
RS
823This is a destructive function; it reuses the storage of LIST1 and LIST2
824whenever possible.
47bc4b3f
JB
825\nKeywords supported: :test :test-not :key
826\n(fn LIST1 LIST2 [KEYWORD VALUE]...)"
7c1898a7 827 (and cl-list1 cl-list2 (apply 'cl-intersection cl-list1 cl-list2 cl-keys)))
fcd73769 828
323698cc 829;;;###autoload
7c1898a7 830(defun cl-set-difference (cl-list1 cl-list2 &rest cl-keys)
fcd73769 831 "Combine LIST1 and LIST2 using a set-difference operation.
86361e1e 832The resulting list contains all items that appear in LIST1 but not LIST2.
fcd73769
RS
833This is a non-destructive function; it makes a copy of the data if necessary
834to avoid corrupting the original LIST1 and LIST2.
47bc4b3f
JB
835\nKeywords supported: :test :test-not :key
836\n(fn LIST1 LIST2 [KEYWORD VALUE]...)"
fcd73769 837 (if (or (null cl-list1) (null cl-list2)) cl-list1
bb3faf5b 838 (cl--parsing-keywords (:key) (:test :test-not)
fcd73769
RS
839 (let ((cl-res nil))
840 (while cl-list1
841 (or (if (or cl-keys (numberp (car cl-list1)))
bb3faf5b 842 (apply 'cl-member (cl--check-key (car cl-list1))
fcd73769
RS
843 cl-list2 cl-keys)
844 (memq (car cl-list1) cl-list2))
ca50d9e6
SM
845 (push (car cl-list1) cl-res))
846 (pop cl-list1))
fcd73769
RS
847 cl-res))))
848
323698cc 849;;;###autoload
7c1898a7 850(defun cl-nset-difference (cl-list1 cl-list2 &rest cl-keys)
fcd73769 851 "Combine LIST1 and LIST2 using a set-difference operation.
86361e1e 852The resulting list contains all items that appear in LIST1 but not LIST2.
fcd73769
RS
853This is a destructive function; it reuses the storage of LIST1 and LIST2
854whenever possible.
47bc4b3f
JB
855\nKeywords supported: :test :test-not :key
856\n(fn LIST1 LIST2 [KEYWORD VALUE]...)"
fcd73769 857 (if (or (null cl-list1) (null cl-list2)) cl-list1
7c1898a7 858 (apply 'cl-set-difference cl-list1 cl-list2 cl-keys)))
fcd73769 859
323698cc 860;;;###autoload
7c1898a7 861(defun cl-set-exclusive-or (cl-list1 cl-list2 &rest cl-keys)
fcd73769 862 "Combine LIST1 and LIST2 using a set-exclusive-or operation.
86361e1e 863The resulting list contains all items appearing in exactly one of LIST1, LIST2.
fcd73769
RS
864This is a non-destructive function; it makes a copy of the data if necessary
865to avoid corrupting the original LIST1 and LIST2.
47bc4b3f
JB
866\nKeywords supported: :test :test-not :key
867\n(fn LIST1 LIST2 [KEYWORD VALUE]...)"
fcd73769
RS
868 (cond ((null cl-list1) cl-list2) ((null cl-list2) cl-list1)
869 ((equal cl-list1 cl-list2) nil)
7c1898a7
SM
870 (t (append (apply 'cl-set-difference cl-list1 cl-list2 cl-keys)
871 (apply 'cl-set-difference cl-list2 cl-list1 cl-keys)))))
fcd73769 872
323698cc 873;;;###autoload
7c1898a7 874(defun cl-nset-exclusive-or (cl-list1 cl-list2 &rest cl-keys)
fcd73769 875 "Combine LIST1 and LIST2 using a set-exclusive-or operation.
86361e1e 876The resulting list contains all items appearing in exactly one of LIST1, LIST2.
fcd73769
RS
877This is a destructive function; it reuses the storage of LIST1 and LIST2
878whenever possible.
47bc4b3f
JB
879\nKeywords supported: :test :test-not :key
880\n(fn LIST1 LIST2 [KEYWORD VALUE]...)"
fcd73769
RS
881 (cond ((null cl-list1) cl-list2) ((null cl-list2) cl-list1)
882 ((equal cl-list1 cl-list2) nil)
7c1898a7
SM
883 (t (nconc (apply 'cl-nset-difference cl-list1 cl-list2 cl-keys)
884 (apply 'cl-nset-difference cl-list2 cl-list1 cl-keys)))))
fcd73769 885
323698cc 886;;;###autoload
7c1898a7 887(defun cl-subsetp (cl-list1 cl-list2 &rest cl-keys)
213233f0 888 "Return true if LIST1 is a subset of LIST2.
fcd73769 889I.e., if every element of LIST1 also appears in LIST2.
47bc4b3f
JB
890\nKeywords supported: :test :test-not :key
891\n(fn LIST1 LIST2 [KEYWORD VALUE]...)"
fcd73769
RS
892 (cond ((null cl-list1) t) ((null cl-list2) nil)
893 ((equal cl-list1 cl-list2) t)
bb3faf5b 894 (t (cl--parsing-keywords (:key) (:test :test-not)
fcd73769 895 (while (and cl-list1
bb3faf5b 896 (apply 'cl-member (cl--check-key (car cl-list1))
fcd73769 897 cl-list2 cl-keys))
ca50d9e6 898 (pop cl-list1))
fcd73769
RS
899 (null cl-list1)))))
900
323698cc 901;;;###autoload
7c1898a7 902(defun cl-subst-if (cl-new cl-pred cl-tree &rest cl-keys)
fcd73769
RS
903 "Substitute NEW for elements matching PREDICATE in TREE (non-destructively).
904Return a copy of TREE with all matching elements replaced by NEW.
47bc4b3f
JB
905\nKeywords supported: :key
906\n(fn NEW PREDICATE TREE [KEYWORD VALUE]...)"
7c1898a7 907 (apply 'cl-sublis (list (cons nil cl-new)) cl-tree :if cl-pred cl-keys))
fcd73769 908
323698cc 909;;;###autoload
7c1898a7 910(defun cl-subst-if-not (cl-new cl-pred cl-tree &rest cl-keys)
fcd73769
RS
911 "Substitute NEW for elts not matching PREDICATE in TREE (non-destructively).
912Return a copy of TREE with all non-matching elements replaced by NEW.
47bc4b3f
JB
913\nKeywords supported: :key
914\n(fn NEW PREDICATE TREE [KEYWORD VALUE]...)"
7c1898a7 915 (apply 'cl-sublis (list (cons nil cl-new)) cl-tree :if-not cl-pred cl-keys))
fcd73769 916
323698cc 917;;;###autoload
7c1898a7 918(defun cl-nsubst (cl-new cl-old cl-tree &rest cl-keys)
fcd73769
RS
919 "Substitute NEW for OLD everywhere in TREE (destructively).
920Any element of TREE which is `eql' to OLD is changed to NEW (via a call
921to `setcar').
47bc4b3f
JB
922\nKeywords supported: :test :test-not :key
923\n(fn NEW OLD TREE [KEYWORD VALUE]...)"
7c1898a7 924 (apply 'cl-nsublis (list (cons cl-old cl-new)) cl-tree cl-keys))
fcd73769 925
323698cc 926;;;###autoload
7c1898a7 927(defun cl-nsubst-if (cl-new cl-pred cl-tree &rest cl-keys)
fcd73769
RS
928 "Substitute NEW for elements matching PREDICATE in TREE (destructively).
929Any element of TREE which matches is changed to NEW (via a call to `setcar').
47bc4b3f
JB
930\nKeywords supported: :key
931\n(fn NEW PREDICATE TREE [KEYWORD VALUE]...)"
7c1898a7 932 (apply 'cl-nsublis (list (cons nil cl-new)) cl-tree :if cl-pred cl-keys))
fcd73769 933
323698cc 934;;;###autoload
7c1898a7 935(defun cl-nsubst-if-not (cl-new cl-pred cl-tree &rest cl-keys)
fcd73769
RS
936 "Substitute NEW for elements not matching PREDICATE in TREE (destructively).
937Any element of TREE which matches is changed to NEW (via a call to `setcar').
47bc4b3f
JB
938\nKeywords supported: :key
939\n(fn NEW PREDICATE TREE [KEYWORD VALUE]...)"
7c1898a7 940 (apply 'cl-nsublis (list (cons nil cl-new)) cl-tree :if-not cl-pred cl-keys))
fcd73769 941
bb3faf5b
SM
942(defvar cl--alist)
943
323698cc 944;;;###autoload
7c1898a7 945(defun cl-sublis (cl-alist cl-tree &rest cl-keys)
fcd73769
RS
946 "Perform substitutions indicated by ALIST in TREE (non-destructively).
947Return a copy of TREE with all matching elements replaced.
47bc4b3f
JB
948\nKeywords supported: :test :test-not :key
949\n(fn ALIST TREE [KEYWORD VALUE]...)"
bb3faf5b
SM
950 (cl--parsing-keywords (:test :test-not :key :if :if-not) ()
951 (let ((cl--alist cl-alist))
952 (cl--sublis-rec cl-tree))))
fcd73769 953
bb3faf5b
SM
954(defun cl--sublis-rec (cl-tree) ;Uses cl--alist cl-key/test*/if*.
955 (let ((cl-temp (cl--check-key cl-tree)) (cl-p cl--alist))
956 (while (and cl-p (not (cl--check-test-nokey (car (car cl-p)) cl-temp)))
fcd73769
RS
957 (setq cl-p (cdr cl-p)))
958 (if cl-p (cdr (car cl-p))
959 (if (consp cl-tree)
bb3faf5b
SM
960 (let ((cl-a (cl--sublis-rec (car cl-tree)))
961 (cl-d (cl--sublis-rec (cdr cl-tree))))
fcd73769
RS
962 (if (and (eq cl-a (car cl-tree)) (eq cl-d (cdr cl-tree)))
963 cl-tree
964 (cons cl-a cl-d)))
965 cl-tree))))
966
323698cc 967;;;###autoload
7c1898a7 968(defun cl-nsublis (cl-alist cl-tree &rest cl-keys)
fcd73769
RS
969 "Perform substitutions indicated by ALIST in TREE (destructively).
970Any matching element of TREE is changed via a call to `setcar'.
47bc4b3f
JB
971\nKeywords supported: :test :test-not :key
972\n(fn ALIST TREE [KEYWORD VALUE]...)"
bb3faf5b
SM
973 (cl--parsing-keywords (:test :test-not :key :if :if-not) ()
974 (let ((cl-hold (list cl-tree))
975 (cl--alist cl-alist))
976 (cl--nsublis-rec cl-hold)
fcd73769
RS
977 (car cl-hold))))
978
bb3faf5b 979(defun cl--nsublis-rec (cl-tree) ;Uses cl--alist cl-key/test*/if*.
fcd73769 980 (while (consp cl-tree)
bb3faf5b
SM
981 (let ((cl-temp (cl--check-key (car cl-tree))) (cl-p cl--alist))
982 (while (and cl-p (not (cl--check-test-nokey (car (car cl-p)) cl-temp)))
fcd73769
RS
983 (setq cl-p (cdr cl-p)))
984 (if cl-p (setcar cl-tree (cdr (car cl-p)))
bb3faf5b
SM
985 (if (consp (car cl-tree)) (cl--nsublis-rec (car cl-tree))))
986 (setq cl-temp (cl--check-key (cdr cl-tree)) cl-p cl--alist)
987 (while (and cl-p (not (cl--check-test-nokey (car (car cl-p)) cl-temp)))
fcd73769
RS
988 (setq cl-p (cdr cl-p)))
989 (if cl-p
990 (progn (setcdr cl-tree (cdr (car cl-p))) (setq cl-tree nil))
991 (setq cl-tree (cdr cl-tree))))))
992
323698cc 993;;;###autoload
7c1898a7 994(defun cl-tree-equal (cl-x cl-y &rest cl-keys)
47bc4b3f 995 "Return t if trees TREE1 and TREE2 have `eql' leaves.
fcd73769 996Atoms are compared by `eql'; cons cells are compared recursively.
47bc4b3f
JB
997\nKeywords supported: :test :test-not :key
998\n(fn TREE1 TREE2 [KEYWORD VALUE]...)"
bb3faf5b
SM
999 (cl--parsing-keywords (:test :test-not :key) ()
1000 (cl--tree-equal-rec cl-x cl-y)))
fcd73769 1001
bb3faf5b 1002(defun cl--tree-equal-rec (cl-x cl-y) ;Uses cl-key/test*.
fcd73769 1003 (while (and (consp cl-x) (consp cl-y)
bb3faf5b 1004 (cl--tree-equal-rec (car cl-x) (car cl-y)))
fcd73769 1005 (setq cl-x (cdr cl-x) cl-y (cdr cl-y)))
bb3faf5b 1006 (and (not (consp cl-x)) (not (consp cl-y)) (cl--check-match cl-x cl-y)))
fcd73769
RS
1007
1008
1009(run-hooks 'cl-seq-load-hook)
1010
323698cc 1011;; Local variables:
08f5e965
GM
1012;; byte-compile-dynamic: t
1013;; byte-compile-warnings: (not cl-functions)
323698cc
SM
1014;; generated-autoload-file: "cl-loaddefs.el"
1015;; End:
1016
fcd73769 1017;;; cl-seq.el ends here