]> git.eshelyaron.com Git - emacs.git/commitdiff
* lisp/emacs-lisp/seq.el (seq-doseq): Tighten the code
authorStefan Monnier <monnier@iro.umontreal.ca>
Fri, 24 Apr 2015 20:11:35 +0000 (16:11 -0400)
committerStefan Monnier <monnier@iro.umontreal.ca>
Fri, 24 Apr 2015 20:11:35 +0000 (16:11 -0400)
(seq-doseq): Fix out-of-scope binding.
Don't call `seq-length at every iteration.
Reduce `if's from 3 to 2 per iteration.
(emacs-lisp-mode-hook): Don't tweak in Emacs≥25.

doc/lispref/sequences.texi
lisp/emacs-lisp/seq.el

index e1330f7d59406ee102f151d92f79ec2a149cd2bb..b48fae4741f0706d307ff20e674df777d19e6bfc 100644 (file)
@@ -790,7 +790,7 @@ of type @var{type}.  @var{type} can be one of the following symbols:
 @end example
 @end defun
 
-@defmac seq-doseq (var sequence [result]) body@dots{}
+@defmac seq-doseq (var sequence) body@dots{}
 @cindex sequence iteration
   This macro is like @code{dolist}, except that @var{sequence} can be a list,
 vector or string (@pxref{Iteration} for more information about the
index 320ee201487789ba76e64b9eb924392c3e4bf96b..b8647ec93ecf92cb04eb57f1fec9d4d26e1a70bf 100644 (file)
 
 (defmacro seq-doseq (spec &rest body)
   "Loop over a sequence.
-Similar to `dolist' but can be applied lists, strings and vectors.
+Similar to `dolist' but can be applied to lists, strings, and vectors.
 
 Evaluate BODY with VAR bound to each element of SEQ, in turn.
-Then evaluate RESULT to get return value, default nil.
 
-\(fn (VAR SEQ [RESULT]) BODY...)"
+\(fn (VAR SEQ) BODY...)"
   (declare (indent 1) (debug ((symbolp form &optional form) body)))
   (let ((is-list (make-symbol "is-list"))
         (seq (make-symbol "seq"))
         (index (make-symbol "index")))
     `(let* ((,seq ,(cadr spec))
-            (,is-list (listp ,seq))
+            (,length (if (listp ,seq) nil (seq-length ,seq)))
             (,index (if ,is-list ,seq 0)))
-       (while (if ,is-list
-                  (consp ,index)
-                (< ,index (seq-length ,seq)))
-         (let ((,(car spec) (if ,is-list
-                                (car ,index)
-                              (seq-elt ,seq ,index))))
-           ,@body
-           (setq ,index (if ,is-list
-                            (cdr ,index)
-                          (+ ,index 1)))))
-       ,@(if (cddr spec)
-             `((setq ,(car spec) nil) ,@(cddr spec))))))
+       (while (if ,length
+                  (< ,index ,length)
+                (consp ,index))
+         (let ((,(car spec) (if ,length
+                                (prog1 (seq-elt ,seq ,index)
+                                  (setq ,index (+ ,index 1)))
+                              (pop ,index))))
+           ,@body))
+       ;; FIXME: Do we really want to support this?
+       ,@(cddr spec))))
 
 (defun seq-drop (seq n)
   "Return a subsequence of SEQ without its first N elements.
@@ -350,7 +347,10 @@ This is an optimization for lists in `seq-take-while'."
 (defalias 'seq-each #'seq-do)
 (defalias 'seq-map #'mapcar)
 
-(add-to-list 'emacs-lisp-mode-hook #'seq--activate-font-lock-keywords)
+(unless (fboundp 'elisp--font-lock-flush-elisp-buffers)
+  ;; In Emacs≥25, (via elisp--font-lock-flush-elisp-buffers and a few others)
+  ;; we automatically highlight macros.
+  (add-to-list 'emacs-lisp-mode-hook #'seq--activate-font-lock-keywords))
 
 (provide 'seq)
 ;;; seq.el ends here