From: Tamas Papp
Subject: defparameter (& co) with multiple values idiom
Date: 
Message-ID: <87642yfz0x.fsf@pu100877.student.princeton.edu>
Is there a nice way to write

(multiple-value-bind (foo bar) (calculate-foo-bar)
  (defparameter *foo* foo)
  (defparameter *bar* bar))

I know how to write a macro for this, but I am looking for an existing
idiom.

Tamas

From: Stefan Arentz
Subject: Re: defparameter (& co) with multiple values idiom
Date: 
Message-ID: <87642yved0.fsf@kip.sateh.com>
Tamas Papp <······@gmail.com> writes:

> Is there a nice way to write
> 
> (multiple-value-bind (foo bar) (calculate-foo-bar)
>   (defparameter *foo* foo)
>   (defparameter *bar* bar))
> 
> I know how to write a macro for this, but I am looking for an existing
> idiom.

I'm a lisp n00b so excuse me if this is a st00pid question, but what
is wrong with the code you pasted?

 S.
From: Tamas Papp
Subject: Re: defparameter (& co) with multiple values idiom
Date: 
Message-ID: <871wdmfuvs.fsf@pu100877.student.princeton.edu>
Stefan Arentz <·············@gmail.com> writes:

> Tamas Papp <······@gmail.com> writes:
>
>> Is there a nice way to write
>> 
>> (multiple-value-bind (foo bar) (calculate-foo-bar)
>>   (defparameter *foo* foo)
>>   (defparameter *bar* bar))
>> 
>> I know how to write a macro for this, but I am looking for an existing
>> idiom.
>
> I'm a lisp n00b so excuse me if this is a st00pid question, but what
> is wrong with the code you pasted?

Nothing wrong with it per se, I just find this thing useful so I
guessed that there must be a construct for it, but found nothing in
the HyperSpec.

Anyhow, here is a macro that I am currently using:

