copy-tree used to always call itself, even on linear lists, which
caused stack exhaustion on long lists. Make it copy linear lists
linearly, and recur only when necessary. This also makes it somewhat
faster.
Fixes lp#98926.
* bug fix: compiler-internal interval arithmetic needed to be more
conservative about open intervals when operated on by monotonic but not
strictly-monotonic functions. (lp#975528)
+ * bug fix: copy-tree caused stack exhaustion on long linear lists, and now
+ it's also slightly faster. (lp#998926)
* documentation:
** improved docstrings: REPLACE (lp#965592)
#!+sb-doc
"Recursively copy trees of conses."
(if (consp object)
- (cons (copy-tree (car object)) (copy-tree (cdr object)))
+ (let ((result (list (if (consp (car object))
+ (copy-tree (car object))
+ (car object)))))
+ (loop for last-cons = result then new-cons
+ for cdr = (cdr object) then (cdr cdr)
+ for car = (if (consp cdr)
+ (car cdr)
+ (return (setf (cdr last-cons) cdr)))
+ for new-cons = (list (if (consp car)
+ (copy-tree car)
+ car))
+ do (setf (cdr last-cons) new-cons))
+ result)
object))
+
\f
;;;; more commonly-used list functions