There is also a function `glue`
<https://github.com/cloojure/tupelo#gluing-together-like-collections> 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 <clooj...@gmail.com> wrote:

> As someone mentioned, the functions `prepend` and `append` exist in the
> Tupelo library
> <https://github.com/cloojure/tupelo#adding-values-to-the-beginning-or-end-of-a-sequence>
> 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 prepend and append always return a vector result.
> <https://github.com/cloojure/tupelo#combining-scalars-and-vectors>
>
>
>
>
> On Wed, Jul 18, 2018 at 8:17 AM, Christian Seberino <cseber...@gmail.com>
> wrote:
>
>> Actually I was just kicked out of paradise.  concat always returns a list
>> and does NOT return a vector for this (concat [1 2] [3 4]) sadly.
>>
>> cs
>>
>> _______________________________________
>>
>> Christian Seberino, Ph.D.
>> Phone: (936) 235-1139
>> Email: cseber...@gmail.com
>> _______________________________________
>>
>>
>>
>> On Wed, Jul 18, 2018 at 2:16 AM, Didier <didi...@gmail.com> wrote:
>>
>>> It's never a good idea to use the wrong data structure for the job.
>>>
>>> And thus Clojure takes the stance that it won't make bad ideas easy for
>>> you to use. Yet, it will never prevent you from doing anything.
>>>
>>> If you want to do something bad, you'll need to get your own hands dirty.
>>>
>>> That's why slow data structure access functions don't exist as standard.
>>> That's why data transforms are lazy by default. And why the non lazy
>>> variant (transducers) do loop fusion for you. That's why mutability is ugly
>>> and requires you to wrap things in extra verbosity. That's why OOP isn't
>>> there, and forces you to use the host interop if you want it. That's why
>>> there's only recursive loops. Etc.
>>>
>>> The Clojure standard lib is opinionated. It's not trying to make
>>> everything easy and convenient. It's trying to make things simple to reason
>>> about, and promote Rich Hickeys opinion of what is a good idea, and what
>>> isn't.
>>>
>>> But, it can afford to be this way, because it made itself a Lisp,
>>> meaning it gave you all the power needed to disagree and make your own
>>> core, which follows your own opinions of good and bad.[1]
>>>
>>> Now, I recommend that everyone should have a core library of their own
>>> that they keep around for cases like this, where they disagree.
>>>
>>> And for beginners, I mean, what are you trying to teach them? What
>>> problem requires them to add items to the beginning and end of an ordered
>>> collection?
>>>
>>> Anyways, my advice is to teach them concat. It's even nicer then
>>> append/prepend. You just give it the arguments where you want them to go.
>>>
>>> (concat [1] [2 3])
>>>
>>> (concat [1 2] [3])
>>>
>>> And it works for any type of ordered collections, even arrays.
>>>
>>> Also, this blog I think does a great job at teaching all this to a
>>> beginner https://medium.com/@greg_63957/conj-cons-concat-oh-my-1398a2
>>> 981eab
>>>
>>>
>>>
>>> [1] Except for reader macros. Rich didn't want you to be able to change
>>> the whole program syntax in unconstrained ways. That's probably a good
>>> thing to at least keep the foundation universal accross code bases.
>>>
>>> --
>>> 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