On Saturday, June 11, 2016 at 6:33:07 PM UTC-5, Fluid Dynamics wrote: > > On Saturday, June 11, 2016 at 6:55:03 PM UTC-4, Matching Socks wrote: >> >> pop isn't a sequence function. >> >> Check out the manual: >> http://clojure.github.io/clojure/clojure.core-api.html#clojure.core/pop >> <http://www.google.com/url?q=http%3A%2F%2Fclojure.github.io%2Fclojure%2Fclojure.core-api.html%23clojure.core%2Fpop&sa=D&sntz=1&usg=AFQjCNHBkrZNW1WA3Vf7Umyqq4KVNK6cEQ> >> >> You may use first/rest on any sequence, but pop does something more >> special(ized). >> > > Well, I see push/pop/peek as like conj, except not applicable to > non-ordered (set, map) or non-arbitrarily-ordered (sorted-set, sorted-map) > collections. Should work with all linear arbitrarily-ordered > order-preserving colls that have an efficient trio of add/examine/drop-one > at one end or the other. >
Clojure distinguishes between collection functions (which take and return a collection instance) and sequence functions (which take and return a seqable). Currently pop/peek are defined specifically for persistent collections (list, queue, and vector) as mentioned in the doc string. I can see how pop/peek could be considered as sequence ops too as they map basically to first/rest. I don't know that I've ever heard a justification for this, but my guess would be that they differ based on what you should expect based on efficiency. With a collection, you know the data already exists and peek can return it in constant time. Similarly, pop can efficiently return to you the remainder of the collection. Sequences however are potentially lazy and an open abstraction. While calling first seems like a fast operation, in a lazy sequence you might be calling a database to retrieve a row or hitting a file system to retrieve a file or a line. Similarly, calling rest may also require the first item to be realized if the elements are being read from a serialized source. One (common) approach when building a collection library is to build a very rich generic API. Ultimately you will have implementations that either fail to implement certain operations or back-fill them with inefficient implementations. Clojure instead chooses to define many "traits" or slices of functionality, set performance expectations for the ops in those traits, and implement them only where those expectations can be met. The former approach feels more "complete" as a user but only by lying about what its data structures can do. This ultimately means that when you see a call to a collection operation, you must either have no expectation about its performance or you must understand at a deeper level what implementation you are actually using and what it will do. Clojure's approach allows you to instead make assumptions about the performance of an operation and know that when the call doesn't work, that's probably why (and perhaps you need to revisit what data structures you are using). If it's not too cliche, this is a textbook choice of easy vs simple. You haven't actually said what problem you're trying to solve. If the problem is choosing a data structure to act as a stack, then I would recommend choosing one of the collections that implements the stack API. -- 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 unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.