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.
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
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
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
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.
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