From: Szymon
Subject: How to destructure list to places?
Date: 
Message-ID: <87mzxy1yz6.fsf@eva.rplacd.net>
... without using values?

I mean:

(setf (values place-1 place-2 .... place-n)
      (values-list list))
.

Is there other way?

TIA, Szymon.
 

From: Matthew Danish
Subject: Re: How to destructure list to places?
Date: 
Message-ID: <87wtx2qtyi.fsf@mapcar.org>
Szymon <············@o2.pl> writes:
> ... without using values?

(destructuring-bind (a b (c d)) (list 1 2 (list 3 4))
  (list b c d a))

-- 
;; Matthew Danish -- user: mrd domain: cmu.edu
;; OpenPGP public key: C24B6010 on keyring.debian.org
From: Barry Margolin
Subject: Re: How to destructure list to places?
Date: 
Message-ID: <barmar-C74BB7.21170103112004@comcast.dca.giganews.com>
In article <··············@mapcar.org>,
 Matthew Danish <··········@cmu.edu> wrote:

> Szymon <············@o2.pl> writes:
> > ... without using values?
> 
> (destructuring-bind (a b (c d)) (list 1 2 (list 3 4))
>   (list b c d a))

How does that assign to places, i.e. generalized references?

-- 
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
From: Joerg Hoehle
Subject: Re: How to destructure list to places?
Date: 
Message-ID: <uvfc35uy1.fsf@users.sourceforge.net>
Barry Margolin <······@alum.mit.edu> writes:
> > (destructuring-bind (a b (c d)) (list 1 2 (list 3 4))
> >   (list b c d a))
> How does that assign to places, i.e. generalized references?

The Iterate package features a destructuring DSETQ which assigns
(and also recognizes NIL in the template as meaning IGNORE):

> (let (a b c d)
    (dsetq (a b (c d)) (list 1 2 (list 3 4)))
    (list b c d a))
(2 3 4 1)

http://common-lisp.net/project/iterate/index.html

