Subject: Re: bug#27584: 26.0.50; alist-get: Add optional arg TESTFN

From: Tino Calancha <[email-masked]>
Date: Sun, 9 Jul 2017 23:45:53 +0900 (JST)

On Fri, 7 Jul 2017, Stefan Monnier wrote:

>> +  (declare (compiler-macro
>> +            (lambda (_)
>> +              `(pcase ,pred
>> +                 ('eq (assq ,key ,alist))
>> +                 ((or 'equal 'nil) (assoc ,key ,alist))
>> +                 ((guard (and (macroexp-const-p ,key) (eq ,pred 'eql)))
>> +                  (if (floatp ,key)
>> +                      (assoc ,key ,alist) (assq ,key ,alist)))
>> +                 (_ (assoc-default ,key ,alist ,pred nil 'full))))))
>
> This replaces a call to the function with a chunk of code which does
> `pcase`, which is not what we want: we want the `pcase` to be executed
> during compilation and if we can't choose which branch to follow, then
> we just keep the call unchanged (which is why, in my define-inline
> example, the pcase was outside of `inline-quote`).
Thank you Stefan.  After playing a bit with this i'd like to
ask you something.

I rewrote it as follows:

   (declare (compiler-macro
             (lambda (form)
               (pcase pred
                 (''eq `(assq ,key ,alist))
                 ((or ''equal 'nil) `(assoc ,key ,alist))
                 ((and (guard (macroexp-const-p key)) ''eql)
                  (if (floatp key)
                      `(assoc ,key ,alist) `(assq ,key ,alist)))
                 (t form)))))

Apparently, it works as a charm:
*) For example, if i compile a file with content:
;; -*- lexical-binding: t; -*-

(defun run ()
     (assoc-predicate 999 '((1 . "a") (2 . "b")) 'eql))

*) tmp.elc contains, something like:
(defalias 'run #[0 "\300\301\236\207" [999 ((1 . "a") (2 . "b"))] 2])

**) But note what happens if the file contains:
;; -*- lexical-binding: t; -*-

(defun run ()
     (assoc-predicate (let ((x 999)) x) '((1 . "a") (2 . "b")) 'eql))

**) tmp.elc shows:
(defalias 'run #[0 "\300\301\211\262\302\303#\207" [assoc-predicate 999 
((1 . "a") (2 . "b")) eql] 4])

That is, in the pcase fails the condition:
(and (guard (macroexp-const-p key)) ''eql)
so that the compiler macro doesn't change the form.

But we know that:
(macroexp-const-p (let ((x 999)) x))
=> t

So, i would expect to **) compiles to similar code as *).

What is wrong with my assumptions?