2010-04-23 16 views
6

Sono un novizio Clojure. Sto cercando di ottenere due copie di un vettore di semi delle carte. Il DRY modo non che io possa venire in mente èRipetizione dei vettori in Clojure

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

Ci deve essere un modo più funzionale (anche se ci vuole più caratteri :-)). Cosa succede se voglio N volte? Eventuali suggerimenti?

Tutte le cose che cerco, come

(replicate 2 suits) 

risultati in due vettori separati:

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

Come faccio "appiattire" la struttura?

+1

Non c'è niente non funzionale sull'utilizzo del valore di un Var all'interno del 'def' modulo creazione un altro Var. In effetti, questa è la cosa naturale da fare se il secondo Var dipende dal primo. Naturalmente se si desidera un metodo generale di concatenazione di n copie di un seq, dove n potrebbe o non potrebbe essere conosciuto in anticipo, allora è necessaria una soluzione migliore (come si trova nelle risposte qui). –

+1

In realtà, questo è ciò che intendevo (N copie). Sono d'accordo sul fatto che la mia funzione due volte sia "funzionale" - non è pratica se voglio 100 copie :-). – Ralph

risposta

7

concat ti dà un ss pigro. Se si vuole finire con un vettore (non pigro) invece:

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] 

A seconda se si sta accedendo a questo indice da molto o iterando su di esso, sia un vettore o un ss potrebbe essere più appropriato.

C'è sempre cycle troppo, se si desidera un flusso infinito (pigro) di elementi ripetuti:

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

Mi sono anche inventato (prendere 8 (tute ciclo)). Sembra funzionare, ma ho dovuto capire da solo la parte "8", senza l'aiuto di un computer :-). – Ralph

2

(non testata!)

(apply concat (repeat 2 suits)) 

si spera fare il trucco.

concat concatenerà naturalmente 2 elenchi; apply può essere utilizzato per contraffare una determinata funzione nella posizione di testa di un elenco esistente per la valutazione.

+2

Risolto il nome della funzione ('assoc' ->' apply'). –

+0

Oh, che stupido da parte mia. Io uso 'apply' tutto il tempo, penseresti che ora conosco il suo nome ... Grazie per la correzione! –

+0

'(doc replicate)' come di Clojure 1.7 dice 'DEPRECATED: Usa 'repeat' invece. ' –

2

Un po 'di sperimentazione con il REPL mi portano a questa soluzione:

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