GNU bug report logs -
#7408
23.2.1 dolist -- subr.el and cl-macs differ with nil-block return
Previous Next
Reported by: Jari Aalto <jari.aalto <at> cante.net>
Date: Mon, 15 Nov 2010 10:47:02 UTC
Severity: normal
Found in version 23.2+1-4
Done: Stefan Monnier <monnier <at> iro.umontreal.ca>
Bug is archived. No further changes may be made.
Full log
Message #34 received at 7408 <at> debbugs.gnu.org (full text, mbox):
On 2010-11-16 17:21, Stefan Monnier wrote:
| >> subr.el has had a dolist definition since at least Emacs 21.x; ie 9 years.
| >> Therefore this cannot be a major issue in practice.
| > In my book it is still a bug, no matter how many years ago this bug were
| > introduced:
|
| > a: - To have two different implementations of same function.
| > b: - To not be able to rely on uniform behavior.
|
| You look at it the wrong way: the problem is not with dolist, it's that
| you use `return' which is a special form that's not defined in standard
| Elisp.
As I understand it, the fact that there are forms like these nowadays:
unless
when
...
dolist
was because people used these constructs from CL so many time that
they were "re-introduced" directly in subr.el in order to prevent
loading CL.
However re-implementation of CL equivalent of 'dolist' did not meet
all the criteria. The 'return' has been integral part of 'dolist'
since the start.
| After (require 'cl), `return' gets defined and things work as you
| expect.
The implementation in subr.el::dolist does not have any support for
'return'.
It is not that 'return' gets defined, but what happens is that loading
CL clobbers that current definition pf 'dolist' by overwiting it with
its own implementation:
Two different implementation, that are not compatible.
$ diff -u 1.subr.el 2.cl-macs.el | grep -vE ";|declare"
--- 1.subr.el 2010-11-17 06:31:53.000000000 +0200
+++ 2.cl-macs.el 2010-11-17 06:32:31.000000000 +0200
@@ -1,19 +1,15 @@
(defmacro dolist (spec &rest body)
"Loop over a list.
-Evaluate BODY with VAR bound to each car from LIST, in turn.
+Evaluate BODY with VAR bound to each `car' from LIST, in turn.
Then evaluate RESULT to get return value, default nil.
\(fn (VAR LIST [RESULT]) BODY...)"
- (let ((temp '--dolist-tail--))
- `(let ((,temp ,(nth 1 spec))
- ,(car spec))
- (while ,temp
- (setq ,(car spec) (car ,temp))
- ,@body
- (setq ,temp (cdr ,temp)))
- ,@(if (cdr (cdr spec))
- `((setq ,(car spec) nil) ,@(cdr (cdr spec)))))))
+ (let ((temp (make-symbol "--cl-dolist-temp--")))
>> + (list 'block nil
+ (list* 'let (list (list temp (nth 1 spec)) (car spec))
+ (list* 'while temp (list 'setq (car spec) (list 'car temp))
+ (append body (list (list 'setq temp
+ (list 'cdr temp)))))
+ (if (cdr (cdr spec))
+ (cons (list 'setq (car spec) nil) (cdr (cdr spec)))
+ '(nil))))))
Naturally, loading CL also defines other things. But the fundamental
problem is two incompatible dolist implementations.
A possible solution:
- Make subr.el::dolist repect return-block (nil-block)
- have 'return' autoloaded
If user uses:
- Plain dolist, nothing more is loaded (subr.el is used)
- "return", it triggers autoloading CL (or parts of it).
Jari
This bug report was last modified 14 years and 186 days ago.
Previous Next
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.