From: Raymond Wai-man LO
Subject: How to set values to a list of variables?
Date: 
Message-ID: <LO.91Jul19124917@kongur.eecs.ucdavis.edu>
I am trying to write a function (or macro) to set a list of variables
recursively.  For example,

(setl '(a (b c) . d) '(1 (2 3) 4 5 6))
       =>  a -> 1
       =>  b -> 2
       =>  c -> 3
       =>  d -> (4 5 6)


(defun setl (vars vals)
  (cond ((null vars) nil)
	((atom vars)
	 (set vars vals))
	((listp vals)
	 (setl (car vars) (car vals))
	 (setl (cdr vars) (cdr vals)))
	(t
	 (error "SETL:  Structures of ~A and ~A did not match." vars vals))))


The above is one implementated with function.  But the problem is the
vars are evaluated in a scope different from the calling function.  So
my questions are:

* Is there any way to tell setl to use the scope of the calling
function?

* How can this be implemented with macros (so that the scope is right)?


--
Raymond Lo <··@fuji.cs.ucdavis.edu>
Computer Science, Univ. of California, Davis, CA 95616

From: Len Charest
Subject: Re: How to set values to a list of variables?
Date: 
Message-ID: <1991Jul20.010907.8479@jpl-devvax.jpl.nasa.gov>
In article <················@kongur.eecs.ucdavis.edu>, ··@kongur.eecs.ucdavis.edu (Raymond Wai-man LO) writes:
> I am trying to write a function (or macro) to set a list of variables
> recursively.  For example,
> 
> (setl '(a (b c) . d) '(1 (2 3) 4 5 6))
>        =>  a -> 1
>        =>  b -> 2
>        =>  c -> 3
>        =>  d -> (4 5 6)
[defun setl deleted]
> --
> Raymond Lo <··@fuji.cs.ucdavis.edu>
> Computer Science, Univ. of California, Davis, CA 95616

If you are using a Common Lisp that conforms to CLtL2 then take a look at the macro DESTRUCTURING-BIND. Otherwise, I believe this macro is included in one of the util files that come with PCL.

-- 
*
Len Charest, Jr.                                       ·······@ai-cyclops.jpl.nasa.gov
JPL Artificial Intelligence Group
*
From: Barry Margolin
Subject: Re: How to set values to a list of variables?
Date: 
Message-ID: <1991Jul20.032555.2022@Think.COM>
In article <················@kongur.eecs.ucdavis.edu> ··@kongur.eecs.ucdavis.edu (Raymond Wai-man LO) writes:
>I am trying to write a function (or macro) to set a list of variables
>recursively.  For example,
>
>(setl '(a (b c) . d) '(1 (2 3) 4 5 6))
>       =>  a -> 1
>       =>  b -> 2
>       =>  c -> 3
>       =>  d -> (4 5 6)

[Example function definition omitted]

>The above is one implementated with function.  But the problem is the
>vars are evaluated in a scope different from the calling function.  So
>my questions are:
>
>* Is there any way to tell setl to use the scope of the calling
>function?

No.  Functions can't access lexical environments, because lexical
environments exist only at compile time, not run time.

>* How can this be implemented with macros (so that the scope is right)?

Very similarly to your function definition, recursively:

