2010-04-23 8 views
6

Je suis un débutant Clojure. J'essaie d'obtenir deux copies d'un vecteur de combinaisons de cartes. La façon non DRY que je peux trouver estRépéter des vecteurs dans Clojure

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

Il doit y avoir une façon plus fonctionnelle (même si cela prend plus de caractères :-)). Que faire si je veux N fois? Aucune suggestion?

Toutes les choses que j'essaie, comme

(replicate 2 suits) 

résultats dans deux vecteurs séparés:

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

Comment puis-je "Aplatir" la structure?

+1

Il n'y a rien non fonctionnel sur l'utilisation de la valeur d'un Var à l'intérieur du 'def' création de formulaire un autre Var. En fait, c'est la chose naturelle à faire si le second Var dépend du premier. Bien sûr, si vous voulez une méthode générale de concaténer n copies d'un seq, où n peut ou peut ne pas être connu à l'avance, alors vous avez besoin d'une meilleure solution (que l'on trouve dans les réponses ici). –

+1

En fait, c'est ce que je voulais dire (N copies). Je suis d'accord que ma fonction deux fois est "fonctionnelle" - ce n'est tout simplement pas pratique si je veux 100 exemplaires :-). – Ralph

Répondre

7

concat vous donne un seq paresseux. Si vous voulez finir avec un (non paresseux) vecteur à la place:

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] 

Selon que vous accédez à ce par index beaucoup ou itère dessus, soit un vecteur ou un seq pourrait être plus approprié.

Il y a toujours cycle aussi, si vous voulez un flux sans fin (paresseux) d'éléments répétés:

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

Je suis également venu avec (prendre 8 (combinaisons de cycle)). Semble travailler, mais je devais comprendre la partie moi-même « 8 », sans l'aide d'un ordinateur :-). – Ralph

2

(non testé!)

(apply concat (repeat 2 suits)) 

nous l'espérons faire l'affaire.

concat concaténerons bien sûr 2 listes; apply peut être utilisé pour faire passer une fonction donnée en tête d'une liste existante pour évaluation.

+2

Correction du nom de la fonction ('assoc' ->' apply'). –

+0

Oh, comme c'est stupide de ma part. J'utilise 'apply' tout le temps, vous penseriez que je connais son nom maintenant ... Merci pour la correction! –

+0

'(doc répliquées)' partir de Clojure 1.7 'dit Obsolète: Utilisez 'répétition' instead.' –

2

Un peu d'expérimentation avec le REPL me conduisent à cette 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) 
1
(take (* 2 (count suits)) (cycle suits))