From: Eric Abrahamsen <eric@ericabrahamsen.net>
To: Michael Heerdegen <michael_heerdegen@web.de>
Cc: emacs-devel@gnu.org
Subject: Re: Help with recursive destructive function
Date: Sat, 28 Jul 2018 13:52:40 -0700 [thread overview]
Message-ID: <87fu03gk13.fsf@ericabrahamsen.net> (raw)
In-Reply-To: <87y3glomjm.fsf@web.de> (Michael Heerdegen's message of "Tue, 15 May 2018 01:16:45 +0200")
On 05/15/18 01:16 AM, Michael Heerdegen wrote:
> Eric Abrahamsen <eric@ericabrahamsen.net> writes:
>
>> For backwards compatibility, we need to be able to handle lists that are
>> quoted, or that start with the symbol `list'. This will sound familiar
>> to you... In the non-destructive version, it was easy enough just to
>> return (cdr thing) instead of thing.
>
> What will this code do when the saved list was really quoted, or was a
> list with the symbol list as first element? Wouldn't the backward
> compatible version cause errors?
After weeks of avoiding this, I'm nearly there. This version does
everything I need it to, EXCEPT I have somehow lost the ability to
handle single-atom data, which was the whole point of passing in a
gv-ref. I don't understand why, it seemed to be working fine, but I
switched to cl-labels and maybe changed some other things (I didn't keep
the intermediate version), and now it just doesn't do it. Would you help
me take one more look at this?
It also doesn't handle '(list), but those cases are rare and occur at
top-level, so I can take care of them in pre-processing.
#+BEGIN_SRC elisp
(defun deep-edit (data edit-p traverse-p)
(let ((stack (list (gv-deref data))))
(cl-labels ((handle-refs
(refs)
(dolist (ref refs)
(let* ((val (gv-deref ref))
(edit (when val (funcall edit-p val))))
(when (car edit)
(cl-callf (lambda (x) (funcall (car edit) x))
(gv-deref ref))
(when (cdr edit)
(handle-refs (list ref))))
(when (funcall traverse-p (gv-deref ref))
(push (gv-deref ref) stack))))))
(while stack
(let ((current (pop stack)))
(cond
((consp current)
(handle-refs `(,(gv-ref (car current))
,(gv-ref (cdr current)))))
((and (arrayp current) (not (stringp current)))
(handle-refs
(mapcar (lambda (idx) (gv-ref (aref current idx)))
(number-sequence 0 (1- (length current))))))
((hash-table-p current)
(let ((refs '()))
(maphash (lambda (key _val)
;; Order matters here!
(push (gv-ref (gethash key current)) refs)
(push (gv-ref (deep-edit-hash-key key current))
refs))
current)
(handle-refs (nreverse refs))))))))))
(let ((tree '("one" two ''(three "four" (list "five")))))
(deep-edit
(gv-ref tree)
(lambda (thing)
(cond ((consp thing)
(pcase (car thing)
('list (cons #'cdr t))
('quote (cons #'cadr t))))
((stringp thing)
(cons #'upcase nil))))
(lambda (thing)
(consp thing)))
tree)
#+END_SRC
The above works, yet if I change `tree' to be a plain string "one", it
isn't transformed. I just can't see why.
Eric
next prev parent reply other threads:[~2018-07-28 20:52 UTC|newest]
Thread overview: 41+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-05-05 1:04 Help with recursive destructive function Eric Abrahamsen
2018-05-05 1:18 ` Stefan Monnier
2018-05-05 1:37 ` Michael Heerdegen
2018-05-05 15:41 ` Michael Heerdegen
2018-05-06 17:29 ` Eric Abrahamsen
2018-05-06 19:29 ` Michael Heerdegen
2018-05-06 19:34 ` Eric Abrahamsen
2018-05-06 18:27 ` Eric Abrahamsen
2018-05-07 2:01 ` Michael Heerdegen
2018-05-07 3:01 ` Eric Abrahamsen
2018-05-07 4:16 ` Clément Pit-Claudel
2018-05-07 14:14 ` Michael Heerdegen
2018-05-07 16:26 ` Stefan Monnier
2018-05-07 16:52 ` Eric Abrahamsen
2018-05-08 13:15 ` Michael Heerdegen
2018-05-08 18:42 ` Eric Abrahamsen
2018-05-08 19:03 ` Clément Pit-Claudel
2018-05-08 19:41 ` Eric Abrahamsen
2018-05-10 1:52 ` Michael Heerdegen
2018-05-10 17:08 ` Michael Heerdegen
2018-05-11 2:12 ` Eric Abrahamsen
2018-05-14 14:27 ` Michael Heerdegen
2018-05-14 16:57 ` Eric Abrahamsen
2018-05-14 23:16 ` Michael Heerdegen
2018-05-15 0:28 ` Eric Abrahamsen
2018-07-28 20:52 ` Eric Abrahamsen [this message]
2018-07-28 23:46 ` Michael Heerdegen
2018-07-28 23:59 ` Eric Abrahamsen
2018-07-29 0:09 ` Michael Heerdegen
2018-06-04 22:28 ` Eric Abrahamsen
2018-06-05 0:23 ` Michael Heerdegen
2018-06-06 21:04 ` Eric Abrahamsen
2018-06-06 21:58 ` Michael Heerdegen
2018-06-06 22:10 ` Eric Abrahamsen
2018-06-06 23:10 ` Eric Abrahamsen
2018-06-06 23:30 ` Michael Heerdegen
2018-06-07 0:49 ` Eric Abrahamsen
2018-06-07 1:13 ` Michael Heerdegen
2018-06-06 23:18 ` Michael Heerdegen
2018-06-07 13:59 ` Stefan Monnier
2018-06-07 16:51 ` Eric Abrahamsen
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
List information: https://www.gnu.org/software/emacs/
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87fu03gk13.fsf@ericabrahamsen.net \
--to=eric@ericabrahamsen.net \
--cc=emacs-devel@gnu.org \
--cc=michael_heerdegen@web.de \
/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 public inbox
https://git.savannah.gnu.org/cgit/emacs.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).