GNU bug report logs - #27584
26.0.50; alist-get: Add optional arg TESTFN

Previous Next

Package: emacs;

Reported by: Tino Calancha <tino.calancha <at> gmail.com>

Date: Wed, 5 Jul 2017 03:24:02 UTC

Severity: wishlist

Found in version 26.0.50

Done: Tino Calancha <tino.calancha <at> gmail.com>

Bug is archived. No further changes may be made.

Full log


View this message in rfc822 format

From: Tino Calancha <tino.calancha <at> gmail.com>
To: Stefan Monnier <monnier <at> iro.umontreal.ca>
Cc: Nicolas Petton <nicolas <at> petton.fr>, 27584 <at> debbugs.gnu.org, Tino Calancha <tino.calancha <at> gmail.com>
Subject: bug#27584: 26.0.50; alist-get: Add optional arg TESTFN
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?




This bug report was last modified 7 years and 352 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.