Thanks Meikel, if I may reply to your points and your function as it's slightly 
different from what I wanted:

> * It's a function, not macro.

I need it to be a macro because it's more usable for my purposes that way. The 
newLISP function is being used to generate templates php-style:

        <table>
                <tr><td>Name</td><td>Email</td></tr>
                <% (for-query-with-db db "SELECT * FROM people" %>
                <tr><td><%=NAME%></td><td><%=EMAIL%></td></tr>
                <% ) %>
        </table>

As you can see it's much more convenient as a macro.

> * You don't have to fiddle with magic names. The user can choose himself.

These aren't magic names, they're just like you keywords, except they're 
symbols, and they're not magic because they're defined by the columns of the 
table. Or, I may be misunderstanding your use of the term 'magic'.

> * The query can be also stored in some local and doesn't have to be a literal 
> string.


There's nothing forcing you to use it as a literal, the newLISP version can be 
used with a let statement just as your example did.

After discussing this problem with the folks on #clojure they helped me refine 
my attempt at writing a clojure version of it:

        (def col-names ["name" "age"])
        (def col-vals [["Sally" 5] ["Sue" 6]])
        (defmacro foo [& body]
                (let [col-syms (for [n col-names] (-> n .toUpperCase symbol))
                      exprs    (for [v col-vals] `(let [~@(interleave col-syms 
v)] ~...@body))]
                        `(do ~...@exprs)
                )
        )
        (foo (prn NAME))

As I'm not yet experienced in Clojure enough to use an actual db, I used the 
vars 'col-names' and 'col-vals' as placeholders.

That seems to work great, what I'm fuzzy on is the whole macroexpansion thing 
and when it occurs. As in this example everything is known at compile-time, is 
this "macro-expanded" at compile time? Can this sort of macro work just fine 
when the column information is only known at runtime? Are there any performance 
considerations?

Thanks!

- Greg

On Feb 4, 2010, at 1:42 AM, Meikel Brandmeyer wrote:

> Hi,
> 
> On Feb 4, 4:42 am, Greg <g...@kinostudios.com> wrote:
> 
>> The magic happens here:
>> 
>>                 (while (list? (setf values (sql:next-row)))
>>                         (eval (expand (cons 'begin $args) (unify keys 
>> values)))
>>                 )
>> 
>> $args is equivalent to the 'body' in [& body] in clojure, and the expand 
>> function will replace all of the symbols in 'keys' (in $args) with the 
>> 'values'.
>> 
>> So (println NAME) becomes (println "José Lopez"), and it gets eval'd each 
>> time in the loop to the different values in the table.
>> 
>> How would you implement this behavior in Clojure?
> 
> (defn do-query
>  [db query thunk]
>  (doseq [entry (-> db (.prepareStatement query) .executeQuery
> resultset-seq)]
>    (thunk entry)))
> 
> (let [q "SELECT name FROM people"]
>  (do-query db q #(println (:name %))))
> 
> Several differences to the newLisp code:
> 
> * It's a function, not macro.
> * You don't have to fiddle with magic names. The user can choose
> himself.
> * The query can be also stored in some local and doesn't have to be a
> literal
>  string.
> 
> I am really happy that I'm a smug Clojure weenie, who doesn't have to
> write
> code which walks other code to replace things in place and to eval
> it...
> 
> Sincerely
> Meikel
> 
> -- 
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clojure@googlegroups.com
> Note that posts from new members are moderated - please be patient with your 
> first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Reply via email to