(defmacro setl (vars vals)
  (cond ((null vars)
	 `(progn))
	((atom vars)
	 `(setq ,vars ,vals))
	((consp vals)	; was LISTP in your function
	 `(progn (setl ,(car vars) ,(car vals))
		 (setl ,(cdr vars) ,(cdr vals))))
	(t (error "~S: Structures of ~S and ~S did not match."
		  'setl vars vals))))
-- 
Barry Margolin, Thinking Machines Corp.

······@think.com
{uunet,harvard}!think!barmar
From: Jacques Duthen
Subject: Re: How to set values to a list of variables?
Date: 
Message-ID: <1991Jul26.111447.26398@ircam.fr>
In article <·····················@Think.COM> ······@think.com writes:
>In article <················@kongur.eecs.ucdavis.edu> ··@kongur.eecs.ucdavis.edu (Raymond Wai-man LO) writes:
>>I am trying to write a function (or macro) to set a list of variables
>>recursively.  For example,
>>
>>(setl '(a (b c) . d) '(1 (2 3) 4 5 6))
>>       =>  a -> 1
>>       =>  b -> 2
>>       =>  c -> 3
>>       =>  d -> (4 5 6)
>
>(defmacro setl (vars vals)
>  (cond ((null vars)
>	 `(progn))
>	((atom vars)
>	 `(setq ,vars ,vals))
>	((consp vals)	; was LISTP in your function
>	 `(progn (setl ,(car vars) ,(car vals))
>		 (setl ,(cdr vars) ,(cdr vals))))
>	(t (error "~S: Structures of ~S and ~S did not match."
>		  'setl vars vals))))
>-- 
>Barry Margolin, Thinking Machines Corp.

I'm very surprised to see that coming from Barry !

The macro you wrote can work only if you statically know the list of variables
(which could be normal) but also the list of values !
Actually, your code work only for something like:
(setl (a (b c) . d) (1 (2 3) 4 5 6))
But not for something like:
(let ((lvar '(a (b c) . d)) (lval '(1 (2 3) 4 5 6)))
  (setl lvar lval))
nor
(let ((lval '(1 (2 3) 4 5 6)))
  (setl (a (b c) . d) lval))

The latest probably can be done using your macro without the commas which
are before the vals.

Am I wrong ?							[jack]
From: Raymond Lo
Subject: Re: How to set values to a list of variables?
Date: 
Message-ID: <LO.91Jul26101107@ararat.eecs.ucdavis.edu>
In article <······················@ircam.fr> ······@ircam.fr (Jacques Duthen) writes:

> >
> >(defmacro setl (vars vals)
> >  (cond ((null vars)
> >	 `(progn))
> >	((atom vars)
> >	 `(setq ,vars ,vals))
> >	((consp vals)	; was LISTP in your function
> >	 `(progn (setl ,(car vars) ,(car vals))
> >		 (setl ,(cdr vars) ,(cdr vals))))
> >	(t (error "~S: Structures of ~S and ~S did not match."
> >		  'setl vars vals))))
> >-- 
> >Barry Margolin, Thinking Machines Corp.
> 
> I'm very surprised to see that coming from Barry !
> 
> The macro you wrote can work only if you statically know the list of variables
> (which could be normal) but also the list of values !
> Actually, your code work only for something like:
> (setl (a (b c) . d) (1 (2 3) 4 5 6))
> But not for something like:
> (let ((lvar '(a (b c) . d)) (lval '(1 (2 3) 4 5 6)))
>   (setl lvar lval))
> nor
> (let ((lval '(1 (2 3) 4 5 6)))
>   (setl (a (b c) . d) lval))
> 
> The latest probably can be done using your macro without the commas which
> are before the vals.


Here is what I have after reading sloop.lsp.   The macro only work if
the list of variables is known statically, but we don't know need to
know the list of values.  Notice that the list of values is copied so
that any side effect is executed once.


(defmacro setl (vars expr)
  (cond ((symbolp vars)
	 `(setf ,vars ,expr))
	(t   (let ((vals (gentemp)))
	       `(let ((,vals ,expr)) ,(setl-1 vars vals))))))

(defun setl-1 (vars vals)
  (cond ((symbolp vars)
	 (and vars `(setf ,vars ,vals)))
	((consp vars)
	 `(progn ,(setl-1 (car vars) `(car ,vals))
	   ,@(if (consp (cdr vars))
		 (list (setl-1 (cdr vars) `(cdr ,vals)))
		 (and (cdr vars) `((setf ,(cdr vars) (cdr ,vals)))))))
	(t (error ""))))


In response to Barry's implementation, he is correct because of the
implementation of the error checking

	(t (error "~S: Structures of ~S and ~S did not match."
		  'setl vars vals))))

in my original posting, which is only possible when the value is
statically known at macro expansion time.


Just as as exercise, I try to write a version of setl that takes both
a list of vars, which are defined in the lexical scope,n and values
not known statically.  That involves (set sym val), but set changes
the special sym instead of the lexical sym.  I think there is no way
to implement such function in CL.  Is that true?

--
Raymond Lo <··@fuji.cs.ucdavis.edu>
Computer Science, Univ. of California, Davis, CA 95616