From: Jonathon McKitrick
Subject: Macro help needed
Date: 
Message-ID: <1155404858.063567.24090@i42g2000cwa.googlegroups.com>
Perhaps I'm totally going about this the wrong way.

I have a database query from clsql made with (multiple-value-list), so
it combines the matching record (there will be only one) with the
field-names:

( ( (val1 val2 val3) ) ( key1 key2 key3 ) )

What I want to do is write a macro that will accept the query and a
column name, and then execute the body with the corresponding value
bound to some variable.  Not sure what variable name to choose, but
here's the feeble attempt at macro code:

(defmacro with-query-column (query column &body body)
  "With a query of 1 result, get the value for a column."
  (let ((val (gensym)))
    `(destructuring-bind ((vals) columns) ,query
       (let ((,val (elt vals (position ,column columns :test
#'equal))))
	 ,@body))))

I'm sure I'm doing something wrong here.  It just occurred to me I
might be better off building a hash table.  What do you guys think?

From: Barry Margolin
Subject: Re: Macro help needed
Date: 
Message-ID: <barmar-08A51C.14282612082006@comcast.dca.giganews.com>
In article <·······················@i42g2000cwa.googlegroups.com>,
 "Jonathon McKitrick" <···········@bigfoot.com> wrote:

> Perhaps I'm totally going about this the wrong way.
> 
> I have a database query from clsql made with (multiple-value-list), so
> it combines the matching record (there will be only one) with the
> field-names:
> 
> ( ( (val1 val2 val3) ) ( key1 key2 key3 ) )
> 
> What I want to do is write a macro that will accept the query and a
> column name, and then execute the body with the corresponding value
> bound to some variable.  Not sure what variable name to choose, but
> here's the feeble attempt at macro code:

Let the user supply the variable.

> 
> (defmacro with-query-column (query column &body body)
>   "With a query of 1 result, get the value for a column."
>   (let ((val (gensym)))
>     `(destructuring-bind ((vals) columns) ,query
>        (let ((,val (elt vals (position ,column columns :test
> #'equal))))
> 	 ,@body))))

You're using gensym for the wrong thing.  You should be using it for the 
temporary variables used internally within the expansion (vals and 
columns), to avoid shadowing real variables, not for the variable that 
you actually want the user to access within the body.

(defmacro with-query-column ((var column query) &body body)
  (let ((vals (gensym))
        (cols (gensym)))
    `(destructuring-bind ((,vals) ,cols) ,query
       (let ((,var (nth (position ,column ,cols :test #'equal) ,vals)))
         ,@body))))

> I'm sure I'm doing something wrong here.  It just occurred to me I
> might be better off building a hash table.  What do you guys think?

Unless these lists of values and keys are large, that's probably 
overkill.

-- 
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***
From: Jonathon McKitrick
Subject: Re: Macro help needed
Date: 
Message-ID: <1155413390.509917.254780@h48g2000cwc.googlegroups.com>
Barry Margolin wrote:
> You're using gensym for the wrong thing.  You should be using it for the
> temporary variables used internally within the expansion (vals and
> columns), to avoid shadowing real variables, not for the variable that
> you actually want the user to access within the body.
>
> (defmacro with-query-column ((var column query) &body body)
>   (let ((vals (gensym))
>         (cols (gensym)))
>     `(destructuring-bind ((,vals) ,cols) ,query
>        (let ((,var (nth (position ,column ,cols :test #'equal) ,vals)))
>          ,@body))))

Got it, thanks!

Is this violating the concept of using macros to define the problem,
not the solution?
From: Jonathon McKitrick
Subject: Re: Macro help needed
Date: 
Message-ID: <1155415775.499506.115000@74g2000cwt.googlegroups.com>
Barry Margolin wrote:
> You're using gensym for the wrong thing.  You should be using it for the
> temporary variables used internally within the expansion (vals and
> columns), to avoid shadowing real variables, not for the variable that
> you actually want the user to access within the body.
>
> (defmacro with-query-column ((var column query) &body body)
>   (let ((vals (gensym))
>         (cols (gensym)))
>     `(destructuring-bind ((,vals) ,cols) ,query
>        (let ((,var (nth (position ,column ,cols :test #'equal) ,vals)))
>          ,@body))))

Got it, thanks!

Is this violating the concept of using macros to define the problem,
not the solution?
From: Barry Margolin
Subject: Re: Macro help needed
Date: 
Message-ID: <barmar-C4549D.17485012082006@comcast.dca.giganews.com>
In article <························@74g2000cwt.googlegroups.com>,
 "Jonathon McKitrick" <···········@bigfoot.com> wrote:

> Barry Margolin wrote:
> > You're using gensym for the wrong thing.  You should be using it for the
> > temporary variables used internally within the expansion (vals and
> > columns), to avoid shadowing real variables, not for the variable that
> > you actually want the user to access within the body.
> >
> > (defmacro with-query-column ((var column query) &body body)
> >   (let ((vals (gensym))
> >         (cols (gensym)))
> >     `(destructuring-bind ((,vals) ,cols) ,query
> >        (let ((,var (nth (position ,column ,cols :test #'equal) ,vals)))
> >          ,@body))))
> 
> Got it, thanks!
> 
> Is this violating the concept of using macros to define the problem,
> not the solution?

Perhaps.  It strikes me that this could just as easily be done with a 
function:

(defun get-query-column (column query)
  (destructuring-bind ((vals) cols) query
    (nth (position column cols :test #'equal) vals)))

Then you can easily do:

(let ((thing (get-query-column 'col2 query)))
  ...)

WITH-XXX macros are usually necessary when you need to do something more 
than just bind a variable, e.g. clean up things after the body is done.  
For instance, WITH-OPEN-FILE has to close the file before finishing.

P.S. Why the double post?  What is it about Google that causes this to 
happen so often?

-- 
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***
From: Jonathon McKitrick
Subject: Re: Macro help needed
Date: 
Message-ID: <1155430427.800386.111280@m73g2000cwd.googlegroups.com>
Barry Margolin wrote:
> P.S. Why the double post?  What is it about Google that causes this to
> happen so often?

Not sure.  I hit the 'submit' button, and the progress bar sometimes
hangs 1/4 way across.  Sometimes I just stop the browser and re-submit,
sometimes I hit 'preview' then re-submit from there.  Other times I
force myself to be patient and let it do its thing, and I get a
time-out page and have to backup and resubmit anyway.
From: bradb
Subject: Re: Macro help needed
Date: 
Message-ID: <1155482528.284628.305550@m79g2000cwm.googlegroups.com>
Jonathon McKitrick wrote:
> Perhaps I'm totally going about this the wrong way.
>
> I have a database query from clsql made with (multiple-value-list), so
> it combines the matching record (there will be only one) with the
> field-names:
>
> ( ( (val1 val2 val3) ) ( key1 key2 key3 ) )
>
> What I want to do is write a macro that will accept the query and a
> column name, and then execute the body with the corresponding value
> bound to some variable.  Not sure what variable name to choose, but
> here's the feeble attempt at macro code:
>
> (defmacro with-query-column (query column &body body)
>   "With a query of 1 result, get the value for a column."
>   (let ((val (gensym)))
>     `(destructuring-bind ((vals) columns) ,query
>        (let ((,val (elt vals (position ,column columns :test
> #'equal))))
> 	 ,@body))))
>
> I'm sure I'm doing something wrong here.  It just occurred to me I
> might be better off building a hash table.  What do you guys think?
Jon, I tried to reply to your email but your bigfoot account bounced
me.

Brad
From: jmckitrick
Subject: Re: Macro help needed
Date: 
Message-ID: <1155485343.284411.212460@m79g2000cwm.googlegroups.com>
bradb wrote:
> Jon, I tried to reply to your email but your bigfoot account bounced
> me.

I've finally been forced to update my address.  When the spam-bots find
me, I'll blame you.  ;-P

Please try again, at the new one jmckitrick ( at ) yahoooooooo! ( dot )
KAHM.

Think that will throw them off?
From: bradb
Subject: Re: Macro help needed
Date: 
Message-ID: <1155499832.027395.77790@74g2000cwt.googlegroups.com>
jmckitrick wrote:
> bradb wrote:
> > Jon, I tried to reply to your email but your bigfoot account bounced
> > me.
>
> I've finally been forced to update my address.  When the spam-bots find
> me, I'll blame you.  ;-P
>
> Please try again, at the new one jmckitrick ( at ) yahoooooooo! ( dot )
> KAHM.
>
> Think that will throw them off?

Hmm, that didn't work :)  Just email me again from your new account.

Cheers
Brad