emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: (byte-compile '(append '(1 2) '(3 4)))


From: Basil L. Contovounesios
Subject: Re: (byte-compile '(append '(1 2) '(3 4)))
Date: Sun, 17 Mar 2024 00:42:24 +0100
User-agent: Gnus/5.13 (Gnus v5.13)

Philip Kaludercic [2024-03-16 13:55 +0000] wrote:
> "Basil L. Contovounesios" <basil@contovou.net> writes:
>> Philip Kaludercic [2024-03-16 12:46 +0000] wrote:
>>
>>> I am not sure what the danger is in the case of constant, quoted lists,
>>> but I am not familiar with the byte compiler either.  It seems like this
>>>
>>> --- a/lisp/emacs-lisp/byte-opt.el
>>> +++ b/lisp/emacs-lisp/byte-opt.el
>>> @@ -1599,6 +1599,12 @@ byte-optimize-append
>>>                           (cdr args))
>>>                     (cdr newargs)))
>>>  
>>> +            ;; (append '(C1...) ... '(C2...)) -> (append C1... ... C2...)
>>> +            ((cl-loop for arg in args
>>> +                      always (and (eq (car arg) 'quote)
>>> +                                  (proper-list-p (cdr arg))))
>>> +             `',(mapcan #'cadr args))
>>> +
>>>              ;; non-terminal arg
>>>              ((cdr args)
>>>               (cond
>>>
>>> would do the trick, and the byte-code is even better:
>>>
>>> byte code:
>>>   args: nil
>>> 0   constant  (1 2 3 4)
>>> 1   return    
>>
>> Is this correct?  According to its docstring, append's last argument
>> must be eq to the tail of its return value.
>
> This little test indicates that it would still be eq:
>
> ((macro . (lambda (arg)
>           `(eq (cddadr (byte-optimize-append '(append '(1 2) ,arg)))
>                ,arg)))
>  '(3 4)) ;=> t
>
> since the mapcan or rather nconc makes the same promise.

Right, it seems straightforward to keep the resulting tail eq to the
last argument.  I'm too squeamish to destructively modify the input
form, and Emacs doesn't build with the diff above, so I'm guessing you
meant something like this instead:

diff --git a/lisp/emacs-lisp/byte-opt.el b/lisp/emacs-lisp/byte-opt.el
index f75be3f71ad..f0e543319c3 100644
--- a/lisp/emacs-lisp/byte-opt.el
+++ b/lisp/emacs-lisp/byte-opt.el
@@ -1630,6 +1630,13 @@ byte-optimize-append
             ;; (append X) -> X
             ((null newargs) arg)
 
+            ;; (append '(X...) ... '(Y...)) -> '(X... Y...)
+            ((and (eq (car-safe arg) 'quote)
+                  (cl-loop for newarg in newargs
+                           always (and (eq (car-safe newarg) 'quote)
+                                       (proper-list-p (cadr newarg)))))
+             `',(apply #'append (mapcar #'cadr (nreverse (cons arg newargs)))))
+
             ;; (append ... (list Xs...) nil) -> (append ... (list Xs...))
             ((and (null arg) (eq (car-safe prev) 'list))
              (cons (car form) (nreverse newargs)))
But then the problem is that you can't e.g.

  (setcar (append '(0) '(1)) t)

without it looking like the program is modifying a constant list.

-- 
Basil

reply via email to

[Prev in Thread] Current Thread [Next in Thread]