[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).
- "Like `let*' but .....",
Alan Mackenzie <=