> On 19 Jul 2018, at 21:17, Andy Fingerhut <andy.finger...@gmail.com> wrote:
> 
> 
> If you wish for the Clojure core team to provide that style of documentation 
> for you, I expect your wish will not be fulfilled.  It is not technically 
> difficult to replace all Clojure doc strings with more verbose variants.  It 
> _is_ a lot of work to write documentation like that and maintain it over 
> time.  For example, here is a whole bunch of stuff I wrote on the behavior of 
> clojure.core/= and clojure.core/hash.  It took way more hours than I care to 
> admit: 
> https://github.com/jafingerhut/thalia/blob/master/doc/other-topics/equality.md
> 
> I believe someone wrote a book aiming to be a reference to all Clojure 
> functions, but don't recall the name or author at the moment, nor have I read 
> it.

Apologies for not resisting the plug: 
https://www.manning.com/books/clojure-standard-library

It should be completed very soon. Also sympathetic with the complexities of 
equality: I still can't believe how much there is to say.

Cheers
Renzo

> 
> Andy
> 
>  
> 
> 
> On Thu, Jul 19, 2018 at 11:04 AM Benoît Fleury <m...@benfle.com> wrote:
> I agree with Alex. It is important to understand the rationale behind the
> behavior of conj. conj is for adding an element to a collection. It doesn't
> say anything about ordering. It has been chosen as an operation, as
> opposed to append/prepend, because it can be implemented with the
> same time complexity for a lot of data structures.
> 
> To convince myself that time complexity mattered in programming, I take
> the example of a stack. If you give me an implementation of a stack that
> push and pop items in linear time, I will write very inefficient programs 
> very quickly. To the point of not working at all. So it makes sense to me 
> that space/time complexity should be part of the signature of an operation.
> 
> Now, I think the problem here comes from the fact that we have a tendency
> to infer the semantic of an operation from its behavior on certain types. We
> see that (conj [1 2] 3) returns [1 2 3] so we conclude that conj is for adding
> an item at the end of a collection. And then we get surprised when the
> behavior is "different" for other types. As Clojure programmers, it is 
> something
> we need to be careful about and make sure we understand the actual
> semantic of the operations.
> 
> However, I think it is easier said than done. I would be ready to bet that a
> lot of Clojure programs rely on the fact that conj *appends* to a vector or
> *prepends* to a list. I agree that it is problematic. First, it makes the
> understanding of the code harder because you need to remember the behavior
> of conj on each type. And it prevents the implementation of conj to change
> because so many programs rely on implementation details. But to all expert
> Clojure programmers here, can you honestly think about what mental model you
> use when using conj on vectors and lists? Are you really thinking: I'm adding
> this element to this collection. I don't really care where it ends up :) ?
> 
> So my questions are:
> 
> 1. Am I wrong in thinking that most Clojure programmers use append/prepend
> as mental models for the different implementations of conj?
> 
> 2. Am I wrong in thinking that they shouldn't?
> 
> 3. And if I'm not wrong, how could we make it easier for programmers to make
> sure they code against the semantic of an operation and not its implementation
> details? Is there methods, tools or tests that could help us with that?
> 
> 
> On Thu, Jul 19, 2018 at 3:20 AM Didier <didi...@gmail.com> wrote:
> Hey Alan,
> 
> Nice job on Tupelo by the way. I do find it a bit bloated though, and that's 
> why I never use it. Any reason why all the different namespace are still 
> mixed together? Seem like they could each be an independent lib, like how the 
> datomic namespace was split out.
> 
> On Wednesday, 18 July 2018 13:16:15 UTC-7, Alan Thompson wrote:
> There is also a function `glue` for combining like collections:
> 
> ---------------------------------------------------------------------------------
> Gluing Together Like Collections
> 
> The concat function can sometimes have rather surprising results:
> 
> (concat {:a 1} {:b 2} {:c 3
> } )
> 
> ;=>   ( [:a 1] [:b 2] [:c 3] )
> In this example, the user probably meant to merge the 3 maps into one. 
> Instead, the three maps were mysteriously converted into length-2 vectors, 
> which were then nested inside another sequence.
> 
> The conj function can also surprise the user:
> 
> (conj [1 2] [3 4
> ] )
> 
> ;=>   [1 2  [3 4] ]
> Here the user probably wanted to get [1 2 3 4] back, but instead got a nested 
> vector by mistake.
> 
> Instead of having to wonder if the items to be combined will be merged, 
> nested, or converted into another data type, we provide the glue function to 
> always combine like collections together into a result collection of the same 
> type:
> 
> ; Glue together like collections:
> 
> (
> is (= (glue [ 1 2] '(3 4) [ 5 6] )       [ 1 2 3 4 5 6 ]  ))   ; all 
> sequential (vectors & lists)
> 
> (
> is (= (glue {:a 1} {:b 2} {:c 3} )       {:a 1 :c 3 :b 2} ))   ; all maps
> 
> (
> is (= (glue #{1 2} #{3 4} #{6 5} )      #{ 1 2 6 5 3 4 }  ))   ; all sets
> 
> (
> is (= (glue "I" " like " \a " nap!" )   "I like a nap!"   ))   ; all text 
> (strings & chars)
> 
> 
> 
> ; If you want to convert to a sorted set or map, just put an empty one first:
> 
> (
> is (= (glue (sorted-map) {:a 1} {:b 2} {:c 3})   {:a 1 :b 2 :c 3
> } ))
> (
> is (= (glue (sorted-set) #{1 2} #{3 4} #{6 5})  #{ 1 2 3 4 5 6  } ))
> An Exception will be thrown if the collections to be 'glued' are not all of 
> the same type. The allowable input types are:
> 
>       • all sequential: any mix of lists & vectors (vector result)
> 
>       • all maps (sorted or not)
> 
>       • all sets (sorted or not)
> 
>       • all text: any mix of strings & characters (string result)
> 
> 
> 
> On Wed, Jul 18, 2018 at 1:13 PM, Alan Thompson <cloo...@gmail.com> wrote:
> As someone mentioned, the functions `prepend` and `append` exist in the 
> Tupelo library to prevent this kind of confusion:
> 
> from the README:
> ------------------------------------------------------------------------------------
> Adding Values to the Beginning or End of a Sequence
> 
> Clojure has the cons, conj, and concat functions, but it is not obvious how 
> they should be used to add a new value to the beginning of a vector or list:
> 
> ; Add to the end
> 
> > (
> concat [1 2] 3)    ;=> IllegalArgumentException
> 
> > (
> cons   [1 2] 3)    ;=> IllegalArgumentException
> 
> > (
> conj   [1 2] 3)    ;=> [1 2 3]
> 
> > (
> conj   [1 2] 3 4)  ;=> [1 2 3 4]
> 
> > (
> conj  '(1 2) 3)    ;=> (3 1 2)       ; oops
> 
> > (
> conj  '(1 2) 3 4)  ;=> (4 3 1 2)     ; oops
> 
> 
> 
> ; Add to the beginning
> 
> > (
> conj     1  [2 3] ) ;=> ClassCastException
> 
> > (
> concat   1  [2 3] ) ;=> IllegalArgumentException
> 
> > (
> cons     1  [2 3] ) ;=> (1 2 3)
> 
> > (
> cons   1 2  [3 4] ) ;=> ArityException
> 
> > (
> cons     1 '(2 3) ) ;=> (1 2 3)
> 
> > (
> cons   1 2 '(3 4) ) ;=> ArityException
> Do you know what conj does when you pass it nil instead of a sequence? It 
> silently replaces it with an empty list: (conj nil 5) ⇒ (5) This can cause 
> you to accumulate items in reverse order if you aren’t aware of the default 
> behavior:
> 
> (-> nil
> 
>   (
> conj 1
> )
>   (
> conj 2
> )
>   (
> conj 3
> ))
> 
> ;=> (3 2 1)
> These failures are irritating and unproductive, and the error messages don’t 
> make it obvious what went wrong. Instead, use the simple prepend and append 
> functions to add new elements to the beginning or end of a sequence, 
> respectively:
> 
> (append [1 2] 3  )   ;=> [1 2 3  ]
> 
> (
> append [1 2] 3 4)   ;=> [1 2 3 4]
> 
> 
> (
> prepend   3 [2 1])  ;=> [  3 2 1]
> 
> (
> prepend 4 3 [2 1])  ;=> [4 3 2 1]
> Both <code 
> style="box-sizing:border-box;font-family:SFMono-Regular,Consolas,"Liberation
> 
> 
> -- 
> 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.
> 
> -- 
> 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.
> 
> -- 
> 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.

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