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.

Reply via email to