1 ;;; cl-seq.el --- Common Lisp features, part 3 -*- lexical-binding: t -*-
3 ;; Copyright (C) 1993, 2001-2012 Free Software Foundation, Inc.
5 ;; Author: Dave Gillespie <daveg@synaptics.com>
7 ;; Keywords: extensions
10 ;; This file is part of GNU Emacs.
12 ;; GNU Emacs is free software: you can redistribute it and/or modify
13 ;; it under the terms of the GNU General Public License as published by
14 ;; the Free Software Foundation, either version 3 of the License, or
15 ;; (at your option) any later version.
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.
22 ;; You should have received a copy of the GNU General Public License
23 ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
27 ;; These are extensions to Emacs Lisp that provide a degree of
28 ;; Common Lisp compatibility, beyond what is already built-in
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.
34 ;; Bug reports, comments, and suggestions are welcome!
36 ;; This file contains the Common Lisp sequence and list functions
37 ;; which take keyword arguments.
39 ;; See cl.el for Change Log.
47 ;; This is special-cased here so that we can compile
48 ;; this file independent from cl-macs.
50 (defmacro cl--parsing-keywords
(kwords other-keys
&rest body
)
51 (declare (indent 2) (debug (sexp sexp
&rest form
)))
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
)))
59 (setq mem
`(and ,mem
(setq cl-if
,mem
) t
)))
61 (format "cl-%s" (substring (symbol-name var
) 1)))
62 (if (consp x
) `(or ,mem
,(car (cdr x
))) mem
))))
65 (and (not (eq other-keys t
))
67 (list 'let
'((cl-keys-temp cl-keys
))
68 (list 'while
'cl-keys-temp
69 (list 'or
(list 'memq
'(car cl-keys-temp
)
78 '(car (cdr (memq (quote :allow-other-keys
)
80 '(error "Bad keyword argument %s"
82 '(setq cl-keys-temp
(cdr (cdr cl-keys-temp
)))))))
85 (defmacro cl--check-key
(x) ;Expects `cl-key' in context of generated code.
86 (declare (debug edebug-forms
))
87 `(if cl-key
(funcall cl-key
,x
) ,x
))
89 (defmacro cl--check-test-nokey
(item x
) ;cl-test cl-if cl-test-not cl-if-not.
90 (declare (debug edebug-forms
))
92 (cl-test (eq (not (funcall cl-test
,item
,x
))
94 (cl-if (eq (not (funcall cl-if
,x
)) cl-if-not
))
97 (defmacro cl--check-test
(item x
) ;all of the above.
98 (declare (debug edebug-forms
))
99 `(cl--check-test-nokey ,item
(cl--check-key ,x
)))
101 (defmacro cl--check-match
(x y
) ;cl-key cl-test cl-test-not
102 (declare (debug edebug-forms
))
103 (setq x
`(cl--check-key ,x
) y
`(cl--check-key ,y
))
105 (eq (not (funcall cl-test
,x
,y
)) cl-test-not
)
108 (defvar cl-test
) (defvar cl-test-not
)
109 (defvar cl-if
) (defvar cl-if-not
)
113 (defun cl-reduce (cl-func cl-seq
&rest cl-keys
)
114 "Reduce two-argument FUNCTION across SEQ.
115 \nKeywords supported: :start :end :from-end :initial-value :key
116 \n(fn FUNCTION SEQ [KEYWORD VALUE]...)"
117 (cl--parsing-keywords (:from-end
(:start
0) :end
:initial-value
:key
) ()
118 (or (listp cl-seq
) (setq cl-seq
(append cl-seq nil
)))
119 (setq cl-seq
(cl-subseq cl-seq cl-start cl-end
))
120 (if cl-from-end
(setq cl-seq
(nreverse cl-seq
)))
121 (let ((cl-accum (cond ((memq :initial-value cl-keys
) cl-initial-value
)
122 (cl-seq (cl--check-key (pop cl-seq
)))
123 (t (funcall cl-func
)))))
126 (setq cl-accum
(funcall cl-func
(cl--check-key (pop cl-seq
))
129 (setq cl-accum
(funcall cl-func cl-accum
130 (cl--check-key (pop cl-seq
))))))
134 (defun cl-fill (seq item
&rest cl-keys
)
135 "Fill the elements of SEQ with ITEM.
136 \nKeywords supported: :start :end
137 \n(fn SEQ ITEM [KEYWORD VALUE]...)"
138 (cl--parsing-keywords ((:start
0) :end
) ()
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))
145 (or cl-end
(setq cl-end
(length seq
)))
146 (if (and (= cl-start
0) (= cl-end
(length seq
)))
148 (while (< cl-start cl-end
)
149 (aset seq cl-start item
)
150 (setq cl-start
(1+ cl-start
)))))
154 (defun cl-replace (cl-seq1 cl-seq2
&rest cl-keys
)
155 "Replace the elements of SEQ1 with the elements of SEQ2.
156 SEQ1 is destructively modified, then returned.
157 \nKeywords supported: :start1 :end1 :start2 :end2
158 \n(fn SEQ1 SEQ2 [KEYWORD VALUE]...)"
159 (cl--parsing-keywords ((:start1
0) :end1
(:start2
0) :end2
) ()
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)
166 (cl--set-elt cl-seq1
(+ cl-start1 cl-n
)
167 (elt cl-seq2
(+ cl-start2 cl-n
))))))
169 (let ((cl-p1 (nthcdr cl-start1 cl-seq1
))
170 (cl-n1 (if cl-end1
(- cl-end1 cl-start1
) 4000000)))
172 (let ((cl-p2 (nthcdr cl-start2 cl-seq2
))
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
))
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
))))))
197 (defun cl-remove (cl-item cl-seq
&rest cl-keys
)
198 "Remove all occurrences of ITEM in SEQ.
199 This is a non-destructive function; it makes a copy of SEQ if necessary
200 to avoid corrupting the original SEQ.
201 \nKeywords supported: :test :test-not :key :count :start :end :from-end
202 \n(fn ITEM SEQ [KEYWORD VALUE]...)"
203 (cl--parsing-keywords (:test
:test-not
:key
:if
:if-not
:count
:from-end
205 (if (<= (or cl-count
(setq cl-count
8000000)) 0)
207 (if (or (nlistp cl-seq
) (and cl-from-end
(< cl-count
4000000)))
208 (let ((cl-i (cl--position cl-item cl-seq cl-start cl-end
211 (let ((cl-res (apply 'cl-delete cl-item
(append cl-seq nil
)
212 (append (if cl-from-end
213 (list :end
(1+ cl-i
))
216 (if (listp cl-seq
) cl-res
217 (if (stringp cl-seq
) (concat cl-res
) (vconcat cl-res
))))
219 (setq cl-end
(- (or cl-end
8000000) cl-start
))
221 (while (and cl-seq
(> cl-end
0)
222 (cl--check-test cl-item
(car cl-seq
))
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)
229 (not (cl--check-test cl-item
(car cl-p
))))
230 (setq cl-p
(cdr cl-p
) cl-end
(1- cl-end
)))
231 (if (and cl-p
(> cl-end
0))
232 (nconc (cl-ldiff cl-seq cl-p
)
233 (if (= cl-count
1) (cdr cl-p
)
235 (apply 'cl-delete cl-item
236 (copy-sequence (cdr cl-p
))
237 :start
0 :end
(1- cl-end
)
238 :count
(1- cl-count
) cl-keys
))))
243 (defun cl-remove-if (cl-pred cl-list
&rest cl-keys
)
244 "Remove all items satisfying PREDICATE in SEQ.
245 This is a non-destructive function; it makes a copy of SEQ if necessary
246 to avoid corrupting the original SEQ.
247 \nKeywords supported: :key :count :start :end :from-end
248 \n(fn PREDICATE SEQ [KEYWORD VALUE]...)"
249 (apply 'cl-remove nil cl-list
:if cl-pred cl-keys
))
252 (defun cl-remove-if-not (cl-pred cl-list
&rest cl-keys
)
253 "Remove all items not satisfying PREDICATE in SEQ.
254 This is a non-destructive function; it makes a copy of SEQ if necessary
255 to avoid corrupting the original SEQ.
256 \nKeywords supported: :key :count :start :end :from-end
257 \n(fn PREDICATE SEQ [KEYWORD VALUE]...)"
258 (apply 'cl-remove nil cl-list
:if-not cl-pred cl-keys
))
261 (defun cl-delete (cl-item cl-seq
&rest cl-keys
)
262 "Remove all occurrences of ITEM in SEQ.
263 This is a destructive function; it reuses the storage of SEQ whenever possible.
264 \nKeywords supported: :test :test-not :key :count :start :end :from-end
265 \n(fn ITEM SEQ [KEYWORD VALUE]...)"
266 (cl--parsing-keywords (:test
:test-not
:key
:if
:if-not
:count
:from-end
268 (if (<= (or cl-count
(setq cl-count
8000000)) 0)
271 (if (and cl-from-end
(< cl-count
4000000))
273 (while (and (>= (setq cl-count
(1- cl-count
)) 0)
274 (setq cl-i
(cl--position cl-item cl-seq cl-start
275 cl-end cl-from-end
)))
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
)))))
281 (setq cl-end
(- (or cl-end
8000000) cl-start
))
286 (cl--check-test cl-item
(car cl-seq
))
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))
294 (if (cl--check-test cl-item
(car (cdr cl-p
)))
296 (setcdr cl-p
(cdr (cdr cl-p
)))
297 (if (= (setq cl-count
(1- cl-count
)) 0)
299 (setq cl-p
(cdr cl-p
)))
300 (setq cl-end
(1- cl-end
)))))
302 (apply 'cl-remove cl-item cl-seq cl-keys
)))))
305 (defun cl-delete-if (cl-pred cl-list
&rest cl-keys
)
306 "Remove all items satisfying PREDICATE in SEQ.
307 This is a destructive function; it reuses the storage of SEQ whenever possible.
308 \nKeywords supported: :key :count :start :end :from-end
309 \n(fn PREDICATE SEQ [KEYWORD VALUE]...)"
310 (apply 'cl-delete nil cl-list
:if cl-pred cl-keys
))
313 (defun cl-delete-if-not (cl-pred cl-list
&rest cl-keys
)
314 "Remove all items not satisfying PREDICATE in SEQ.
315 This is a destructive function; it reuses the storage of SEQ whenever possible.
316 \nKeywords supported: :key :count :start :end :from-end
317 \n(fn PREDICATE SEQ [KEYWORD VALUE]...)"
318 (apply 'cl-delete nil cl-list
:if-not cl-pred cl-keys
))
321 (defun cl-remove-duplicates (cl-seq &rest cl-keys
)
322 "Return a copy of SEQ with all duplicate elements removed.
323 \nKeywords supported: :test :test-not :key :start :end :from-end
324 \n(fn SEQ [KEYWORD VALUE]...)"
325 (cl--delete-duplicates cl-seq cl-keys t
))
328 (defun cl-delete-duplicates (cl-seq &rest cl-keys
)
329 "Remove all duplicate elements from SEQ (destructively).
330 \nKeywords supported: :test :test-not :key :start :end :from-end
331 \n(fn SEQ [KEYWORD VALUE]...)"
332 (cl--delete-duplicates cl-seq cl-keys nil
))
334 (defun cl--delete-duplicates (cl-seq cl-keys cl-copy
)
336 (cl--parsing-keywords (:test
:test-not
:key
(:start
0) :end
:from-end
:if
)
339 (let ((cl-p (nthcdr cl-start cl-seq
)) cl-i
)
340 (setq cl-end
(- (or cl-end
(length cl-seq
)) cl-start
))
343 (while (setq cl-i
(cl--position (cl--check-key (car cl-p
))
344 (cdr cl-p
) cl-i
(1- cl-end
)))
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
)))
353 (setq cl-end
(- (or cl-end
(length cl-seq
)) cl-start
))
354 (while (and (cdr cl-seq
) (= cl-start
0) (> cl-end
1)
355 (cl--position (cl--check-key (car cl-seq
))
356 (cdr cl-seq
) 0 (1- cl-end
)))
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))
361 (if (cl--position (cl--check-key (car (cdr cl-p
)))
362 (cdr (cdr cl-p
)) 0 (1- cl-end
))
364 (if cl-copy
(setq cl-seq
(copy-sequence cl-seq
)
365 cl-p
(nthcdr (1- cl-start
) cl-seq
)
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
)))
371 (let ((cl-res (cl--delete-duplicates (append cl-seq nil
) cl-keys nil
)))
372 (if (stringp cl-seq
) (concat cl-res
) (vconcat cl-res
)))))
375 (defun cl-substitute (cl-new cl-old cl-seq
&rest cl-keys
)
376 "Substitute NEW for OLD in SEQ.
377 This is a non-destructive function; it makes a copy of SEQ if necessary
378 to avoid corrupting the original SEQ.
379 \nKeywords supported: :test :test-not :key :count :start :end :from-end
380 \n(fn NEW OLD SEQ [KEYWORD VALUE]...)"
381 (cl--parsing-keywords (:test
:test-not
:key
:if
:if-not
:count
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))
386 (let ((cl-i (cl--position cl-old cl-seq cl-start cl-end
)))
389 (setq cl-seq
(copy-sequence cl-seq
))
391 (progn (cl--set-elt cl-seq cl-i cl-new
)
392 (setq cl-i
(1+ cl-i
) cl-count
(1- cl-count
))))
393 (apply 'cl-nsubstitute cl-new cl-old cl-seq
:count cl-count
394 :start cl-i cl-keys
))))))
397 (defun cl-substitute-if (cl-new cl-pred cl-list
&rest cl-keys
)
398 "Substitute NEW for all items satisfying PREDICATE in SEQ.
399 This is a non-destructive function; it makes a copy of SEQ if necessary
400 to avoid corrupting the original SEQ.
401 \nKeywords supported: :key :count :start :end :from-end
402 \n(fn NEW PREDICATE SEQ [KEYWORD VALUE]...)"
403 (apply 'cl-substitute cl-new nil cl-list
:if cl-pred cl-keys
))
406 (defun cl-substitute-if-not (cl-new cl-pred cl-list
&rest cl-keys
)
407 "Substitute NEW for all items not satisfying PREDICATE in SEQ.
408 This is a non-destructive function; it makes a copy of SEQ if necessary
409 to avoid corrupting the original SEQ.
410 \nKeywords supported: :key :count :start :end :from-end
411 \n(fn NEW PREDICATE SEQ [KEYWORD VALUE]...)"
412 (apply 'cl-substitute cl-new nil cl-list
:if-not cl-pred cl-keys
))
415 (defun cl-nsubstitute (cl-new cl-old cl-seq
&rest cl-keys
)
416 "Substitute NEW for OLD in SEQ.
417 This is a destructive function; it reuses the storage of SEQ whenever possible.
418 \nKeywords supported: :test :test-not :key :count :start :end :from-end
419 \n(fn NEW OLD SEQ [KEYWORD VALUE]...)"
420 (cl--parsing-keywords (:test
:test-not
:key
:if
:if-not
:count
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))
427 (if (cl--check-test cl-old
(car cl-p
))
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
)))
434 (while (and (< cl-start cl-end
) (> cl-count
0))
435 (setq cl-end
(1- cl-end
))
436 (if (cl--check-test cl-old
(elt cl-seq cl-end
))
438 (cl--set-elt cl-seq cl-end cl-new
)
439 (setq cl-count
(1- cl-count
)))))
440 (while (and (< cl-start cl-end
) (> cl-count
0))
441 (if (cl--check-test cl-old
(aref cl-seq cl-start
))
443 (aset cl-seq cl-start cl-new
)
444 (setq cl-count
(1- cl-count
))))
445 (setq cl-start
(1+ cl-start
))))))
449 (defun cl-nsubstitute-if (cl-new cl-pred cl-list
&rest cl-keys
)
450 "Substitute NEW for all items satisfying PREDICATE in SEQ.
451 This is a destructive function; it reuses the storage of SEQ whenever possible.
452 \nKeywords supported: :key :count :start :end :from-end
453 \n(fn NEW PREDICATE SEQ [KEYWORD VALUE]...)"
454 (apply 'cl-nsubstitute cl-new nil cl-list
:if cl-pred cl-keys
))
457 (defun cl-nsubstitute-if-not (cl-new cl-pred cl-list
&rest cl-keys
)
458 "Substitute NEW for all items not satisfying PREDICATE in SEQ.
459 This is a destructive function; it reuses the storage of SEQ whenever possible.
460 \nKeywords supported: :key :count :start :end :from-end
461 \n(fn NEW PREDICATE SEQ [KEYWORD VALUE]...)"
462 (apply 'cl-nsubstitute cl-new nil cl-list
:if-not cl-pred cl-keys
))
465 (defun cl-find (cl-item cl-seq
&rest cl-keys
)
466 "Find the first occurrence of ITEM in SEQ.
467 Return the matching ITEM, or nil if not found.
468 \nKeywords supported: :test :test-not :key :start :end :from-end
469 \n(fn ITEM SEQ [KEYWORD VALUE]...)"
470 (let ((cl-pos (apply 'cl-position cl-item cl-seq cl-keys
)))
471 (and cl-pos
(elt cl-seq cl-pos
))))
474 (defun cl-find-if (cl-pred cl-list
&rest cl-keys
)
475 "Find the first item satisfying PREDICATE in SEQ.
476 Return the matching item, or nil if not found.
477 \nKeywords supported: :key :start :end :from-end
478 \n(fn PREDICATE SEQ [KEYWORD VALUE]...)"
479 (apply 'cl-find nil cl-list
:if cl-pred cl-keys
))
482 (defun cl-find-if-not (cl-pred cl-list
&rest cl-keys
)
483 "Find the first item not satisfying PREDICATE in SEQ.
484 Return the matching item, or nil if not found.
485 \nKeywords supported: :key :start :end :from-end
486 \n(fn PREDICATE SEQ [KEYWORD VALUE]...)"
487 (apply 'cl-find nil cl-list
:if-not cl-pred cl-keys
))
490 (defun cl-position (cl-item cl-seq
&rest cl-keys
)
491 "Find the first occurrence of ITEM in SEQ.
492 Return the index of the matching item, or nil if not found.
493 \nKeywords supported: :test :test-not :key :start :end :from-end
494 \n(fn ITEM SEQ [KEYWORD VALUE]...)"
495 (cl--parsing-keywords (:test
:test-not
:key
:if
:if-not
496 (:start
0) :end
:from-end
) ()
497 (cl--position cl-item cl-seq cl-start cl-end cl-from-end
)))
499 (defun cl--position (cl-item cl-seq cl-start
&optional cl-end cl-from-end
)
501 (let ((cl-p (nthcdr cl-start cl-seq
)))
502 (or cl-end
(setq cl-end
8000000))
504 (while (and cl-p
(< cl-start cl-end
) (or (not cl-res
) cl-from-end
))
505 (if (cl--check-test cl-item
(car cl-p
))
506 (setq cl-res cl-start
))
507 (setq cl-p
(cdr cl-p
) cl-start
(1+ cl-start
)))
509 (or cl-end
(setq cl-end
(length cl-seq
)))
512 (while (and (>= (setq cl-end
(1- cl-end
)) cl-start
)
513 (not (cl--check-test cl-item
(aref cl-seq cl-end
)))))
514 (and (>= cl-end cl-start
) cl-end
))
515 (while (and (< cl-start cl-end
)
516 (not (cl--check-test cl-item
(aref cl-seq cl-start
))))
517 (setq cl-start
(1+ cl-start
)))
518 (and (< cl-start cl-end
) cl-start
))))
521 (defun cl-position-if (cl-pred cl-list
&rest cl-keys
)
522 "Find the first item satisfying PREDICATE in SEQ.
523 Return the index of the matching item, or nil if not found.
524 \nKeywords supported: :key :start :end :from-end
525 \n(fn PREDICATE SEQ [KEYWORD VALUE]...)"
526 (apply 'cl-position nil cl-list
:if cl-pred cl-keys
))
529 (defun cl-position-if-not (cl-pred cl-list
&rest cl-keys
)
530 "Find the first item not satisfying PREDICATE in SEQ.
531 Return the index of the matching item, or nil if not found.
532 \nKeywords supported: :key :start :end :from-end
533 \n(fn PREDICATE SEQ [KEYWORD VALUE]...)"
534 (apply 'cl-position nil cl-list
:if-not cl-pred cl-keys
))
537 (defun cl-count (cl-item cl-seq
&rest cl-keys
)
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]...)"
541 (cl--parsing-keywords (:test
:test-not
:key
:if
:if-not
(:start
0) :end
) ()
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
)
546 (setq cl-x
(if (consp cl-seq
) (pop cl-seq
) (aref cl-seq cl-start
)))
547 (if (cl--check-test cl-item cl-x
) (setq cl-count
(1+ cl-count
)))
548 (setq cl-start
(1+ cl-start
)))
552 (defun cl-count-if (cl-pred cl-list
&rest cl-keys
)
553 "Count the number of items satisfying PREDICATE in SEQ.
554 \nKeywords supported: :key :start :end
555 \n(fn PREDICATE SEQ [KEYWORD VALUE]...)"
556 (apply 'cl-count nil cl-list
:if cl-pred cl-keys
))
559 (defun cl-count-if-not (cl-pred cl-list
&rest cl-keys
)
560 "Count the number of items not satisfying PREDICATE in SEQ.
561 \nKeywords supported: :key :start :end
562 \n(fn PREDICATE SEQ [KEYWORD VALUE]...)"
563 (apply 'cl-count nil cl-list
:if-not cl-pred cl-keys
))
566 (defun cl-mismatch (cl-seq1 cl-seq2
&rest cl-keys
)
567 "Compare SEQ1 with SEQ2, return index of first mismatching element.
568 Return nil if the sequences match. If one sequence is a prefix of the
569 other, the return value indicates the end of the shorter sequence.
570 \nKeywords supported: :test :test-not :key :start1 :end1 :start2 :end2 :from-end
571 \n(fn SEQ1 SEQ2 [KEYWORD VALUE]...)"
572 (cl--parsing-keywords (:test
:test-not
:key
:from-end
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
)))
578 (while (and (< cl-start1 cl-end1
) (< cl-start2 cl-end2
)
579 (cl--check-match (elt cl-seq1
(1- cl-end1
))
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
))
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
)
587 (cl--check-match (if cl-p1
(car cl-p1
)
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
))
597 (defun cl-search (cl-seq1 cl-seq2
&rest cl-keys
)
598 "Search for SEQ1 as a subsequence of SEQ2.
599 Return the index of the leftmost element of the first match found;
600 return nil if there are no matches.
601 \nKeywords supported: :test :test-not :key :start1 :end1 :start2 :end2 :from-end
602 \n(fn SEQ1 SEQ2 [KEYWORD VALUE]...)"
603 (cl--parsing-keywords (:test
:test-not
:key
:from-end
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
))
610 (cl-first (cl--check-key (elt cl-seq1 cl-start1
)))
612 (setq cl-end2
(- cl-end2
(1- cl-len
)))
613 (while (and (< cl-start2 cl-end2
)
614 (setq cl-pos
(cl--position cl-first cl-seq2
615 cl-start2 cl-end2 cl-from-end
))
616 (apply 'cl-mismatch cl-seq1 cl-seq2
617 :start1
(1+ cl-start1
) :end1 cl-end1
618 :start2
(1+ cl-pos
) :end2
(+ cl-pos cl-len
)
619 :from-end nil cl-keys
))
620 (if cl-from-end
(setq cl-end2 cl-pos
) (setq cl-start2
(1+ cl-pos
))))
621 (and (< cl-start2 cl-end2
) cl-pos
)))))
624 (defun cl-sort (cl-seq cl-pred
&rest cl-keys
)
625 "Sort the argument SEQ according to PREDICATE.
626 This is a destructive function; it reuses the storage of SEQ if possible.
627 \nKeywords supported: :key
628 \n(fn SEQ PREDICATE [KEYWORD VALUE]...)"
630 (cl-replace cl-seq
(apply 'cl-sort
(append cl-seq nil
) cl-pred cl-keys
))
631 (cl--parsing-keywords (:key
) ()
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
)))))))))
639 (defun cl-stable-sort (cl-seq cl-pred
&rest cl-keys
)
640 "Sort the argument SEQ stably according to PREDICATE.
641 This is a destructive function; it reuses the storage of SEQ if possible.
642 \nKeywords supported: :key
643 \n(fn SEQ PREDICATE [KEYWORD VALUE]...)"
644 (apply 'cl-sort cl-seq cl-pred cl-keys
))
647 (defun cl-merge (cl-type cl-seq1 cl-seq2 cl-pred
&rest cl-keys
)
648 "Destructively merge the two sequences to produce a new sequence.
649 TYPE is the sequence type to return, SEQ1 and SEQ2 are the two argument
650 sequences, and PREDICATE is a `less-than' predicate on the elements.
651 \nKeywords supported: :key
652 \n(fn TYPE SEQ1 SEQ2 PREDICATE [KEYWORD VALUE]...)"
653 (or (listp cl-seq1
) (setq cl-seq1
(append cl-seq1 nil
)))
654 (or (listp cl-seq2
) (setq cl-seq2
(append cl-seq2 nil
)))
655 (cl--parsing-keywords (:key
) ()
657 (while (and cl-seq1 cl-seq2
)
658 (if (funcall cl-pred
(cl--check-key (car cl-seq2
))
659 (cl--check-key (car cl-seq1
)))
660 (push (pop cl-seq2
) cl-res
)
661 (push (pop cl-seq1
) cl-res
)))
662 (cl-coerce (nconc (nreverse cl-res
) cl-seq1 cl-seq2
) cl-type
))))
665 (defun cl-member (cl-item cl-list
&rest cl-keys
)
666 "Find the first occurrence of ITEM in LIST.
667 Return the sublist of LIST whose car is ITEM.
668 \nKeywords supported: :test :test-not :key
669 \n(fn ITEM LIST [KEYWORD VALUE]...)"
670 (declare (compiler-macro cl--compiler-macro-member
))
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
))))
674 (setq cl-list
(cdr cl-list
)))
676 (if (and (numberp cl-item
) (not (integerp cl-item
)))
677 (member cl-item cl-list
)
678 (memq cl-item cl-list
))))
679 (autoload 'cl--compiler-macro-member
"cl-macs")
682 (defun cl-member-if (cl-pred cl-list
&rest cl-keys
)
683 "Find the first item satisfying PREDICATE in LIST.
684 Return the sublist of LIST whose car matches.
685 \nKeywords supported: :key
686 \n(fn PREDICATE LIST [KEYWORD VALUE]...)"
687 (apply 'cl-member nil cl-list
:if cl-pred cl-keys
))
690 (defun cl-member-if-not (cl-pred cl-list
&rest cl-keys
)
691 "Find the first item not satisfying PREDICATE in LIST.
692 Return the sublist of LIST whose car matches.
693 \nKeywords supported: :key
694 \n(fn PREDICATE LIST [KEYWORD VALUE]...)"
695 (apply 'cl-member nil cl-list
:if-not cl-pred cl-keys
))
698 (defun cl--adjoin (cl-item cl-list
&rest cl-keys
)
699 (if (cl--parsing-keywords (:key
) t
700 (apply 'cl-member
(cl--check-key cl-item
) cl-list cl-keys
))
702 (cons cl-item cl-list
)))
705 (defun cl-assoc (cl-item cl-alist
&rest cl-keys
)
706 "Find the first item whose car matches ITEM in LIST.
707 \nKeywords supported: :test :test-not :key
708 \n(fn ITEM LIST [KEYWORD VALUE]...)"
709 (declare (compiler-macro cl--compiler-macro-assoc
))
711 (cl--parsing-keywords (:test
:test-not
:key
:if
:if-not
) ()
713 (or (not (consp (car cl-alist
)))
714 (not (cl--check-test cl-item
(car (car cl-alist
))))))
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
))))
720 (autoload 'cl--compiler-macro-assoc
"cl-macs")
723 (defun cl-assoc-if (cl-pred cl-list
&rest cl-keys
)
724 "Find the first item whose car satisfies PREDICATE in LIST.
725 \nKeywords supported: :key
726 \n(fn PREDICATE LIST [KEYWORD VALUE]...)"
727 (apply 'cl-assoc nil cl-list
:if cl-pred cl-keys
))
730 (defun cl-assoc-if-not (cl-pred cl-list
&rest cl-keys
)
731 "Find the first item whose car does not satisfy PREDICATE in LIST.
732 \nKeywords supported: :key
733 \n(fn PREDICATE LIST [KEYWORD VALUE]...)"
734 (apply 'cl-assoc nil cl-list
:if-not cl-pred cl-keys
))
737 (defun cl-rassoc (cl-item cl-alist
&rest cl-keys
)
738 "Find the first item whose cdr matches ITEM in LIST.
739 \nKeywords supported: :test :test-not :key
740 \n(fn ITEM LIST [KEYWORD VALUE]...)"
741 (if (or cl-keys
(numberp cl-item
))
742 (cl--parsing-keywords (:test
:test-not
:key
:if
:if-not
) ()
744 (or (not (consp (car cl-alist
)))
745 (not (cl--check-test cl-item
(cdr (car cl-alist
))))))
746 (setq cl-alist
(cdr cl-alist
)))
747 (and cl-alist
(car cl-alist
)))
748 (rassq cl-item cl-alist
)))
751 (defun cl-rassoc-if (cl-pred cl-list
&rest cl-keys
)
752 "Find the first item whose cdr satisfies PREDICATE in LIST.
753 \nKeywords supported: :key
754 \n(fn PREDICATE LIST [KEYWORD VALUE]...)"
755 (apply 'cl-rassoc nil cl-list
:if cl-pred cl-keys
))
758 (defun cl-rassoc-if-not (cl-pred cl-list
&rest cl-keys
)
759 "Find the first item whose cdr does not satisfy PREDICATE in LIST.
760 \nKeywords supported: :key
761 \n(fn PREDICATE LIST [KEYWORD VALUE]...)"
762 (apply 'cl-rassoc nil cl-list
:if-not cl-pred cl-keys
))
765 (defun cl-union (cl-list1 cl-list2
&rest cl-keys
)
766 "Combine LIST1 and LIST2 using a set-union operation.
767 The resulting list contains all items that appear in either LIST1 or LIST2.
768 This is a non-destructive function; it makes a copy of the data if necessary
769 to avoid corrupting the original LIST1 and LIST2.
770 \nKeywords supported: :test :test-not :key
771 \n(fn LIST1 LIST2 [KEYWORD VALUE]...)"
772 (cond ((null cl-list1
) cl-list2
) ((null cl-list2
) cl-list1
)
773 ((equal cl-list1 cl-list2
) cl-list1
)
775 (or (>= (length cl-list1
) (length cl-list2
))
776 (setq cl-list1
(prog1 cl-list2
(setq cl-list2 cl-list1
))))
778 (if (or cl-keys
(numberp (car cl-list2
)))
779 (setq cl-list1
(apply 'cl-adjoin
(car cl-list2
) cl-list1 cl-keys
))
780 (or (memq (car cl-list2
) cl-list1
)
781 (push (car cl-list2
) cl-list1
)))
786 (defun cl-nunion (cl-list1 cl-list2
&rest cl-keys
)
787 "Combine LIST1 and LIST2 using a set-union operation.
788 The resulting list contains all items that appear in either LIST1 or LIST2.
789 This is a destructive function; it reuses the storage of LIST1 and LIST2
791 \nKeywords supported: :test :test-not :key
792 \n(fn LIST1 LIST2 [KEYWORD VALUE]...)"
793 (cond ((null cl-list1
) cl-list2
) ((null cl-list2
) cl-list1
)
794 (t (apply 'cl-union cl-list1 cl-list2 cl-keys
))))
797 (defun cl-intersection (cl-list1 cl-list2
&rest cl-keys
)
798 "Combine LIST1 and LIST2 using a set-intersection operation.
799 The resulting list contains all items that appear in both LIST1 and LIST2.
800 This is a non-destructive function; it makes a copy of the data if necessary
801 to avoid corrupting the original LIST1 and LIST2.
802 \nKeywords supported: :test :test-not :key
803 \n(fn LIST1 LIST2 [KEYWORD VALUE]...)"
804 (and cl-list1 cl-list2
805 (if (equal cl-list1 cl-list2
) cl-list1
806 (cl--parsing-keywords (:key
) (:test
:test-not
)
808 (or (>= (length cl-list1
) (length cl-list2
))
809 (setq cl-list1
(prog1 cl-list2
(setq cl-list2 cl-list1
))))
811 (if (if (or cl-keys
(numberp (car cl-list2
)))
812 (apply 'cl-member
(cl--check-key (car cl-list2
))
814 (memq (car cl-list2
) cl-list1
))
815 (push (car cl-list2
) cl-res
))
820 (defun cl-nintersection (cl-list1 cl-list2
&rest cl-keys
)
821 "Combine LIST1 and LIST2 using a set-intersection operation.
822 The resulting list contains all items that appear in both LIST1 and LIST2.
823 This is a destructive function; it reuses the storage of LIST1 and LIST2
825 \nKeywords supported: :test :test-not :key
826 \n(fn LIST1 LIST2 [KEYWORD VALUE]...)"
827 (and cl-list1 cl-list2
(apply 'cl-intersection cl-list1 cl-list2 cl-keys
)))
830 (defun cl-set-difference (cl-list1 cl-list2
&rest cl-keys
)
831 "Combine LIST1 and LIST2 using a set-difference operation.
832 The resulting list contains all items that appear in LIST1 but not LIST2.
833 This is a non-destructive function; it makes a copy of the data if necessary
834 to avoid corrupting the original LIST1 and LIST2.
835 \nKeywords supported: :test :test-not :key
836 \n(fn LIST1 LIST2 [KEYWORD VALUE]...)"
837 (if (or (null cl-list1
) (null cl-list2
)) cl-list1
838 (cl--parsing-keywords (:key
) (:test
:test-not
)
841 (or (if (or cl-keys
(numberp (car cl-list1
)))
842 (apply 'cl-member
(cl--check-key (car cl-list1
))
844 (memq (car cl-list1
) cl-list2
))
845 (push (car cl-list1
) cl-res
))
850 (defun cl-nset-difference (cl-list1 cl-list2
&rest cl-keys
)
851 "Combine LIST1 and LIST2 using a set-difference operation.
852 The resulting list contains all items that appear in LIST1 but not LIST2.
853 This is a destructive function; it reuses the storage of LIST1 and LIST2
855 \nKeywords supported: :test :test-not :key
856 \n(fn LIST1 LIST2 [KEYWORD VALUE]...)"
857 (if (or (null cl-list1
) (null cl-list2
)) cl-list1
858 (apply 'cl-set-difference cl-list1 cl-list2 cl-keys
)))
861 (defun cl-set-exclusive-or (cl-list1 cl-list2
&rest cl-keys
)
862 "Combine LIST1 and LIST2 using a set-exclusive-or operation.
863 The resulting list contains all items appearing in exactly one of LIST1, LIST2.
864 This is a non-destructive function; it makes a copy of the data if necessary
865 to avoid corrupting the original LIST1 and LIST2.
866 \nKeywords supported: :test :test-not :key
867 \n(fn LIST1 LIST2 [KEYWORD VALUE]...)"
868 (cond ((null cl-list1
) cl-list2
) ((null cl-list2
) cl-list1
)
869 ((equal cl-list1 cl-list2
) nil
)
870 (t (append (apply 'cl-set-difference cl-list1 cl-list2 cl-keys
)
871 (apply 'cl-set-difference cl-list2 cl-list1 cl-keys
)))))
874 (defun cl-nset-exclusive-or (cl-list1 cl-list2
&rest cl-keys
)
875 "Combine LIST1 and LIST2 using a set-exclusive-or operation.
876 The resulting list contains all items appearing in exactly one of LIST1, LIST2.
877 This is a destructive function; it reuses the storage of LIST1 and LIST2
879 \nKeywords supported: :test :test-not :key
880 \n(fn LIST1 LIST2 [KEYWORD VALUE]...)"
881 (cond ((null cl-list1
) cl-list2
) ((null cl-list2
) cl-list1
)
882 ((equal cl-list1 cl-list2
) nil
)
883 (t (nconc (apply 'cl-nset-difference cl-list1 cl-list2 cl-keys
)
884 (apply 'cl-nset-difference cl-list2 cl-list1 cl-keys
)))))
887 (defun cl-subsetp (cl-list1 cl-list2
&rest cl-keys
)
888 "Return true if LIST1 is a subset of LIST2.
889 I.e., if every element of LIST1 also appears in LIST2.
890 \nKeywords supported: :test :test-not :key
891 \n(fn LIST1 LIST2 [KEYWORD VALUE]...)"
892 (cond ((null cl-list1
) t
) ((null cl-list2
) nil
)
893 ((equal cl-list1 cl-list2
) t
)
894 (t (cl--parsing-keywords (:key
) (:test
:test-not
)
896 (apply 'cl-member
(cl--check-key (car cl-list1
))
902 (defun cl-subst-if (cl-new cl-pred cl-tree
&rest cl-keys
)
903 "Substitute NEW for elements matching PREDICATE in TREE (non-destructively).
904 Return a copy of TREE with all matching elements replaced by NEW.
905 \nKeywords supported: :key
906 \n(fn NEW PREDICATE TREE [KEYWORD VALUE]...)"
907 (apply 'cl-sublis
(list (cons nil cl-new
)) cl-tree
:if cl-pred cl-keys
))
910 (defun cl-subst-if-not (cl-new cl-pred cl-tree
&rest cl-keys
)
911 "Substitute NEW for elts not matching PREDICATE in TREE (non-destructively).
912 Return a copy of TREE with all non-matching elements replaced by NEW.
913 \nKeywords supported: :key
914 \n(fn NEW PREDICATE TREE [KEYWORD VALUE]...)"
915 (apply 'cl-sublis
(list (cons nil cl-new
)) cl-tree
:if-not cl-pred cl-keys
))
918 (defun cl-nsubst (cl-new cl-old cl-tree
&rest cl-keys
)
919 "Substitute NEW for OLD everywhere in TREE (destructively).
920 Any element of TREE which is `eql' to OLD is changed to NEW (via a call
922 \nKeywords supported: :test :test-not :key
923 \n(fn NEW OLD TREE [KEYWORD VALUE]...)"
924 (apply 'cl-nsublis
(list (cons cl-old cl-new
)) cl-tree cl-keys
))
927 (defun cl-nsubst-if (cl-new cl-pred cl-tree
&rest cl-keys
)
928 "Substitute NEW for elements matching PREDICATE in TREE (destructively).
929 Any element of TREE which matches is changed to NEW (via a call to `setcar').
930 \nKeywords supported: :key
931 \n(fn NEW PREDICATE TREE [KEYWORD VALUE]...)"
932 (apply 'cl-nsublis
(list (cons nil cl-new
)) cl-tree
:if cl-pred cl-keys
))
935 (defun cl-nsubst-if-not (cl-new cl-pred cl-tree
&rest cl-keys
)
936 "Substitute NEW for elements not matching PREDICATE in TREE (destructively).
937 Any element of TREE which matches is changed to NEW (via a call to `setcar').
938 \nKeywords supported: :key
939 \n(fn NEW PREDICATE TREE [KEYWORD VALUE]...)"
940 (apply 'cl-nsublis
(list (cons nil cl-new
)) cl-tree
:if-not cl-pred cl-keys
))
945 (defun cl-sublis (cl-alist cl-tree
&rest cl-keys
)
946 "Perform substitutions indicated by ALIST in TREE (non-destructively).
947 Return a copy of TREE with all matching elements replaced.
948 \nKeywords supported: :test :test-not :key
949 \n(fn ALIST TREE [KEYWORD VALUE]...)"
950 (cl--parsing-keywords (:test
:test-not
:key
:if
:if-not
) ()
951 (let ((cl--alist cl-alist
))
952 (cl--sublis-rec cl-tree
))))
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
)))
957 (setq cl-p
(cdr cl-p
)))
958 (if cl-p
(cdr (car cl-p
))
960 (let ((cl-a (cl--sublis-rec (car cl-tree
)))
961 (cl-d (cl--sublis-rec (cdr cl-tree
))))
962 (if (and (eq cl-a
(car cl-tree
)) (eq cl-d
(cdr cl-tree
)))
968 (defun cl-nsublis (cl-alist cl-tree
&rest cl-keys
)
969 "Perform substitutions indicated by ALIST in TREE (destructively).
970 Any matching element of TREE is changed via a call to `setcar'.
971 \nKeywords supported: :test :test-not :key
972 \n(fn ALIST TREE [KEYWORD VALUE]...)"
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
)
979 (defun cl--nsublis-rec (cl-tree) ;Uses cl--alist cl-key/test*/if*.
980 (while (consp cl-tree
)
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
)))
983 (setq cl-p
(cdr cl-p
)))
984 (if cl-p
(setcar cl-tree
(cdr (car cl-p
)))
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
)))
988 (setq cl-p
(cdr cl-p
)))
990 (progn (setcdr cl-tree
(cdr (car cl-p
))) (setq cl-tree nil
))
991 (setq cl-tree
(cdr cl-tree
))))))
994 (defun cl-tree-equal (cl-x cl-y
&rest cl-keys
)
995 "Return t if trees TREE1 and TREE2 have `eql' leaves.
996 Atoms are compared by `eql'; cons cells are compared recursively.
997 \nKeywords supported: :test :test-not :key
998 \n(fn TREE1 TREE2 [KEYWORD VALUE]...)"
999 (cl--parsing-keywords (:test
:test-not
:key
) ()
1000 (cl--tree-equal-rec cl-x cl-y
)))
1002 (defun cl--tree-equal-rec (cl-x cl-y
) ;Uses cl-key/test*.
1003 (while (and (consp cl-x
) (consp cl-y
)
1004 (cl--tree-equal-rec (car cl-x
) (car cl-y
)))
1005 (setq cl-x
(cdr cl-x
) cl-y
(cdr cl-y
)))
1006 (and (not (consp cl-x
)) (not (consp cl-y
)) (cl--check-match cl-x cl-y
)))
1009 (run-hooks 'cl-seq-load-hook
)
1012 ;; byte-compile-dynamic: t
1013 ;; generated-autoload-file: "cl-loaddefs.el"
1016 ;;; cl-seq.el ends here