It ought to work with symbol-macrolet names, however destructuring
syntax seems incompatible with generalized references, i.e.
(destructure (car x) (foo)
  -> create/use variables car and x
  -> or (temporarily?) set (car x) to value of foo??

CLISP provides ext:LETF which temporarily binds places
(let ((a (list 1 2))) (ext:letf (((car a) 0)) (prin1 a)) a)
(0 2)
(1 2)
Macro-writing exercise: write it yourself
hint: setf-expanders

Regards,
	Jorg Hohle
Telekom/T-Systems Technology Center
From: Svein Ove Aas
Subject: Re: How to destructure list to places?
Date: 
Message-ID: <cmbgmi$o16$1@services.kq.no>
Szymon wrote:

> 
> ... without using values?
> 
> I mean:
> 
> (setf (values place-1 place-2 .... place-n)
>       (values-list list))
> .
> 
> Is there other way?
> 
destructuring-bind? 
From: Barry Margolin
Subject: Re: How to destructure list to places?
Date: 
Message-ID: <barmar-654DA2.20484103112004@comcast.dca.giganews.com>
In article <············@services.kq.no>,
 Svein Ove Aas <·········@aas.no> wrote:

> Szymon wrote:
> 
> > 
> > ... without using values?
> > 
> > I mean:
> > 
> > (setf (values place-1 place-2 .... place-n)
> >       (values-list list))
> > .
> > 
> > Is there other way?
> > 
> destructuring-bind? 

DESTRUCTURING-BIND treats a list in the pattern as a list, not a place 
that should be assigned to.  E.g. if you did:

(destructuring-bind ((car foo)) list ...)

it would bind CAR and FOO to the caar and cadar of LIST's value, 
respectively.  What he wants to do is set the car of FOO's value to the 
car of LIST's value.

Or are you suggesting that he use DESTRUCTURING-BIND to pick out the 
pieces from the list, and then assign them with SETF, e.g.

(destructuring-bind (val1 val2 val3 ... valn) list
  (setf place-1 val1 place-2 val2 place-3 val3 ... place-n valn))

-- 
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
From: Pascal Bourguignon
Subject: Re: How to destructure list to places?
Date: 
Message-ID: <871xfaxn6e.fsf@naiad.informatimago.com>
Barry Margolin <······@alum.mit.edu> writes:
> > Szymon wrote:
> > > ... without using values?

Why?  Do you voluntarily spend the day with a foot cast in a block of cement?

> Or are you suggesting that he use DESTRUCTURING-BIND to pick out the 
> pieces from the list, and then assign them with SETF, e.g.
> 
> (destructuring-bind (val1 val2 val3 ... valn) list
>   (setf place-1 val1 place-2 val2 place-3 val3 ... place-n valn))

(destructuring-bind (val1 val2 val3 ... valn) list
 (setf (values place-1 place-2 place-3 ... place-n) (val1 val2 val3 ... valn))

to improve readability.


-- 
__Pascal Bourguignon__
From: Barry Margolin
Subject: Re: How to destructure list to places?
Date: 
Message-ID: <barmar-D4B4AC.23515703112004@comcast.dca.giganews.com>
In article <··············@naiad.informatimago.com>,
 Pascal Bourguignon <····@mouse-potato.com> wrote:

> Barry Margolin <······@alum.mit.edu> writes:
> > > Szymon wrote:
> > > > ... without using values?
> 
> Why?  Do you voluntarily spend the day with a foot cast in a block of cement?
> 
> > Or are you suggesting that he use DESTRUCTURING-BIND to pick out the 
> > pieces from the list, and then assign them with SETF, e.g.
> > 
> > (destructuring-bind (val1 val2 val3 ... valn) list
> >   (setf place-1 val1 place-2 val2 place-3 val3 ... place-n valn))
> 
> (destructuring-bind (val1 val2 val3 ... valn) list
>  (setf (values place-1 place-2 place-3 ... place-n) (val1 val2 val3 ... valn))
> 
> to improve readability.

That should be:

(setf (values place-1 place-2 place-3 ... place-n)
      (values val1 val2 val3 ... valn))
       ^^^^^^

-- 
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
From: Szymon
Subject: Re: How to destructure list to places?
Date: 
Message-ID: <87hdo523j1.fsf@eva.rplacd.net>
Pascal Bourguignon <····@mouse-potato.com> writes:

> Barry Margolin <······@alum.mit.edu> writes:
> > > Szymon wrote:
> > > > ... without using values?
> 
> Why?

I asked without strong reason. Things that come in my mind:
1) simplicity
2) efficiency

(funcall
  (compile nil
           '(lambda ()
              (let ((list (list 1 2 3))
                    (a (make-list 3))
                    (b (make-list 3))
                    (c (vector nil nil)))
                (time
                 (loop repeat 500 do
                   (setf (values (car a) (car b) (svref c 0))
                         (values-list list))))
                (time
                 (loop repeat 500 do
                   (destructuring-setf ((car a) (car b) (svref c 0)) list)))))))

; Evaluation took(cmucl):

;   71,555 CPU cycles


; Evaluation took(cmucl):

;   32,309 CPU cycles

> Do you voluntarily spend the day with a foot cast in a block of cement?

?

Regards, Szymon.

ps.

(defmacro destructuring-setf ((&rest places) list)
  (let ((pointer (gensym)))
    `(let ((,pointer ,list))
       (setf ,@(mapcan (lambda (place)
			 `(,place (car ,pointer) ,pointer (cdr ,pointer)))
		       places)))))
From: Pascal Bourguignon
Subject: Re: How to destructure list to places?
Date: 
Message-ID: <87d5ytwudm.fsf@naiad.informatimago.com>
Szymon <············@o2.pl> writes:

> Pascal Bourguignon <····@mouse-potato.com> writes:
> 
> > Barry Margolin <······@alum.mit.edu> writes:
> > > > Szymon wrote:
> > > > > ... without using values?
> > 
> > Why?
> 
> I asked without strong reason. Things that come in my mind:
> 1) simplicity
> 2) efficiency
> 
> (funcall
>   (compile nil
>            '(lambda ()
>               (let ((list (list 1 2 3))
>                     (a (make-list 3))
>                     (b (make-list 3))
>                     (c (vector nil nil)))
>                 (time
>                  (loop repeat 500 do
>                    (setf (values (car a) (car b) (svref c 0))
>                          (values-list list))))
>                 (time
>                  (loop repeat 500 do
>                    (destructuring-setf ((car a) (car b) (svref c 0)) list)))))))
> 
> ; Evaluation took(cmucl):
> 
> ;   71,555 CPU cycles
> 
> 
> ; Evaluation took(cmucl):
> 
> ;   32,309 CPU cycles

Ah but this question is highly dependent on the processor and the
compiler you're using!

Here are the results with sbcl/ppc, which has 32 registers where values
can be placed! (looping 500000 times):

