From: Stefan Monnier <monnier@iro.umontreal.ca>
To: Nicolas Petton <nicolas@petton.fr>
Cc: emacs-devel <emacs-devel@gnu.org>
Subject: Re: Using gv in map and seq?
Date: Mon, 15 Jun 2015 12:30:03 -0400 [thread overview]
Message-ID: <jwv8ubl3res.fsf-monnier+emacs@gnu.org> (raw)
In-Reply-To: <878ublkrqe.fsf@petton.fr> (Nicolas Petton's message of "Mon, 15 Jun 2015 15:48:09 +0200")
>>> I was wondering if it would make sense to use gv in map or seq?
>> Not sure what you mean. Do you mean to add a setter for seq-elt?
> Yes
I see. Yes, defining a "gv-setter" or "gv-expander" would be good.
Oh, wait, no, it's not needed, since seq-elt is an alias for `elt' and
that one already has a setter. IOW it already works!
> (and a getter too?).
When defining a setter, you need to define the getter as well, indeed, but
that's generally the trivial part.
> The same goes for `map-elt'.
This one is not pre-defined, so yes, we should define it.
Actually, this just means to turn map-put into a gv-setter.
Something like the patch below seems to work (and it generalizes
map-put to accept for MAP not only symbols but any "lvalue"). It also
tightens the code generated by map--dispatch.
Stefan
diff --git a/lisp/emacs-lisp/map.el b/lisp/emacs-lisp/map.el
index dd7fb91..26ad6ce 100644
--- a/lisp/emacs-lisp/map.el
+++ b/lisp/emacs-lisp/map.el
@@ -82,25 +82,19 @@ The following keyword types are meaningful: `:list',
An error is thrown if MAP is neither a list, hash-table nor array.
-Return RESULT if non-nil or the result of evaluation of the
-form.
+Return RESULT if non-nil or the result of evaluation of the form.
\(fn (VAR MAP [RESULT]) &rest ARGS)"
(declare (debug t) (indent 1))
(unless (listp spec)
(setq spec `(,spec ,spec)))
- (let ((map-var (car spec))
- (result-var (make-symbol "result")))
- `(let ((,map-var ,(cadr spec))
- ,result-var)
- (setq ,result-var
- (cond ((listp ,map-var) ,(plist-get args :list))
- ((hash-table-p ,map-var) ,(plist-get args :hash-table))
- ((arrayp ,map-var) ,(plist-get args :array))
- (t (error "Unsupported map: %s" ,map-var))))
- ,@(when (cddr spec)
- `((setq ,result-var ,@(cddr spec))))
- ,result-var)))
+ (let ((map-var (car spec)))
+ `(let* ,(unless (eq map-var (cadr spec)) `((,map-var ,(cadr spec))))
+ (cond ((listp ,map-var) ,(plist-get args :list))
+ ((hash-table-p ,map-var) ,(plist-get args :hash-table))
+ ((arrayp ,map-var) ,(plist-get args :array))
+ (t (error "Unsupported map: %s" ,map-var)))
+ ,@(cddr spec))))
(defun map-elt (map key &optional default)
"Perform a lookup in MAP of KEY and return its associated value.
@@ -109,27 +103,23 @@ If KEY is not found, return DEFAULT which defaults to nil.
If MAP is a list, `equal' is used to lookup KEY.
MAP can be a list, hash-table or array."
+ (declare
+ (gv-expander
+ (lambda (do)
+ (macroexp-let2* nil
+ ;; Eval them once and for all in the right order.
+ ((map map) (key key) (default default))
+ `(map--dispatch map
+ :list ,(gv-get `(alist-get ,key ,map ,default) do)
+ :hash-table ,(funcall do `(gethash ,key ,map ,default)
+ (lambda (v) `(puthash ,key ,v ,map)))
+ :array ,(funcall do `(aref ,map ,key)
+ (lambda (v) `(aset ,map ,key ,v))))))))
(map--dispatch map
:list (map--elt-list map key default)
:hash-table (gethash key map default)
:array (map--elt-array map key default)))
-(defmacro map-put (map key value)
- "In MAP, associate KEY with VALUE and return MAP.
-If KEY is already present in MAP, replace the associated value
-with VALUE.
-
-MAP can be a list, hash-table or array."
- (declare (debug t))
- (let ((symbol (symbolp map)))
- `(progn
- (map--dispatch (m ,map m)
- :list (if ,symbol
- (setq ,map (cons (cons ,key ,value) m))
- (error "Literal lists are not allowed, %s must be a symbol" ',map))
- :hash-table (puthash ,key ,value m)
- :array (aset m ,key ,value)))))
-
(defmacro map-delete (map key)
"In MAP, delete the key KEY if present and return MAP.
If MAP is an array, store nil at the index KEY.
next prev parent reply other threads:[~2015-06-15 16:30 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-06-15 10:47 Using gv in map and seq? Nicolas Petton
2015-06-15 12:41 ` Stefan Monnier
2015-06-15 13:48 ` Nicolas Petton
2015-06-15 16:30 ` Stefan Monnier [this message]
2015-06-16 1:45 ` Stefan Monnier
2015-06-16 7:13 ` Nicolas Petton
2015-06-16 20:35 ` Nicolas Petton
2015-06-17 0:41 ` Stefan Monnier
2015-06-17 12:58 ` Stefan Monnier
2015-06-17 14:40 ` Nicolas Petton
2015-06-17 17:39 ` Stefan Monnier
2015-06-18 19:59 ` Nicolas Petton
2015-06-19 2:52 ` Stefan Monnier
2015-06-16 21:28 ` Nicolas Petton
2015-06-18 8:31 ` [OT] Working with patches inlined in emails (was: Using gv in map and seq?) Nicolas Petton
2015-06-18 8:51 ` Eli Zaretskii
2015-06-18 9:27 ` [OT] Working with patches inlined in emails João Távora
2015-06-18 9:38 ` [OT] Working with patches inlined in emails (was: Using gv in map and seq?) Nicolas Petton
2015-06-18 9:45 ` Nicolas Petton
2015-06-18 8:58 ` [OT] Working with patches inlined in emails Andreas Schwab
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=jwv8ubl3res.fsf-monnier+emacs@gnu.org \
--to=monnier@iro.umontreal.ca \
--cc=emacs-devel@gnu.org \
--cc=nicolas@petton.fr \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this external index
https://git.savannah.gnu.org/cgit/emacs.git
https://git.savannah.gnu.org/cgit/emacs/org-mode.git
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.