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