unofficial mirror of help-gnu-emacs@gnu.org
 help / color / mirror / Atom feed
From: Okam <okamsn@protonmail.com>
To: help-gnu-emacs@gnu.org
Subject: Re: How to extract bindings from `pcase-let*`?
Date: Wed, 17 Mar 2021 01:33:46 +0000	[thread overview]
Message-ID: <a9c76e97-7d8f-80b3-c380-2d98d4783574@protonmail.com> (raw)
In-Reply-To: <jwvim5rrfmo.fsf-monnier+emacs@gnu.org>

On 3/15/21 10:45 PM, Stefan Monnier wrote:
>
>>         (pcase-let* ((`(let* ,temp-vars (let ,true-vars . ,_))
>>                       (macroexpand `(pcase-let* ((,var ,val)) ,var))))
>>           (list temp-vars true-vars)))
>
> Indeed it's not reliable: for a case like
>
>      (pcase-let (((or `(inorder ,x ,y) `(reverse ,y ,x)) FOO))
>        (cons x y))
>
> it will generate code comparable to
>
>      (if (eq (car FOO) 'inorder)
>          (cons (nth 1 FOO) (nth 2 FOO))
>        (cons (nth 2 FOO) (nth 1 FOO))
>
> [ Just obfuscated with gensym'd vars and such ]
>
> And if you replace the trivial (cons x y) with something less trivial it
> will turn into something comparable to:
>
>      (let ((body (lambda (x y) <something-less-trivial>)))
>        (if (eq (car FOO) 'inorder)
>            (funcall body (nth 1 FOO) (nth 2 FOO))
>          (funcall body (nth 2 FOO) (nth 1 FOO))))
>
> so it's far from clear how to represent this kind of code in the form of
> "a list of bindings that can be substituted into forms like `setq` or
> `let*`"
>
> OTOH, I think `pcase.el` could offer a function which could take
> a "buildbody" function as argument, where that buildbody would receive
> something like the list (x y) and would be expected to return the
> (lambda (x y) <something-less-trivial>) to use.  So you could pass it a "buildbody"
> function which takes the list (x y) and returns something like
> (lambda (tmp1 tmp2) (setq x tmp1 y tmp2)), which I expect would do more
> or less what you want.
>
>> I am doing this to attempt to optionally use Pcase for destructuring in
>> a macro that I am writing.
>
> `pcase-let` already does destructuring, so could you explain in a bit
> more detail what kind of destructuring you're looking for (and why)?
>
>
>          Stefan
>
>

I am writing a looping macro similar to `cl-loop`, and have allowed for
destructuring in accumulation clauses.  Here are some examples:

     ;; Summing the nth elements of arrays:
     ;; => (8 10 12 14 16 18)
     (loopy (list (list-elem1 list-elem2)
                  '(([1 2 3] [4 5 6])
                    ([7 8 9] [10 11 12])))
            (sum [sum1 sum2 sum3] list-elem1)
            (sum [sum4 sum5 sum6] list-elem2))

     ;; Or, more simply:
     ;; => (8 10 12 14 16 18)
     (loopy (list list-elem '(([1 2 3] [4 5 6])
                              ([7 8 9] [10 11 12])))
            (sum ([sum1 sum2 sum3] [sum4 sum5 sum6])
                 list-elem))

     ;; Separate the elements of sub-list:
     ;; => ((1 3) (2 4))
     (loopy (list i '((1 2) (3 4)))
            (collect (elem1 elem2) i))

There is a built-in destructuring system for this in the macro, but a
user requested a way to use other destructuring systems, such as Dash,
Pcase, or `seq-let`.

To do this for accumulation, I don't want to actually assign the values
determined by Dash or Pcase to the variables named by the user.
Instead, I want to accumulate those values into the named variables.

Here is an example of the macro that I tested with Pcase (before I
realized my mistake)

     ;; => ((1 4) (3 6))
     (loopy (flag pcase)
            (list elem '((1 (2 3)) (4 (5 6))))
            (collect `(,a (,_ ,b)) elem))

in which the `collect` expression expands into something like

     (setq a (append a (list some-value-from-elem)))
     (setq b (append b (list some-other-value-from-elem)))

where `some-value-from-elem` and `some-other-value-from-elem` are
determined by Pcase, Dash, or other destructuring systems.

Do you think that this is doable using Pcase?

A link to the macro:
https://github.com/okamsn/loopy




  reply	other threads:[~2021-03-17  1:33 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-03-15  1:43 How to extract bindings from `pcase-let*`? Okam
2021-03-15 15:38 ` Stefan Monnier
2021-03-16  1:50   ` Okam
2021-03-16  2:45     ` Stefan Monnier
2021-03-17  1:33       ` Okam [this message]
2021-03-17  2:59         ` Stefan Monnier

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=a9c76e97-7d8f-80b3-c380-2d98d4783574@protonmail.com \
    --to=okamsn@protonmail.com \
    --cc=help-gnu-emacs@gnu.org \
    /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.
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).