Thanks for your responses. I'm glad to see that I'm not entirely on
the wrong track here.

On Mon, May 11, 2009 at 6:39 PM, Sean Devlin <[email protected]> wrote:
>
> Okay, good point about approach #2.  As I mentioned earlier, I'd use
> approach #3 first.  Here's how I'd write your macro as a function
>
> (defn process-feeds
>  [feeds body]
>  (body feeds))
>
> And I'd call it like this
>
> (process-feeds (get-feeds-s-exp ...) (fn [feeds] body))
>
> The first thing I'd like to mention is that this is VERY similar to
> your with-feeds macro.  I think your general approach is sound.
> Following is simply my thoughts and opinions on avoiding a macro in
> this case.
>
> I like this approach better because it segregates the calling from the
> processing, and it lets you test each routine independently.  Also,
> forcing the second argument to be a function encourages defining the
> function, which in turn encourages testing.

I decided to go with the macro, because it makes the default scenario
very convenient. The tests I write apply to the functions where the
feeds operation is performed (and I have tests for the macro). When
the need arises to have an explicitly defined and tested function, I
can still use call-with-feeds without the macro.

> Now, I've made an assumption, and that is the process-feeds has no
> side effects.  If you are doing something that is sequential, not
> functional (like opening/closing a resource), then a macro makes
> sense.
>
> My thoughts in a pithy sound-byte:
>
> If you are abstracting away a function, try to use a function.
> If you are abstracting away a sequence, it's the right time to use a
> macro.
>
> There are other classes of problems in the function-vs-macro debate,
> and I we can save those for another day :)
>
> On May 11, 12:04 pm, Victor Rodriguez <[email protected]> wrote:
>> On Mon, May 11, 2009 at 11:32 AM, Sean Devlin <[email protected]> 
>> wrote:
>>
>> > Here are my thoughts on the three approaches:
>>
>> > Approach #1:  This seems the most straightforward.  I'd write a
>> > function that takes a map of conditions, and returns a list of
>> > tuples.  You can then do what you want with the list of tuples.
>>
>> > Approach #2:  Remember the first rule of macro club:  Don't write
>> > macros if a function will do.  From what you've described, this
>> > application wraps a simple SELECT * FROM... , and a macro is overkill.
>>
>> Yes, you should not write a macro when a function will do, but I think
>> you might be misinterpreting the "spirit" of the rule.
>>
>> Also, the "bottom-up" aspect of programming in Lisp should be kept in
>> mind.  In other words, you want to "write a language for solving your
>> problem", and you should definitively use macros for that.
>>
>> So, if a "with-feeds" macro makes sense for the application, do write
>> it!  Just make sure the macro is simply syntax sugar for your
>> functions.  Following a pattern common in Scheme (at least), the
>> implementation would run along the lines of:
>>
>> (defn call-with-feeds
>>   [f]
>>   "Call a function with the feeds as an argument"
>>   ...)
>>
>> (defmacro with-feeds
>>   [feeds & body]
>>   `(call-with-feeds (fn [~feeds] ~...@body)))
>>
>> Kind regards,
>>
>> Victor Rodriguez.
>>
>> > Approach #3:  This is a good approach once you hit the limits of the
>> > first approach, and before you move on to the second approach.
>>
>> > I've written SQL apps in Clojure too.  And I've used approaches 1 and
>> > 3.  I only use approach 2 when I really have to, and I try to have the
>> > macro do as little as possible.
>>
>> > In summary, try approaches:
>>
>> > 1 -> 3 -> 2
>>
>> > I'll try to throw some code on github this evening so you can see an
>> > example of what I do, and you can decide if it's a good fit for your
>> > application.
>>
>> > Sean
>>
>> > On May 11, 4:05 am, Janico Greifenberg <[email protected]> wrote:
>> >> Hi,
>>
>> >> I'm writing an RSS-reader using compojure and clojure.contrib.sql. As
>> >> this is my first project in a functional language, I'm not sure about
>> >> how to design the application. The concrete question I'm having right
>> >> now, is how to encapsulate database queries in functions. For my
>> >> RSS-reader, a basic operations is to display lists of feeds that I
>> >> retrieve with the following code:
>>
>> >> (sql/with-connection db
>> >>   (sql/with-query-results
>> >>     feeds
>> >>     ["select id, title from feeds order by title"]
>>
>> >> As this happens at a few places in the code, I would like to
>> >> encapsulate it somehow. I see several approaches to this, but I'm
>> >> uncertain which of them is the most idiomatic way to do this in
>> >> Clojure.
>>
>> >> (1) The straightforward approach seems to be a function that returns
>> >> the feeds. However, I would have to call (doall feeds) to get the data
>> >> out of the internals of contrib.sql/JDBC and into my application. So I
>> >> guess this would not be the most efficient way.
>>
>> >> (2) Another idea is to create a function or macro with-feeds that
>> >> wraps the query and creates a binding to be used inside the body.
>>
>> >> (3) Or I could have a function that takes another function as a
>> >> parameter which gets called inside with-query-results and gets feeds
>> >> as parameter.
>>
>> >> Which of these variants -- or another one that I did not think of --
>> >> would you recommend?
>>
>> >> Janico
> >
>

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to 
[email protected]
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to