Evaluation took:
  		 0.048 seconds of real time
  		 0.047992 seconds of user run time
  		 0.0 seconds of system run time
  		 0 page faults and
  		 56 bytes consed.
Evaluation took:
  		 0.235 seconds of real time
  		 0.228965 seconds of user run time
  		 0.0 seconds of system run time
  		 0 page faults and
  		 56 bytes consed.

That's why it's better to first write the clearer lisp code for the
human reader. If you have a deficient implementation or processor, you
can always add compiler macros later.

-- 
__Pascal Bourguignon__
From: Kaz Kylheku
Subject: Re: How to destructure list to places?
Date: 
Message-ID: <cf333042.0411040844.5ccfa23f@posting.google.com>
Szymon <············@o2.pl> wrote in message news:<··············@eva.rplacd.net>...
> ... without using values?
> 
> I mean:
> 
> (setf (values place-1 place-2 .... place-n)
>       (values-list list))
> .
> 
> Is there other way?

I have a gut feeling you are looking for something very direct, that
avoids the use of any intermediate variables, and works like
DESTRUCTURING-BIND, where you have a pattern matching template against
a list, but that template itself contains markup of the places where
you want the extracted values to go.

I think there has to be some inconvenience of a notation which
explicitly indicates what is template structure and what is a place,
because they are too self-similar. Analogy: consider the special
notations within backquote that are needed to distinguish substitution
and splicing points.

Something like this would be ambiguous:

  (destructuring-setf ((a)) list)

because, what place is intended? Is it (A) or is it A?

