2
(setq ali '())
>>> nil
(cl-incf (alist-get 'a ali 0))
>>> ((a . 1))
(setf (alist-get 'b ali) 0)
>>> ((b . 0) (a . 1))
(cl-incf (alist-get 'b ali 0))
>>> 1

As you can see, cl-incf returns different kinds of values in the second and the fourth expressions.

cl-incf per documentation is supposed to return "the incremented value of PLACE", however as we can see with the key 'a it returns the whole ali structure. If we macroexpand it a few times, it's clear what's happening:

(let*
    ((p
      (if
          (and nil
               (not
                (eq nil 'eq)))
          (assoc 'a ali nil)
        (assq 'a ali)))
     (v
      (+
       (if p
           (cdr p)
         0)
       1)))
  (if p
      (setcdr p v)
    (setq ali
          (cons
           (setq p
                 (cons 'a v))
           ali))))

The last setq is applied to ali, so it returns the new value of ali.

It seems to be a bug in the alist generalized variable definition.

Am I correct? If so, how to report it? If not, what's the idiomatic way to work around it, preferably not calling alist-get two times?

Drew
  • 75,699
  • 9
  • 109
  • 225
grepcake
  • 145
  • 7
  • Yep, the behavior for the second sexp, `(cl-incf (alist-get 'a ali 0))` looks wrong. Consider filing a bug report: `M-x report-emacs-bug`. – Drew Aug 12 '20 at 20:29
  • I think the last part of the expansion should be something like this: `(if p (setcdr p v) (setq ali (cons (setq p (cons 'a v)) ali)) v)`. IOW, after updating `ali` it should return `v`, not `ali`. In all cases it should return `v`. – Drew Aug 12 '20 at 20:41
  • I went ahead and filed bug report #[42837](https://debbugs.gnu.org/cgi/bugreport.cgi?bug=42837) for this. Wasn't sure you'd do it, and wanted to get it done. Feel free to chime in there. – Drew Aug 12 '20 at 22:57
  • Emacs 27.1's return value is correct, in other words, for your seconds expression, it returns `1` instead of `((a . 1))`. I don't have Emacs 26.3 installed, so I can't test that version. – xuchunyang Aug 13 '20 at 03:45
  • @Drew thank you for filing the report, it's okay that you did it. – grepcake Aug 13 '20 at 08:42
  • @xuchunyang it's good to know that it's fixed in 27.1. My Emacs version is 26.3. – grepcake Aug 13 '20 at 08:43
  • @Drew I guess, you can write a short answer mentioning `emacs-report-bug` and your report and I'll mark it as a correct answer. Also, the fact that it's apparently fixed in 27.1 which I can't test right now. – grepcake Aug 13 '20 at 08:44
  • @grepcake: Done. – Drew Aug 13 '20 at 16:23

1 Answers1

2

Yep, the behavior for the second sexp, (cl-incf (alist-get 'a ali 0)) looks wrong. I think the last part of the expansion should be something like this:

(if p
    (setcdr p v)
  (setq ali (cons (setq p (cons 'a v)) ali))
  v)

IOW, after updating ali it should return v, not ali. In all cases it should return v.

I filed Emacs bug #42837 for this. In the future, you can do it yourself via report-emacs-bug.

But it turns out this has already been fixed in Emacs 27.1, which has just been released.

grepcake
  • 145
  • 7
Drew
  • 75,699
  • 9
  • 109
  • 225