comparison lisp/cl-extra.el @ 4995:8431b52e43b1

Move the various map* functions to C; add #'map-into. src/ChangeLog addition: 2010-01-31 Aidan Kehoe <kehoea@parhasard.net> Move #'mapcar*, #'mapcan, #'mapc, #'map, #'mapl, #'mapcon to C; extend #'mapvector, #'mapconcat, #'mapcar to support more SEQUENCES; have them all error with circular lists. * fns.c (Fsubseq): Call CHECK_SEQUENCE here; Flength can return from the debugger if it errors with a non-sequence, leading to a crash in Fsubseq if sequence really is *not* a sequence. (mapcarX): Rename mapcar1 to mapcarX; rework it comprehensively to take an optional lisp output argument, and a varying number of sequences. Special-case a single list argument, as we used to, saving its elements in the stack space for the results before calling FUNCTION, so FUNCTION can corrupt the list all it wants. dead_wrong_type_argument() in the other cases if we encounter a non-cons where we expected a cons. (Fmapconcat): Accept further SEQUENCES after separator here. Special-case the idiom (mapconcat 'identity SEQUENCE), don't even funcall. (FmapcarX): Rename this from Fmapcar. Accept optional SEQUENCES. (Fmapvector): Accept optional SEQUENCES. (Fmapcan, Fmapc, Fmap): Move these here from cl-extra.el. (Fmap_into): New function, as specified by Common Lisp. (maplist): New function, the guts of the implementation of Fmaplist and Fmapl. (Fmaplist, Fmapl, Fmapcon): Move these from cl-extra.el. (syms_of_fns): Add a few needed symbols here, for the type tests used by #'map. Add the new subrs, with aliases for #'mapc-internal and #'mapcar. * general-slots.h: Declare Qcoerce here, now it's used in both indent.c and fns.c * indent.c (syms_of_indent): Qcoerce is gone from here. * lisp.h: Add ARRAYP(), SEQUENCEP(), and the corresponding CHECK_* macros. Declare Fbit_vector, Fstring, FmapcarX, now other files need to use them. * data.c (Farrayp, Fsequencep): Use ARRAYP and SEQUENCEP, just added to lisp.h * buffer.c (Fbuffer_list): Now Fmapcar has been renamed FmapcarX and takes MANY arguments, update this function to reflect that. lisp/ChangeLog addition: 2010-01-31 Aidan Kehoe <kehoea@parhasard.net> * cl.el (mapcar*): Delete; this is now in fns.c. Use #'mapc, not #'mapc-internal in a couple of places. * cl-macs.el (mapc, mapcar*, map): Delete these compiler macros now the corresponding functions are in fns.c; there's no run-time advantage to the macros. * cl-extra.el (coerce): Extend the possible conversions here a little; it's not remotely comprehensive yet, though it does allow running slightly more Common Lisp code than previously. (cl-mapcar-many): Delete. (map, maplist, mapc, mapl, mapcan, mapcon): Move these to fns.c. * bytecomp.el (byte-compile-maybe-mapc): Use #'mapc itself, not #'mapc-internal, now the former is in C. (mapcar*): Use #'byte-compile-maybe-mapc as this function's byte-compile method, now a #'mapc that can take more than one sequence is in C. * obsolete.el (cl-mapc): Move this compatibility alias to this file. * update-elc.el (do-autoload-commands): Use #'mapc, not #'mapc-internal here.
author Aidan Kehoe <kehoea@parhasard.net>
date Sun, 31 Jan 2010 18:29:48 +0000
parents b828e06dbe38
children c17c857e20bf
comparison
equal deleted inserted replaced
4904:e91e3e353805 4995:8431b52e43b1
73 ;; XEmacs addition: enhanced numeric type coercions 73 ;; XEmacs addition: enhanced numeric type coercions
74 ((and-fboundp 'coerce-number 74 ((and-fboundp 'coerce-number
75 (memq type '(integer ratio bigfloat)) 75 (memq type '(integer ratio bigfloat))
76 (coerce-number x type))) 76 (coerce-number x type)))
77 ;; XEmacs addition: bit-vector coercion 77 ;; XEmacs addition: bit-vector coercion
78 ((eq type 'bit-vector) (if (bit-vector-p x) x 78 ((or (eq type 'bit-vector)
79 (apply 'bit-vector (append x nil)))) 79 (eq type 'simple-bit-vector))
80 (if (bit-vector-p x) x (apply 'bit-vector (append x nil))))
80 ;; XEmacs addition: weak-list coercion 81 ;; XEmacs addition: weak-list coercion
81 ((eq type 'weak-list) 82 ((eq type 'weak-list)
82 (if (weak-list-p x) x 83 (if (weak-list-p x) x
83 (let ((wl (make-weak-list))) 84 (let ((wl (make-weak-list)))
84 (set-weak-list-list wl (if (listp x) x (append x nil))) 85 (set-weak-list-list wl (if (listp x) x (append x nil)))
85 wl))) 86 wl)))
87 ((and
88 (consp type)
89 (or (eq (car type) 'vector)
90 (eq (car type) 'simple-array)
91 (eq (car type) 'simple-vector))
92 (cond
93 ((equal (cdr-safe type) '(*))
94 (coerce x 'vector))
95 ((equal (cdr-safe type) '(bit))
96 (coerce x 'bit-vector))
97 ((equal (cdr-safe type) '(character))
98 (coerce x 'string)))))
86 ((typep x type) x) 99 ((typep x type) x)
87 (t (error "Can't coerce %s to type %s" x type)))) 100 (t (error "Can't coerce %s to type %s" x type))))
88 101
89 102
90 ;;; Predicates. 103 ;;; Predicates.
210 ;; bit-vectors and strings are only equalp if they're 223 ;; bit-vectors and strings are only equalp if they're
211 ;; zero-length: 224 ;; zero-length:
212 (and (equal "" y) (equal #* x))))) 225 (and (equal "" y) (equal #* x)))))
213 (t (equal x y))))))) 226 (t (equal x y)))))))
214 227
215 ;;; Control structures. 228 ;; XEmacs; #'map, #'mapc, #'mapl, #'maplist, #'mapcon are now in C, together
216 229 ;; with #'map-into, which was never in this file.
217 (defun cl-mapcar-many (cl-func cl-seqs)
218 (if (cdr (cdr cl-seqs))
219 (let* ((cl-res nil)
220 (cl-n (apply 'min (mapcar 'length cl-seqs)))
221 (cl-i 0)
222 (cl-args (copy-sequence cl-seqs))
223 cl-p1 cl-p2)
224 (setq cl-seqs (copy-sequence cl-seqs))
225 (while (< cl-i cl-n)
226 (setq cl-p1 cl-seqs cl-p2 cl-args)
227 (while cl-p1
228 (setcar cl-p2
229 (if (consp (car cl-p1))
230 (prog1 (car (car cl-p1))
231 (setcar cl-p1 (cdr (car cl-p1))))
232 (aref (car cl-p1) cl-i)))
233 (setq cl-p1 (cdr cl-p1) cl-p2 (cdr cl-p2)))
234 (push (apply cl-func cl-args) cl-res)
235 (setq cl-i (1+ cl-i)))
236 (nreverse cl-res))
237 (let ((cl-res nil)
238 (cl-x (car cl-seqs))
239 (cl-y (nth 1 cl-seqs)))
240 (let ((cl-n (min (length cl-x) (length cl-y)))
241 (cl-i -1))
242 (while (< (setq cl-i (1+ cl-i)) cl-n)
243 (push (funcall cl-func
244 (if (consp cl-x) (pop cl-x) (aref cl-x cl-i))
245 (if (consp cl-y) (pop cl-y) (aref cl-y cl-i)))
246 cl-res)))
247 (nreverse cl-res))))
248
249 (defun map (cl-type cl-func cl-seq &rest cl-rest)
250 "Map a function across one or more sequences, returning a sequence.
251 TYPE is the sequence type to return, FUNC is the function, and SEQS
252 are the argument sequences."
253 (let ((cl-res (apply 'mapcar* cl-func cl-seq cl-rest)))
254 (and cl-type (coerce cl-res cl-type))))
255
256 (defun maplist (cl-func cl-list &rest cl-rest)
257 "Map FUNC to each sublist of LIST or LISTS.
258 Like `mapcar', except applies to lists and their cdr's rather than to
259 the elements themselves."
260 (if cl-rest
261 (let ((cl-res nil)
262 (cl-args (cons cl-list (copy-sequence cl-rest)))
263 cl-p)
264 (while (not (memq nil cl-args))
265 (push (apply cl-func cl-args) cl-res)
266 (setq cl-p cl-args)
267 (while cl-p (setcar cl-p (cdr (pop cl-p)) )))
268 (nreverse cl-res))
269 (let ((cl-res nil))
270 (while cl-list
271 (push (funcall cl-func cl-list) cl-res)
272 (setq cl-list (cdr cl-list)))
273 (nreverse cl-res))))
274
275 ;; XEmacs change: in Emacs, this function is named cl-mapc.
276 (defun mapc (cl-func cl-seq &rest cl-rest)
277 "Like `mapcar', but does not accumulate values returned by the function."
278 (if cl-rest
279 (apply 'map nil cl-func cl-seq cl-rest)
280 ;; XEmacs change: in the simplest case we call mapc-internal,
281 ;; which really doesn't accumulate any results.
282 (mapc-internal cl-func cl-seq))
283 cl-seq)
284
285 ;; XEmacs addition: FSF compatibility
286 (defalias 'cl-mapc 'mapc)
287
288 (defun mapl (cl-func cl-list &rest cl-rest)
289 "Like `maplist', but does not accumulate values returned by the function."
290 (if cl-rest
291 (apply 'maplist cl-func cl-list cl-rest)
292 (let ((cl-p cl-list))
293 (while cl-p (funcall cl-func cl-p) (setq cl-p (cdr cl-p)))))
294 cl-list)
295
296 (defun mapcan (cl-func cl-seq &rest cl-rest)
297 "Like `mapcar', but nconc's together the values returned by the function."
298 (apply 'nconc (apply 'mapcar* cl-func cl-seq cl-rest)))
299
300 (defun mapcon (cl-func cl-list &rest cl-rest)
301 "Like `maplist', but nconc's together the values returned by the function."
302 (apply 'nconc (apply 'maplist cl-func cl-list cl-rest)))
303 230
304 (defun some (cl-pred cl-seq &rest cl-rest) 231 (defun some (cl-pred cl-seq &rest cl-rest)
305 "Return true if PREDICATE is true of any element of SEQ or SEQs. 232 "Return true if PREDICATE is true of any element of SEQ or SEQs.
306 If so, return the true (non-nil) value returned by PREDICATE." 233 If so, return the true (non-nil) value returned by PREDICATE."
307 (if (or cl-rest (nlistp cl-seq)) 234 (if (or cl-rest (nlistp cl-seq))