(defmacro defparameter-values ((&rest names) form)
  (assert (every #'symbolp names))
  (labels ((expand-definitions (names tmp-names)
	     (unless (null names)
	       (cons `(defparameter ,(car names) ,(car tmp-names))
		     (expand-definitions (cdr names) (cdr tmp-names))))))
    (let ((tmp-names (mapcar #'(lambda (name) (gensym (symbol-name name))) names)))
      `(multiple-value-bind (,@tmp-names) ,form
	 ,@(expand-definitions names tmp-names)))))

Tamas
From: Pillsy
Subject: Re: defparameter (& co) with multiple values idiom
Date: 
Message-ID: <1188387858.827904.278550@o80g2000hse.googlegroups.com>
On Aug 29, 7:22 am, Tamas Papp <······@gmail.com> wrote:

> Anyhow, here is a macro that I am currently using:

> (defmacro defparameter-values ((&rest names) form)
>   (assert (every #'symbolp names))
>   (labels ((expand-definitions (names tmp-names)
>              (unless (null names)
>                (cons `(defparameter ,(car names) ,(car tmp-names))
>                      (expand-definitions (cdr names) (cdr tmp-names))))))
>     (let ((tmp-names (mapcar #'(lambda (name) (gensym (symbol-name name))) names)))
>       `(multiple-value-bind (,@tmp-names) ,form
>          ,@(expand-definitions names tmp-names)))))

If you use MULTIPLE-VALUE-SETQ instead, you can get rid of the
temporaries, like so:

(defmacro defparameter-values ((&rest names) form)
  (assert (every #'symbolp names))
  `(progn
     ,@(mapcar (lambda (n) `(defparameter ,n nil)) names)
     (multiple-value-setq ,names ,form)))

This doesn't match the return value, but I doubt that's important.

Cheers,
Pillsy
From: Chris Russell
Subject: Re: defparameter (& co) with multiple values idiom
Date: 
Message-ID: <1188657112.812551.64970@19g2000hsx.googlegroups.com>
On 29 Aug, 12:22, Tamas Papp <······@gmail.com> wrote:

> Anyhow, here is a macro that I am currently using:
>
> (defmacro defparameter-values ((&rest names) form)
>   (assert (every #'symbolp names))
>   (labels ((expand-definitions (names tmp-names)
>              (unless (null names)
>                (cons `(defparameter ,(car names) ,(car tmp-names))
>                      (expand-definitions (cdr names) (cdr tmp-names))))))
>     (let ((tmp-names (mapcar #'(lambda (name) (gensym (symbol-name name))) names)))
>       `(multiple-value-bind (,@tmp-names) ,form
>          ,@(expand-definitions names tmp-names)))))
>
> Tamas

Recursion is good, but more mapcar is even better...

(defmacro multiple-values-defp(symbol-list values)
	   (let ((gens (mapcar (lambda(x)(declare (ignore x))(gensym)) symbol-
list)))
	     `(multiple-value-bind ,gens ,values
		,@(mapcar (lambda (x y) `(defparameter ,x ,y)) symbol-list gens))))

Of course it looks even cleaner using smalltalk/arc style read macros.

(defmacro multiple-values-defp(symbol-list values)
	   (let ((gens (mapcar [gensym] symbol-list)))
	     `(multiple-value-bind ,gens ,values
		,@(mapcar [list 'defparameter _x _y] symbol-list gens))))
From: Daniel Barlow
Subject: Re: defparameter (& co) with multiple values idiom
Date: 
Message-ID: <1188399858.29949.0@proxy01.news.clara.net>
Tamas Papp wrote:
> Is there a nice way to write
> 
> (multiple-value-bind (foo bar) (calculate-foo-bar)
>   (defparameter *foo* foo)
>   (defparameter *bar* bar))
> 
> I know how to write a macro for this, but I am looking for an existing
> idiom.

I'd be surprised: symbol munging (FOO -> *FOO*) tends to be considered 
non-nice.  How about bypassing the need for temporary variables completely?

(defvar *foo*)
(defvar *bar*)
(setf (values *foo* *bar*) (calculate-foo-bar))


-dan
From: Matthias Buelow
Subject: Re: defparameter (& co) with multiple values idiom
Date: 
Message-ID: <5jr7g6Fusp5U1@mid.dfncis.de>
Daniel Barlow wrote:

> (defvar *foo*)
> (defvar *bar*)
> (setf (values *foo* *bar*) (calculate-foo-bar))

And if one wants to keep the definition and initialization combined, one
can wrap them in a lexical block, like

(block nil	; or progn, ...
  (defvar *foo*)
  (defvar *bar*)
  (setf ...))

to guard against the type of maintainer who might, years later in a
hurry, carelessly add some stuff in between, like:

(defvar *foo*)
(defvar *bar*)
(defvar *baz*)
(defvar *honk* (some-lengthy
  computation
  here)
;; some rambling comment here
;; going on for lines and lines
;; and lines...

(defun and-now-for-something-completely-different (here)
  ...)

;; and the initialization becomes disconnected from the definition until
;; some nasty bugs sneak in.
(setf (values *foo* *bar*) (calculate-foo-bar))

Or make it a macro.
From: Duane Rettig
Subject: Re: defparameter (& co) with multiple values idiom
Date: 
Message-ID: <o0642vqy59.fsf@gemini.franz.com>
Matthias Buelow <···@incubus.de> writes:

> Daniel Barlow wrote:
>
>> (defvar *foo*)
>> (defvar *bar*)
>> (setf (values *foo* *bar*) (calculate-foo-bar))
>
> And if one wants to keep the definition and initialization combined, one
> can wrap them in a lexical block, like
>
> (block nil	; or progn, ...
>   (defvar *foo*)
>   (defvar *bar*)
>   (setf ...))

Progn is better; it maintains the top-level-ness of the original
forms.

-- 
Duane Rettig    ·····@franz.com    Franz Inc.  http://www.franz.com/
555 12th St., Suite 1450               http://www.555citycenter.com/
Oakland, Ca. 94607        Phone: (510) 452-2000; Fax: (510) 452-0182