1 (in-package :alexandria
)
3 (defun rotate-tail-to-head (sequence n
)
4 (declare (type (integer 1) n
))
6 (let ((m (mod n
(list-length sequence
))))
7 (if (null (cdr sequence
))
9 (let* ((tail (last sequence
(+ m
1)))
12 (nconc last sequence
))))
13 (let* ((len (length sequence
))
15 (tail (subseq sequence
(- len m
))))
16 (replace sequence sequence
:start1 m
:start2
0)
17 (replace sequence tail
)
20 (defun rotate-head-to-tail (sequence n
)
21 (declare (type (integer 1) n
))
23 (let ((m (mod (1- n
) (list-length sequence
))))
24 (if (null (cdr sequence
))
26 (let* ((headtail (nthcdr m sequence
))
27 (tail (cdr headtail
)))
28 (setf (cdr headtail
) nil
)
29 (nconc tail sequence
))))
30 (let* ((len (length sequence
))
32 (head (subseq sequence
0 m
)))
33 (replace sequence sequence
:start1
0 :start2 m
)
34 (replace sequence head
:start1
(- len m
))
37 (defun rotate (sequence &optional
(n 1))
38 "Returns a sequence of the same type as SEQUENCE, with the elements of
39 SEQUENCE rotated by N: N elements are moved from the end of the sequence to
40 the front if N is positive, and -N elements moved from the front to the end if
41 N is negative. SEQUENCE must be a proper sequence. N must be an integer,
42 defaulting to 1. If absolute value of N is greater then the length of the
43 sequence, the results are identical to calling ROTATE with (* (SIGNUM N) (MOD
44 N (LENGTH SEQUENCE))). The original sequence may be destructively altered, and
45 result sequence may share structure with it."
47 (rotate-tail-to-head sequence n
)
49 (rotate-head-to-tail sequence
(- n
))
52 (defun shuffle (sequence &key
(start 0) end
)
53 "Returns a random permutation of SEQUENCE bounded by START and END.
54 Permuted sequence may share storage with the original one. Signals
55 an error if SEQUENCE is not a proper sequence."
56 (declare (fixnum start
) ((or fixnum null
) end
))
57 (let ((end (or end
(if (listp sequence
) (list-length sequence
) (length sequence
)))))
58 (loop for i from start below end
59 do
(rotatef (elt sequence i
) (elt sequence
(random end
)))))
62 (defun random-elt (sequence &key
(start 0) end
)
63 "Returns a random element from SEQUENCE bounded by START and END. Signals an
64 error if the SEQUENCE is not a proper sequence."
65 (declare (sequence sequence
) (fixnum start
) ((or fixnum null
) end
))
66 (let ((i (+ start
(random (- (or end
(if (listp sequence
)
67 (list-length sequence
)
72 (define-modify-macro removef
(item &rest remove-keywords
)
73 (lambda (seq item
&rest keyword-arguments
)
74 (apply #'remove item seq keyword-arguments
))
75 "Modify-macro for REMOVE. Sets place designated by the first argument to
76 the result of calling REMOVE with ITEM, place, and the REMOVE-KEYWORDS.")
78 (define-modify-macro deletef
(item &rest remove-keywords
)
79 (lambda (seq item
&rest keyword-arguments
)
80 (apply #'delete item seq keyword-arguments
))
81 "Modify-macro for DELETE. Sets place designated by the first argument to
82 the result of calling DELETE with ITEM, place, and the REMOVE-KEYWORDS.")
84 (deftype proper-sequence
()
85 "Type designator for proper sequences, that is proper lists and sequences
88 (and (not list
) sequence
)))
90 (defun emptyp (sequence)
91 "Returns true if SEQUENCE is an empty sequence. Signals an error if SEQUENCE
94 (list (null sequence
))
95 (sequence (zerop (length sequence
)))))
97 (defun sequence-of-length-p (sequence length
)
98 "Return true if SEQUENCE is a sequence of length LENGTH. Signals an error if
99 SEQUENCE is not a sequence. Returns FALSE for circular lists."
104 (let ((n (1- length
)))
106 (let ((tail (nthcdr n sequence
)))
107 (and tail
(null (cdr tail
)))))))
109 (= length
(length sequence
)))))
111 (declaim (inline copy-sequence
))
112 (defun copy-sequence (type sequence
)
113 "Returns a fresh sequence of TYPE, which has the same elements as
115 (if (typep sequence type
)
117 (coerce sequence type
)))
119 (defun first-elt (sequence)
120 "Returns the first element of SEQUENCE. Signals a type-error if SEQUENCE is
121 not a sequence, or is an empty sequence."
122 ;; Can't just directly use ELT, as it is not guaranteed to signal the
124 (cond ((consp sequence
)
126 ((and (typep sequence
'(and sequence
(not list
))) (plusp (length sequence
)))
131 :expected-type
'(and sequence
(not (satisfies emptyp
)))))))
133 (defun (setf first-elt
) (object sequence
)
134 "Sets the first element of SEQUENCE. Signals a type-error if SEQUENCE is
135 not a sequence, is an empty sequence, or if OBJECT cannot be stored in SEQUENCE."
136 ;; Can't just directly use ELT, as it is not guaranteed to signal the
138 (cond ((consp sequence
)
139 (setf (car sequence
) object
))
140 ((and (typep sequence
'(and sequence
(not list
))) (plusp (length sequence
)))
141 (setf (elt sequence
0) object
))
145 :expected-type
'(and proper-sequence
(not (satisfies emptyp
)))))))
147 (defun last-elt (sequence)
148 "Returns the last element of SEQUENCE. Signals a type-error if SEQUENCE is
149 not a proper sequence, or is an empty sequence."
150 ;; Can't just directly use ELT, as it is not guaranteed to signal the
153 (cond ((consp sequence
)
155 ((and (typep sequence
'(and sequence
(not list
))) (plusp (setf len
(length sequence
))))
156 (elt sequence
(1- len
)))
160 :expected-type
'(and proper-sequence
(not (satisfies emptyp
))))))))
162 (defun (setf last-elt
) (object sequence
)
163 "Sets the last element of SEQUENCE. Signals a type-error if SEQUENCE is not a proper
164 sequence, is an empty sequence, or if OBJECT cannot be stored in SEQUENCE."
166 (cond ((consp sequence
)
167 (setf (lastcar sequence
) object
))
168 ((and (typep sequence
'(and sequence
(not list
))) (plusp (setf len
(length sequence
))))
169 (setf (elt sequence
(1- len
)) object
))
173 :expected-type
'(and proper-sequence
(not (satisfies emptyp
))))))))
175 (defun starts-with (object sequence
&key
(test #'eql
) (key #'identity
))
176 "Returns true if SEQUENCE is a sequence whose first element is EQL to OBJECT.
177 Returns NIL if the SEQUENCE is not a sequence or is an empty sequence."
181 (cons (car sequence
))
183 (if (plusp (length sequence
))
185 (return-from starts-with nil
)))
187 (return-from starts-with nil
))))
190 (defun ends-with (object sequence
&key
(test #'eql
) (key #'identity
))
191 "Returns true if SEQUENCE is a sequence whose last element is EQL to OBJECT.
192 Returns NIL if the SEQUENCE is not a sequence or is an empty sequence. Signals
193 an error if SEQUENCE is an improper list."
198 ;; signals for improper lists
201 ;; Can't use last-elt, as that signals an error for empty sequences
202 (let ((len (length sequence
)))
204 (elt sequence
(1- len
))
205 (return-from ends-with nil
))))
207 (return-from ends-with nil
))))