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