emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

"Like `let*' but ....."


From: Alan Mackenzie
Subject: "Like `let*' but ....."
Date: Tue, 24 Jan 2017 21:12:27 +0000
User-agent: Mutt/1.7.2 (2016-11-26)

Hello, Emacs.

The doc string of pcase-let* reads, in its entirety:

       "Like `let*' but where you can use `pcase' patterns for bindings.
    BODY should be an expression, and BINDINGS should be a list of bindings
    of the form (PAT EXP)."

What is not clear is precisely HOW `pcase' patterns are used for
bindings, and what the semantics of (PAT EXP) are.

There is no other documentation of pcase-let* that I'm aware of.

Would somebody please explain it to me?  In particular, I want to
understand the following form from byte-compile-file-form-defalias in
bytecomp.el:

       (pcase-let*
           ;; `macro' is non-nil if it defines a macro.
           ;; `fun' is the function part of `arg' (defaults to `arg').
           (((or (and (or `(cons 'macro ,fun) `'(macro . ,fun)) (let macro t))
                 (and (let fun arg) (let macro nil)))
             arg)
            ;; `lam' is the lambda expression in `fun' (or nil if not
            ;; recognized).
            ((or `(,(or `quote `function) ,lam) (let lam nil))
             fun)
            ;; `arglist' is the list of arguments (or t if not recognized).
            ;; `body' is the body of `lam' (or t if not recognized).
            ((or `(lambda ,arglist . ,body)
                 ;; `(closure ,_ ,arglist . ,body)
                 (and `(internal-make-closure ,arglist . ,_) (let body t))
                 (and (let arglist t) (let body t)))
             lam))
         (unless (byte-compile-file-form-defmumble
                  name macro arglist body rest)
           (when macro
             (if (null fun)
                 (message "Macro %s unrecognized, won't work in file" name)
               (message "Macro %s partly recognized, trying our luck" name)
               (push (cons name (eval fun))
                     byte-compile-macro-environment)))
           (byte-compile-keep-pending form))))

What eludes me is points such as:
(i) what variables are being bound?
(ii) To what values?
(iii) What do the `or's and `and's on Line 4, etc. mean?

Incidentally, when I expand that form with macroexpand-all and print it
with pp, the resulting form is 173 lines long, totally inscrutable, a
typical portion of it looking like this:

                                          (if
                                              (null x)
                                              (let*
                                                  ((x
                                                    (cdr x)))
                                                (if
                                                    (consp x)
                                                    (let*
                                                        ((x
                                                          (car x))
                                                         (x
                                                          (cdr x)))
                                                      (if
                                                          (null x)
                                                          (funcall pcase-0 t x)
                                                        (funcall pcase-0 nil 
arg)))
                                                  (funcall pcase-0 nil arg)))
                                            (funcall pcase-0 nil arg)))
                                      (funcall pcase-0 nil arg)))
                                (funcall pcase-0 nil arg)))
                          (funcall pcase-0 nil arg)))
                    (funcall pcase-0 nil arg)))
              (funcall pcase-0 nil arg))))

Is this efficient, in either run-time or the size of the byte code produced?

-- 
Alan Mackenzie (Nuremberg, Germany).



reply via email to

[Prev in Thread] Current Thread [Next in Thread]