[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
bug#25826: 26.0.50; cl-mapc and cl-mapl do needless consing
From: |
Tino Calancha |
Subject: |
bug#25826: 26.0.50; cl-mapc and cl-mapl do needless consing |
Date: |
Wed, 22 Feb 2017 12:08:34 +0900 |
User-agent: |
Gnus/5.13 (Gnus v5.13) Emacs/26.0.50 (gnu/linux) |
npostavs@users.sourceforge.net writes:
> Tino Calancha <tino.calancha@gmail.com> writes:
>
>> Current implementation of cl-mapc (cl-mapl) uses `cl-mapcar'
>> (`cl-maplist') when input contains > 1 sequence. Thus,
>> they cons the values and just discard then at the end.
>>
>> Following patch adds a defvar which acts as a flag for consing
>> the values. The flag is bind to nil in the case of `cl-mapc' and
>> `cl-mapl'.
>
> Is it possible to do this via a parameter instead? Using a global
> variable seems like asking for trouble in case of nested calls or
> similar.
How about the following updated patch?
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
>From 917e290e9101426b492becd814f2f570d1fc9802 Mon Sep 17 00:00:00 2001
From: Tino Calancha <tino.calancha@gmail.com>
Date: Wed, 22 Feb 2017 12:06:04 +0900
Subject: [PATCH] Prevent for consing in cl-mapc and cl-mapl
* lisp/emacs-lisp/cl-extra.el (cl--mapcar-many): Add optional arg ACC;
If non-nil, accumulate values in the result (Bug#25826).
(cl-mapc): Do computations inside function instead of call cl-map.
(cl-mapl): Do computations inside function instead of call cl-maplist.
* lisp/emacs-lisp/cl-lib.el (mapcar): Add autoload cookie.
Call cl--mapcar-many with non-nil 3rd argument.
---
lisp/emacs-lisp/cl-extra.el | 38 ++++++++++++++++++++++++++------------
lisp/emacs-lisp/cl-lib.el | 5 +++--
2 files changed, 29 insertions(+), 14 deletions(-)
diff --git a/lisp/emacs-lisp/cl-extra.el b/lisp/emacs-lisp/cl-extra.el
index edd14b816f..8cba913710 100644
--- a/lisp/emacs-lisp/cl-extra.el
+++ b/lisp/emacs-lisp/cl-extra.el
@@ -89,7 +89,7 @@ cl-equalp
;;; Control structures.
;;;###autoload
-(defun cl--mapcar-many (cl-func cl-seqs)
+(defun cl--mapcar-many (cl-func cl-seqs &optional acc)
(if (cdr (cdr cl-seqs))
(let* ((cl-res nil)
(cl-n (apply 'min (mapcar 'length cl-seqs)))
@@ -106,20 +106,23 @@ cl--mapcar-many
(setcar cl-p1 (cdr (car cl-p1))))
(aref (car cl-p1) cl-i)))
(setq cl-p1 (cdr cl-p1) cl-p2 (cdr cl-p2)))
- (push (apply cl-func cl-args) cl-res)
+ (if acc
+ (push (apply cl-func cl-args) cl-res)
+ (apply cl-func cl-args))
(setq cl-i (1+ cl-i)))
- (nreverse cl-res))
+ (and acc (nreverse cl-res)))
(let ((cl-res nil)
(cl-x (car cl-seqs))
(cl-y (nth 1 cl-seqs)))
(let ((cl-n (min (length cl-x) (length cl-y)))
(cl-i -1))
(while (< (setq cl-i (1+ cl-i)) cl-n)
- (push (funcall cl-func
- (if (consp cl-x) (pop cl-x) (aref cl-x cl-i))
- (if (consp cl-y) (pop cl-y) (aref cl-y cl-i)))
- cl-res)))
- (nreverse cl-res))))
+ (let ((val (funcall cl-func
+ (if (consp cl-x) (pop cl-x) (aref cl-x cl-i))
+ (if (consp cl-y) (pop cl-y) (aref cl-y cl-i)))))
+ (when acc
+ (push val cl-res)))))
+ (and acc (nreverse cl-res)))))
;;;###autoload
(defun cl-map (cl-type cl-func cl-seq &rest cl-rest)
@@ -142,7 +145,7 @@ cl-maplist
(while (not (memq nil cl-args))
(push (apply cl-func cl-args) cl-res)
(setq cl-p cl-args)
- (while cl-p (setcar cl-p (cdr (pop cl-p)) )))
+ (while cl-p (setcar cl-p (cdr (pop cl-p)))))
(nreverse cl-res))
(let ((cl-res nil))
(while cl-list
@@ -155,8 +158,14 @@ cl-mapc
"Like `cl-mapcar', but does not accumulate values returned by the function.
\n(fn FUNCTION SEQUENCE...)"
(if cl-rest
- (progn (apply 'cl-map nil cl-func cl-seq cl-rest)
- cl-seq)
+ (if (or (cdr cl-rest) (nlistp cl-seq) (nlistp (car cl-rest)))
+ (progn
+ (cl--mapcar-many cl-func (cons cl-seq cl-rest))
+ cl-seq)
+ (let ((cl-x cl-seq) (cl-y (car cl-rest)))
+ (while (and cl-x cl-y)
+ (funcall cl-func (pop cl-x) (pop cl-y)))
+ cl-seq))
(mapc cl-func cl-seq)))
;;;###autoload
@@ -164,7 +173,12 @@ cl-mapl
"Like `cl-maplist', but does not accumulate values returned by the function.
\n(fn FUNCTION LIST...)"
(if cl-rest
- (apply 'cl-maplist cl-func cl-list cl-rest)
+ (let ((cl-args (cons cl-list (copy-sequence cl-rest)))
+ cl-p)
+ (while (not (memq nil cl-args))
+ (apply cl-func cl-args)
+ (setq cl-p cl-args)
+ (while cl-p (setcar cl-p (cdr (pop cl-p))))))
(let ((cl-p cl-list))
(while cl-p (funcall cl-func cl-p) (setq cl-p (cdr cl-p)))))
cl-list)
diff --git a/lisp/emacs-lisp/cl-lib.el b/lisp/emacs-lisp/cl-lib.el
index 5aa8f1bf65..8c4455a3da 100644
--- a/lisp/emacs-lisp/cl-lib.el
+++ b/lisp/emacs-lisp/cl-lib.el
@@ -347,8 +347,9 @@ cl-float-negative-epsilon
(cl--defalias 'cl-copy-seq 'copy-sequence)
-(declare-function cl--mapcar-many "cl-extra" (cl-func cl-seqs))
+(declare-function cl--mapcar-many "cl-extra" (cl-func cl-seqs &optional acc))
+;;;###autoload
(defun cl-mapcar (cl-func cl-x &rest cl-rest)
"Apply FUNCTION to each element of SEQ, and make a list of the results.
If there are several SEQs, FUNCTION is called with that many arguments,
@@ -358,7 +359,7 @@ cl-mapcar
\n(fn FUNCTION SEQ...)"
(if cl-rest
(if (or (cdr cl-rest) (nlistp cl-x) (nlistp (car cl-rest)))
- (cl--mapcar-many cl-func (cons cl-x cl-rest))
+ (cl--mapcar-many cl-func (cons cl-x cl-rest) 'accumulate)
(let ((cl-res nil) (cl-y (car cl-rest)))
(while (and cl-x cl-y)
(push (funcall cl-func (pop cl-x) (pop cl-y)) cl-res))
--
2.11.0
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
In GNU Emacs 26.0.50 (build 2, x86_64-pc-linux-gnu, GTK+ Version 3.22.7)
of 2017-02-22
Repository revision: fb997d30af28da4712ca64876feddbd07db20e13
- bug#25826: 26.0.50; cl-mapc and cl-mapl do needless consing, Tino Calancha, 2017/02/21
- bug#25826: 26.0.50; cl-mapc and cl-mapl do needless consing, npostavs, 2017/02/21
- bug#25826: 26.0.50; cl-mapc and cl-mapl do needless consing,
Tino Calancha <=
- bug#25826: 26.0.50; cl-mapc and cl-mapl do needless consing, npostavs, 2017/02/21
- bug#25826: 26.0.50; cl-mapc and cl-mapl do needless consing, Tino Calancha, 2017/02/21
- bug#25826: 26.0.50; cl-mapc and cl-mapl do needless consing, Tino Calancha, 2017/02/22
- bug#25826: 26.0.50; cl-mapc and cl-mapl do needless consing, npostavs, 2017/02/22
- bug#25826: 26.0.50; cl-mapc and cl-mapl do needless consing, Tino Calancha, 2017/02/22
- bug#25826: 26.0.50; cl-mapc and cl-mapl do needless consing, Tino Calancha, 2017/02/27