Or use a fixed-size vector as a ring, with start and end "pointers",
and a couple functions to abstract over the handling thereof. But
unless you really really care about performance, this is likely to be
overkill, and Ken's suggestion to just use a vector or a seq and
accept the O(n) behavior.

On Feb 3, 10:22 am, Ken Wesson <kwess...@gmail.com> wrote:
> On Thu, Feb 3, 2011 at 3:11 AM, Petr Gladkikh <petrg...@gmail.com> wrote:
> > On Thu, Feb 3, 2011 at 1:31 PM, Meikel Brandmeyer <m...@kotka.de> wrote:
> >> Hi,
>
> >> On 3 Feb., 08:04, Petr Gladkikh <petrg...@gmail.com> wrote:
>
> >>> Should not it be empty colection instead?
> >>> It seems odd to me since it is inconsistent and forces to consider one
> >>> more case (nil or collection).
>
> >> It is consistent. There is a difference between () and nil. () is the
> >> empty list. However there is no "empty sequence." Either there is
> >> something or there is nothing. Why would you have to check for nil?
> >> You can pass nil to any of the sequence library functions without fear
> >> of harm. When you write such a function yourself, there is usually a
> >> single check in the beginning when realising the sequence. Something
> >> like (when-let [s (seq coll)] ...).
>
> >> I never encountered any problems with this. Do you have a concrete
> >> example where this causes trouble for you?
>
> > I have a vector that holds some history. I conj new items to it and to
> > save space I'd like to retain not more than n last items.
> > To do that I used (take-last n history). So: [] -> (take-last n []) ->
> > nil -> (conj nil newItem) -> '(newItem)
>
> > But list conj's at the beginning not at end of sequence as I would
> > like to. Of course I could use () from the beginning (with account for
> > reverse order).
> > But with [] I should do little more.
>
> Depending on your "little more", you might want to wrap the queue
> implementation I posted a while ago with something like
>
> (defn push-max [q item max]
>   (let [q (conj q item)]
>     (if (> (count q) max)
>       (pop q)
>       q)))
>
> This will be efficient (in particular, the count function should be
> efficient on my queue) without any full traversals (unlike take-last).
> The least recent item can be viewed with peek. If you want to view the
> most recent item you could use my deque implementation (amortized O(1)
> operations at both ends, and O(1) count) which lets you peek both
> ends.
>
> But neither will satisfy you if you want to random access in the
> middle. If you want to partially traverse from only one end (either
> youngest or oldest items) my deque will do: it can be partially
> traversed from the left end efficiently with seq, so you'd add new
> items at that end if you wanted to partially traverse youngest items,
> and at the other if you wanted to partially traverse oldest items.
>
> Of course, if the max length is short it won't matter much; you can
> just use a vector and (vec (take-last ...)) and it won't be very
> inefficient, nor would using reverse on a queue or deque to traverse
> from the other end and last to peek the "difficult" end of a queue.

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