Subject: bug#63251: 28.2; vhdl-mode contribution

From: Mattias Engdegård <[email-masked]>
Date: Sun, 7 May 2023 18:22:56 +0200

7 maj 2023 kl. 17.40 skrev Cyril Arnould <[email-masked]>:

> I had tried (cons …) instead of (sexp …), but that just resulted in
> the customization menu breaking again if one of the compilers was set
> to a dotted list.

Why would they be set to a dotted list? Can you give an example?
I tried

			      (cons :tag "Warning and Info"
                                    (natnum :tag "Warning subexp index")
                                    (natnum :tag "Info subexp index   "))

instead of the (sexp ...) and it seems to work alright.

> > Think of what happens if later code performs an in-place change of that nil you added.
>  
> I am by no means an expert when it comes to elisp, I don’t know what
> kind of problems this could cause.

What I meant was that the code

  (let ((tmp-alist vhdl-compiler-alist))
    (while tmp-alist
      (setcdr (nthcdr 3 (nth 11 (car tmp-alist)))
	      '(2 . nil))
      (setq tmp-alist (cdr tmp-alist))))

modifies the existing list structure instead of creating a new one based on the old. This can lead to surprises if parts of the structure being mutated is shared with structure elsewhere. Now this code probably does work, but it's a bit brittle, and it takes some work for the reader to understand that it's OK. Contrast it to something like (untested!)

  (setq vhdl-compiler-alist
        (mapcar (lambda (entry)
                  ;; Add a `2' to the end of the list that is element #11.
                  (append (take 11 entry)
                          (append (nth 11 entry) (list 2))
                          (nthcdr 12 entry)))
                vhdl-compiler-alist))

where there is no mutation of the list structure, nor any sharing of a program constant whose accidental mutation might have very confusing consequences. (`take` is new in Emacs 29 but you can work around it by using `butlast` instead if the code needs to work with older Emacs versions.)