Some existing read notation could be abused to annotate the difference
in a condensed way. For example QUOTE. Or maybe vector read syntax:

  ;; using vectors to wrap places:

  (destructuring-setf (#((a))) list) ; (setf (a) (car list))
  (destructuring-setf (#(a)) list)  ; (setf a (car list))

  ;; using quote to denote them:

  (destructuring-setf ('(a)) list)   ; (setf (a) (car list))
  (destructuring-setf ('a) list)     ; (setf a (car list))

This improves readability, but there is potential confusion from
overloading the meaning of quote. (Or is it really all that
overloaded? What is quote, it means ``this piece of the body is to be
taken literally''. I would argue that quote is doing its regular job
here, in the abstract sense: it suppresses the ordinary evaluation of
structure within the list pattern matching language in order to
introduce a literal form that represents the assignment place).

Now this DESTRUCTURING-SETF could be just written in terms of
DESTRUCTURING-BIND. The job is simple: hunt down the quotes, pull out
the expressions and substitute them with gensyms. Then generate the
DESTRUCTURING-BIND that pulls out the list into gensyms, and does a
SETF from the gensyms to to the places.
From: Marcin 'Qrczak' Kowalczyk
Subject: Re: How to destructure list to places?
Date: 
Message-ID: <87k6t15t0x.fsf@qrnik.zagroda>
···@ashi.footprints.net (Kaz Kylheku) writes:

> Something like this would be ambiguous:
>
>   (destructuring-setf ((a)) list)
>
> because, what place is intended? Is it (A) or is it A?
>
> Some existing read notation could be abused to annotate the difference
> in a condensed way. For example QUOTE. Or maybe vector read syntax:

It should be a comma. It would be consistent with commas inside backquote.

Except that CL can't do that, because commas are expanded too early,
by the reader, instead of by the backquote macro. They can't be used
outside backquote, for other purposes than originally intended.

It could be done in Scheme, because it treats ,x as (unquote x)
and at the same time forbids to use unquote as a variable identifier.
Its backquote mechanism is more flexible.

-- 
   __("<         Marcin Kowalczyk
   \__/       ······@knm.org.pl
    ^^     http://qrnik.knm.org.pl/~qrczak/
From: Szymon
Subject: Re: How to destructure list to places?
Date: 
Message-ID: <87d5yt1lb7.fsf@eva.rplacd.net>
···@ashi.footprints.net (Kaz Kylheku) writes:

> [.....]

>   (destructuring-setf ('(a)) list)   ; (setf (a) (car list))
>   (destructuring-setf ('a) list)     ; (setf a (car list))
> 
> This improves readability, but there is potential confusion from
> overloading the meaning of quote. (Or is it really all that
> overloaded? What is quote, it means ``this piece of the body is to be
> taken literally''. I would argue that quote is doing its regular job
> here, in the abstract sense: it suppresses the ordinary evaluation of
> structure within the list pattern matching language in order to
> introduce a literal form that represents the assignment place).
> 
> Now this DESTRUCTURING-SETF could be just written in terms of
> DESTRUCTURING-BIND. The job is simple: hunt down the quotes, pull out
> the expressions and substitute them with gensyms. Then generate the
> DESTRUCTURING-BIND that pulls out the list into gensyms, and does a
> SETF from the gensyms to to the places.

Good idea :) thanks. I'm going to implement DESTRUCTURING-SETF (and
DESTRUCTURING-LETF) this way.

Btw, I have another idea (but I think yours is better)...

(HAIRY-DESTRUCTURING-SETF tree pattern places)

example:

(h/d/setf tree (2 (2) (2 (1))) p1 p2 p3 p4 p5 p6 p7)

or

(h/d/setf tree (* * (* *) (* * (*))) p1 p2 p3 p4 p5 p6 p7)

===

(destructuring-setf ('p1 'p2 ('p3 'p4) ('p5 'p6 ('p7))) tree)

Regards, Szymon.
From: Kaz Kylheku
Subject: Re: How to destructure list to places?
Date: 
Message-ID: <cf333042.0411041357.1278c1b9@posting.google.com>
Szymon <············@o2.pl> wrote in message news:<··············@eva.rplacd.net>...
> ... without using values?
> 
> I mean:
> 
> (setf (values place-1 place-2 .... place-n)
>       (values-list list))
> .
> 
> Is there other way?

Here you go, sir!

(defmacro destructuring-setf (template tree)
  (labels ((gensymize-quotes (tree)
             (cond
               ((atom tree)
                (values tree nil))
               ((eq 'quote (first tree))
                (let ((sym (gensym)))
                  (values sym (list (second tree) sym))))
               (t
                (multiple-value-bind (left-tree left-syms)
                                     (gensymize-quotes (first tree))
                  (multiple-value-bind (right-tree right-syms)
                                       (gensymize-quotes (rest tree))
                    (values (cons left-tree right-tree)
                            (append left-syms right-syms))))))))
    (multiple-value-bind (gensym-template gensym-list)
                         (gensymize-quotes template)
      `(destructuring-bind ,gensym-template ,tree
         (setf ,@gensym-list)))))


In the template, places are denoted by QUOTE, for which you can use
the familiar ' shorthand. Example:

   (destructuring-setf ('x 'y ('z)) '(1 2 (3)))

This assigns 1 to X, 2 to Y and 3 to Z. A sample expansion of the
above is:

(DESTRUCTURING-BIND (#:G296 #:G297 (#:G298)) '(1 2 (3))
 (SETF X #:G296 Y #:G297 Z #:G298))

You have to be careful, because if you have any unquoted symbols in
the template, they are passed through to the DESTRUCTURING-BIND
template without being replaced by gensyms. This can be exploited, as
in the following hack:

  (destructuring-setf ('x ignore ('z)) '(1 2 (3))))

The IGNORE variable is set up within the expansion and consumes the
value 2.

Enjoy, improve ...
From: Szymon
Subject: Re: How to destructure list to places?
Date: 
Message-ID: <871xf81lvp.fsf@eva.rplacd.net>
···@ashi.footprints.net (Kaz Kylheku) writes:

> [......]

> (defmacro destructuring-setf (template tree)
>   (labels ((gensymize-quotes (tree)
>              (cond
>                ((atom tree)
>                 (values tree nil))
>                ((eq 'quote (first tree))
>                 (let ((sym (gensym)))
>                   (values sym (list (second tree) sym))))
>                (t

;; ------------------------------------------------------------

>                 (multiple-value-bind (left-tree left-syms)
>                                      (gensymize-quotes (first tree))
>                   (multiple-value-bind (right-tree right-syms)
>                                        (gensymize-quotes (rest tree))
>                     (values (cons left-tree right-tree)
>                             (append left-syms right-syms))))))))

Personally I would prefer this:
             
                  (multiple-value-call
                    (lambda (left-tree left-syms right-tree right-syms)
                      (values (cons left-tree right-tree)
                              (append left-syms right-syms)))
                    (gensymize-quotes (first tree))
                    (gensymize-quotes (rest tree)))

;; ------------------------------------------------------------

>     (multiple-value-bind (gensym-template gensym-list)
>                          (gensymize-quotes template)
>       `(destructuring-bind ,gensym-template ,tree
>          (setf ,@gensym-list)))))

> [.....]

> Enjoy, improve ...

Indeed: your code is enjoyable :)

Regards, Szymon.