From: ········@hex.net
Subject: Simple Macrology
Date: 
Message-ID: <Fof_5.86066$IP1.2903755@news1.giganews.com>
I'm trying to come up with a suitable macro to wrap
defvariable/defparameter in similar fashion to setf.

That is, consider that if you want to rebind a bunch of values, you
might use:

(setf *this* "this"
      *that* "that"
      *other* '(the other thing))

I would think it a nice thing to be able to do:

(multiple-defvar 
      *this* "this"
      *that* "that"
      *other* '(the other thing))

Which would expand to:
(defvariable *this* "this")
(defvariable *that* "that")
(defvariable *other* '(the other thing))

and basically Be Shorter.

I've tried a couple "cuts" at it; no success thus far.

Latest attempt:
(defmacro multiple-defvar (name value &rest args)
  (list 'defvariable name value)
  (if (listp args)
      (multiple-defvar args)))

I think I need to do something more like (apply multiple-defvar args);
'tis not clear.
-- 
(reverse (concatenate 'string ····················@" "454aa"))
<http://www.ntlug.org/~cbbrowne/>
Culus thinks  we should go to trade  shows and see how  many people we
can kill by throwing debian cds at them

From: Johan Kullstam
Subject: Re: Simple Macrology
Date: 
Message-ID: <m3elz9kb3n.fsf@sysengr.res.ray.com>
········@hex.net writes:

> I'm trying to come up with a suitable macro to wrap
> defvariable/defparameter in similar fashion to setf.
> 
> That is, consider that if you want to rebind a bunch of values, you
> might use:
> 
> (setf *this* "this"
>       *that* "that"
>       *other* '(the other thing))
> 
> I would think it a nice thing to be able to do:
> 
> (multiple-defvar 
>       *this* "this"
>       *that* "that"
>       *other* '(the other thing))
> 
> Which would expand to:
> (defvariable *this* "this")
> (defvariable *that* "that")
> (defvariable *other* '(the other thing))
> 
> and basically Be Shorter.
> 
> I've tried a couple "cuts" at it; no success thus far.
> 
> Latest attempt:
> (defmacro multiple-defvar (name value &rest args)
>   (list 'defvariable name value)
>   (if (listp args)
>       (multiple-defvar args)))
> 
> I think I need to do something more like (apply multiple-defvar args);
> 'tis not clear.

i crufted up this out of paul graham parts to make an anaphoric setf.
you should be able to warp it to your task.  it gives an alternative
to 

;; grouping function
(defun group (source n)
  (if (zerop n) (error "zero length"))
  (labels ((rec (source acc)
             (let ((rest (nthcdr n source)))
               (if (consp rest)
                   (rec rest (cons (subseq source 0 n) acc))
                   (nreverse (cons source acc))))))
    (if source (rec source nil) nil))))

;; setf helper
(defmacro _f (op place &rest args)
  (multiple-value-bind (vars forms var set access) 
                       (get-setf-expansion place)
    `(let* (,@(mapcar #'list vars forms)
            (,(car var) (,op ,access ,@args)))
       ,set)))

(defmacro asetf (&rest implicit-pairs)
  ;; unroll for multiple pairs
  `(progn
     ,@(mapcar (lambda (pair) 
                 `(_f (lambda (it) 
                        (declare (ignorable it))
                        ,(cadr pair))
                      ,(car pair)))
               (group implicit-pairs 2))))

the group function takes the input args and reformats them into a list
of pairs.  then you'll want mapcar to stamp out (defparameter (first
pair) (second pair)) instead of the _f stuff.  you'll probably want to
wrap the group function definition in an eval-when compile form.

-- 
J o h a n  K u l l s t a m
[········@ne.mediaone.net]
sysengr
From: Dr Nick Levine
Subject: Re: Simple Macrology
Date: 
Message-ID: <3A39E73F.DC7C8367@anglia.ac.uk>
Something along the lines of 

(defmacro defparameter-multiple (&rest args)
  (when args
    (or (cdr args) (error "Something wrong: ~s" args)) ; could be neater
    (let ((symbol (car args))
          (value (cadr args))
          (more (cddr args)))
      `(progn (defparameter ,symbol ,value)
         (defparameter-multiple ,@more)))))

but note I haven't tested it thoroughly. Alternatively, you can build
the values iteratively:

(defmacro defparameter-multiple (&rest args)
  `(progn ,@(loop for pair on args by 'cddr
                  for symbol = (car args) and value = (cadr args)
                  do (or (cdr pair) (error "Something wrong: ~s" pair))
                  collect `(defparameter ,symbol ,value))))

[oh - isn't the loop macro wicked?]


Note I used defparameter here. Defvariable doesn't exist. Did you mean
defvar? If so then there's a problem - with defvar the value argument is
optional. You'd need a syntax like:
	(defvar-multiple (this "this") (unbound-var) ...) 
or some such. Yuck.

Note also I changed your name around so that the bit that starts with
"def" comes at the beginning, this being a convention for CL defining
forms.

Note finally that actually I would not recommend what you're trying to
do. Top-level defparameter or defvar forms are fine; your new macro
isn't going to make you code shorter or more transparent or more
maintainable or more efficient or anything much that it wasn't already;
you may succeed in confusing some source location systems and degrade
the functionality of your development environment. 

But don't let me put you off...

All the best,

- nick

········@hex.net wrote:
> 
> I'm trying to come up with a suitable macro to wrap
> defvariable/defparameter in similar fashion to setf.
> 
> That is, consider that if you want to rebind a bunch of values, you
> might use:
> 
> (setf *this* "this"
>       *that* "that"
>       *other* '(the other thing))
> 
> I would think it a nice thing to be able to do:
> 
> (multiple-defvar
>       *this* "this"
>       *that* "that"
>       *other* '(the other thing))
> 
> Which would expand to:
> (defvariable *this* "this")
> (defvariable *that* "that")
> (defvariable *other* '(the other thing))
> 
> and basically Be Shorter.
> 
> I've tried a couple "cuts" at it; no success thus far.
> 
> Latest attempt:
> (defmacro multiple-defvar (name value &rest args)
>   (list 'defvariable name value)
>   (if (listp args)
>       (multiple-defvar args)))
> 
> I think I need to do something more like (apply multiple-defvar args);
> 'tis not clear.
> --
> (reverse (concatenate 'string ····················@" "454aa"))
> <http://www.ntlug.org/~cbbrowne/>
> Culus thinks  we should go to trade  shows and see how  many people we
> can kill by throwing debian cds at them
From: Christopher Browne
Subject: Re: Simple Macrology
Date: 
Message-ID: <slrn93k84e.tl2.cbbrowne@knuth.brownes.org>
In our last episode (Fri, 15 Dec 2000 09:41:19 +0000),
the artist formerly known as Dr Nick Levine said:
>[oh - isn't the loop macro wicked?]

I don't regard LOOP as _overly_ wicked; it offers the ability to
create wicked excesses of complexity, but doesn't _have_ to be used
badly...

>Note I used defparameter here. Defvariable doesn't exist. Did you mean
>defvar? If so then there's a problem - with defvar the value argument is
>optional. You'd need a syntax like:
>	(defvar-multiple (this "this") (unbound-var) ...) 
>or some such. Yuck.

Fair 'nuff...

>Note also I changed your name around so that the bit that starts with
>"def" comes at the beginning, this being a convention for CL defining
>forms.
>
>Note finally that actually I would not recommend what you're trying to
>do. Top-level defparameter or defvar forms are fine; your new macro
>isn't going to make you code shorter or more transparent or more
>maintainable or more efficient or anything much that it wasn't already;
>you may succeed in confusing some source location systems and degrade
>the functionality of your development environment. 
>
>But don't let me put you off...

... And that's something to potentially dispute over to provide some
More Relevant Disputes than all the Naggum-bashing; it seems a neat idea
to have similar structuring to what is offered by SETF, but I'm _not_
arguing that this represents something that "obviously" should be added
to "CLTL3." Not before I get it working, anyways :-).
-- 
(reverse (concatenate 'string ····················@" "454aa"))
<http://www.ntlug.org/~cbbrowne/>
"I have yet  to see any problem, however  complicated, which, when you
looked at it in the right way, did not become still more complicated."
-- Poul Anderson
From: Marco Antoniotti
Subject: Re: Simple Macrology
Date: 
Message-ID: <y6cvgslra46.fsf@octagon.mrl.nyu.edu>
········@knuth.brownes.org (Christopher Browne) writes:

> In our last episode (Fri, 15 Dec 2000 09:41:19 +0000),
> the artist formerly known as Dr Nick Levine said:
> >[oh - isn't the loop macro wicked?]
> 
> I don't regard LOOP as _overly_ wicked; it offers the ability to
> create wicked excesses of complexity, but doesn't _have_ to be used
> badly...
> 
> >Note I used defparameter here. Defvariable doesn't exist. Did you mean
> >defvar? If so then there's a problem - with defvar the value argument is
> >optional. You'd need a syntax like:
> >	(defvar-multiple (this "this") (unbound-var) ...) 
> >or some such. Yuck.
> 
> Fair 'nuff...

Note that DEFVAR, DEFPARAMETER, and DEFCONSTANT take an optional
documentation string.   I'd do (untested):

(defmacro defparameter* (&rest defs)
  `(progn (loop for def in defs
                collect (destructuring-bind (name value &optional doc-string)
                             def
                           (if doc-string
                              `(defparameter ,name ,value ,doc-string)
                              `(defparameter ,name ,value))))))

Note that now you must do

(defparameter* (*this* "this")
               (*that* 'that "I meant THAT!")
               (*the-other* '(that is not what I meant)))

What do you like best?

Cheers

-- 
Marco Antoniotti =============================================================
NYU Bioinformatics Group			 tel. +1 - 212 - 998 3488
719 Broadway 12th Floor                          fax  +1 - 212 - 995 4122
New York, NY 10003, USA				 http://galt.mrl.nyu.edu/valis
             Like DNA, such a language [Lisp] does not go out of style.
			      Paul Graham, ANSI Common Lisp
From: Tim Bradshaw
Subject: Re: Simple Macrology
Date: 
Message-ID: <nkjd7euhswj.fsf@tfeb.org>
········@hex.net writes:

> I'm trying to come up with a suitable macro to wrap
> defvariable/defparameter in similar fashion to setf.
> 

Apologies for my LOOPology:

 (defmacro defvars (&rest pairs)
   `(progn
      ,@(loop for tail on pairs by #'cddr
	    while tail
	    if (cdr tail)
	    collect `(defvar ,(first tail) ,(second tail))
	    else
	    collect `(defvar ,(first tail)))))

--tim
From: Pierre R. Mai
Subject: Re: Simple Macrology
Date: 
Message-ID: <87n1dx1v9z.fsf@orion.bln.pmsf.de>
········@hex.net writes:

> I'm trying to come up with a suitable macro to wrap
> defvariable/defparameter in similar fashion to setf.
> 
> That is, consider that if you want to rebind a bunch of values, you
> might use:
> 
> (setf *this* "this"
>       *that* "that"
>       *other* '(the other thing))

Note that the above form doesn't rebind a bunch of variables, but
rather changes the value of their current bindings.

> I would think it a nice thing to be able to do:
> 
> (multiple-defvar 
>       *this* "this"
>       *that* "that"
>       *other* '(the other thing))
> 
> Which would expand to:
> (defvariable *this* "this")
> (defvariable *that* "that")
> (defvariable *other* '(the other thing))
> 
> and basically Be Shorter.

And loose the ability to provide documentation strings for each of
those, which I'd consider major lossage.  And if one added the ability
to provide optional documentation strings, you are pretty much back to
the same complexity-level as the separate DEFVARs (with the exception
of a few[1] keystrokes saved).  And if it boils down to only this
difference, I'd rather write a small Emacs function/macro to insert
the DEFVARs, than invent a new macro.

To take a different perspective, you seem to be in a situation where
you need to DEFVAR lots of variables, or else you probably wouldn't be
bothering with all of this.  If this is the case, then I'd wonder why
you have so many global specials, and if it might not be better to
devise a whole new mechanism to define/manage those specials,
i.e. your needs might differ markedly from the needs that made DEFVAR
arise, and hence some of the assumptions underlying the design of
DEFVAR might be invalid in your special case, and hence a new design
might be more appropriate.

Regs, Pierre.

Footnotes: 
[1]  More precisely: (- (* n 6) 11) keystrokes saved for n variables.

-- 
Pierre R. Mai <····@acm.org>                    http://www.pmsf.de/pmai/
 The most likely way for the world to be destroyed, most experts agree,
 is by accident. That's where we come in; we're computer professionals.
 We cause accidents.                           -- Nathaniel Borenstein
From: Thomas A. Russ
Subject: Re: Simple Macrology
Date: 
Message-ID: <ymipuitxuxu.fsf@sevak.isi.edu>
"Pierre R. Mai" <····@acm.org> writes:
> To take a different perspective, you seem to be in a situation where
> you need to DEFVAR lots of variables, or else you probably wouldn't be
> bothering with all of this.  If this is the case, then I'd wonder why
> you have so many global specials, and if it might not be better to
> devise a whole new mechanism to define/manage those specials

To expand on this a little bit, you might want to consider aggregating
some of the global state into more complicated data structures such as
defstructs and using them to hold the individual values.

Of course, if you only rebind some of the variables at a time this could
be less convenient...

-- 
Thomas A. Russ,  USC/Information Sciences Institute          ···@isi.edu