Search code examples
clojuresequencesplaying-cards

Repeating vectors in Clojure


I am a Clojure newbie. I am trying to get two copies of a vector of card suits. The non-DRY way that I can come up with is

(def suits [:clubs :diamonds :hearts :spades])
(def two-times (concat suits suits))

There must be a more functional way (even if it takes more characters :-)). What if i want N times? Any suggestions?

All of the things I try, like

(replicate 2 suits)

results in two separate vectors:

([:clubs :diamonds :hearts :spades] [:clubs :diamonds :hearts :spades])

How do I "flatten" the structure?


Solution

  • concat gives you a lazy seq. If you want to end up with a (non-lazy) vector instead:

    user> (into suits suits)
    [:clubs :diamonds :hearts :spades :clubs :diamonds :hearts :spades]
    user> (reduce into (replicate 2 suits))
    [:clubs :diamonds :hearts :spades :clubs :diamonds :hearts :spades]
    

    Depending whether you're accessing this by index a lot or iterating over it, either a vector or a seq might be more appropriate.

    There's always cycle too, if you want an endless (lazy) stream of repeated elements:

    user> (take 9 (cycle suits))
    (:clubs :diamonds :hearts :spades :clubs :diamonds :hearts :spades :clubs)