Subject: bug#69013: New package for NonGNU ELPA: totp-auth

From: Stefan Monnier <[email-masked]>
Date: Sat, 10 Feb 2024 13:41:21 -0500

> -  (delq nil
> -        (mapcar (lambda (s &optional secure type source handler)
> -                  (setq source  (slot-value s 'source)
> -                        type    (slot-value s 'type)
> -                        secure  (or (eq type 'secrets)
> -                                    (eq type 'plist)
> -                                    (equal (file-name-extension source) "gpg"))
> -                        handler (if (eq type 'secrets) :secrets :default))
> -                  (if (and encrypted (not secure))
> -                      nil
> -                    (list (cons :source    s)
> -                          (cons :handler   handler)
> -                          (cons :encrypted secure))))
> -                (mapcar #'auth-source-backend-parse (totp-auth-sources)))))
> +  (mapcan
> +   (lambda (s &optional secure type source handler)
> +     (setq source  (slot-value s 'source)
> +           type    (slot-value s 'type)
> +           secure  (or (eq type 'secrets)
> +                       (eq type 'plist)
> +                       (equal (file-name-extension source) "gpg"))
> +           handler (if (eq type 'secrets) :secrets :default))
> +     (if (and encrypted (not secure))
> +         nil
> +       `(((:source ,s) (:handler ,handler) (:encrypted ,secure)))))
> +   (mapcar #'auth-source-backend-parse (totp-auth-sources))))

Also `mapcar/mapcan` will only pass one argument to the loop-body
function, so in the code above the args `&optional secure type source
handler` will always be nil :-(

Maybe you'd want to merge the two loops:

    (mapcan
     (lambda (entry)
       (let* ((s (auth-source-backend-parse entry))
              (source  (slot-value s 'source))
              (type    (slot-value s 'type))
              (secure  (or (memq type '(secrets plist))
                           (equal (file-name-extension source) "gpg")))
              (handler (if (eq type 'secrets) :secrets :default)))
       (if (and encrypted (not secure))
           nil
         `(((:source ,s) (:handler ,handler) (:encrypted ,secure))))))
     (totp-auth-sources))))

> I have to admit that your
>
> (let (foo)
>   (setq foo bar)
>   ...)
>
> pattern confuses me, it seems intentional but unnecessary, so I didn't
> comment on every instance.

AFAIK it's common for coders coming from imperative programming
languages like C where it's common to declare variables separately from
their initialization.

In Lisp it's unidiomatic (tho I've seen this style used in old
Common-Lisp code as well) and in ELisp it comes almost exclusively with
downsides:
- Of course, the usual downside is that it introduces a time-window
  during which the variable is not initialized, so it makes the code
  fundamentally more complex.
- It makes the code more verbose.
- It makes the code less efficient.

        Stefan