On Feb 28, 7:36 pm, reynard <atsan...@gmail.com> wrote:
> Perhaps my choice of function names (abstract and concrete) for my
> original post is not very appropriate.  I did not mean to apply the OO
> concept of abstract class, abstract methods, etc.  Since it seems that
> my original post did not convey my query clearly, I would try to
> depict it with some "concrete" :) examples in the following.
>
> Suppose I want to filter a list '(1 2 3 4 5 6 7 8 9) for all the
> numbers which is less than 5, but I do not want to use the clojure
> filter function.  I decide to roll out my own function using recursion
> and con'sing as follows.
>
> (defn smaller-than [a-list n]
>   (cond (empty? a-list) '()
>         'else (if (< (first a-list) n)
>                 (cons (first a-list)
>                       (smaller-than (rest a-list) n))
>                 (smaller-than (rest a-list) n))))
>
> Later, I want to filter for all numbers which is more than 7 from the
> list.  I do not want to copy and paste and modify smaller-than.  To
> maintain a single place of control, I introduce a function call
> filter1.  I do a little bit abstraction and define some functions as
> follows.
>
> (defn filter1 [comparator a-list n]
>   (cond (empty? a-list) '()
>         'else (if (comparator (first a-list) n)
>                   (cons (first a-list)
>                       (filter1 comparator (rest a-list) n))
>                   (filter1 comparator (rest a-list) n))))
>
> (defn smaller-than [a-list n]
>   (filter1 < a-list n))
>
> (defn more-than [a-list n]
>   (filter1 > a-list n))
>
> Or I can define filter1 as follows:
>
> (defn filter1 [comparator]
>   (fn anonymous [a-list n]
>     (cond (empty? a-list) '()
>           'else (if (comparator (first a-list) n)
>                     (cons (first a-list)
>                         (anonymous (rest a-list) n))
>                     (anonymous (rest a-list) n)))))
>
> and use it the following way
>
> (def smaller-than (filter1 <))
> (smaller-than '(1 2 3 4 5) 3)
>
> Or even ((filter1 <) '(1 2 3 4 5) 3)
>
> I may define filter1 as is, what is now being done, accepting a
> predicate as the parameter. There are just many choices on how to do
> abstraction.
>
> So back to my query on my original post.  Given that there are many
> choices, how do I choose which way to do and why?  Is there really a
> "better" way?  Or just by convention?  By preference?  Or is the
> answer "it depends"?  But depends on what?  I would be glad to hear
> your opinion.  Thanks.

As I said in my previous post, both approaches are valid. Which one
you pick really depends on your intended usage.

Though I think def'ing functions returned by other functions is not
very common in Clojure, it's certainly not bad style. However,
functions are no different from other data, so rather than defining a
global name for them, more often you just pass them into other
functions or store them in a data structure or whatever. If it really
needs a name, a let-bound local one is often enough.

>
> P.S. a side note on recursion:  I may change the above filter1
> function into tail call by introducing an accumulator parameter and
> modify the function a little bit.  Is it generally a good thing to do
> it?  I would like to hear some comments.  Thanks.

In Clojure the most idiomatic version of filter is the lazy one. It is
recursive like in your implementation, but rather than actually
executing the recursion immediately, you wrap the cons call in lazy-
seq and return a thunk.

-- 
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