(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?
(cl-incf (alist-get 'a ali 0))looks wrong. Consider filing a bug report:M-x report-emacs-bug.(if p (setcdr p v) (setq ali (cons (setq p (cons 'a v)) ali)) v). IOW, after updatingaliit should returnv, notali. In all cases it should returnv.1instead of((a . 1)). I don't have Emacs 26.3 installed, so I can't test that version.