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))
开发者_JS百科
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?
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)
A little experimentation with the REPL lead me to this solution:
user=> (def suits [:clubs :diamonds :hearts :spades])
#'user/suits
user=> suits
[:clubs :diamonds :hearts :spades]
user=> (reduce concat (replicate 2 suits))
(:clubs :diamonds :hearts :spades :clubs :diamonds :hearts :spades)
(untested!)
(apply concat (repeat 2 suits))
will hopefully do the trick.
concat
will of course concatenate 2 lists; apply
can be used to smuggle a given function into the head position of an existing list for evaluation.
(take (* 2 (count suits)) (cycle suits))
精彩评论