Disons que j'ai un Lazeueq de Java.lang.Character comme
(\b \ \! \/ \b \ \% \1 \9 \/ \. \i \% \$ \i \space \^@)
Comment puis-je convertir cela en une chaîne? J'ai essayé l'évidence
(String. my-char-seq)
mais ça jette
Java.lang.IllegalArgumentException: No matching ctor found for class Java.lang.String (NO_SOURCE_FILE:0)
[Thrown class clojure.lang.Compiler$CompilerException]
Je pense que parce que le constructeur de string s'attend à une primitive Char [] au lieu d'un LAZYSEQ. Alors j'ai essayé quelque chose comme
(String. (into-array my-char-seq))
mais cela jette la même exception. Le problème est maintenant que dans le tablea renvoie a java.lang.character [] au lieu d'une primitive Char []. Ceci est frustrant, car je génère en fait ma séquence de caractère comme celle-ci
(map #(char (Integer. %)) seq-of-ascii-ints)
Fondamentalement, j'ai un SEQ d'INTS représentant ASCII caractères; 65 = A, etc. Vous pouvez voir que j'ai explicitement utiliser la fonction de coercition de type primitive (((char x).
Ce que cela signifie que ma fonction mon map renvoie une primitive char mais la fonction de clojure carte La fonction globalement renvoie le Java.lang .Character objet.
Cela marche:
(apply str my-char-seq)
Fondamentalement, STR appelle Tostring () sur chacun de ses arguments, puis les concaténe. Ici, nous utilisons Appliquer pour transmettre les caractères de la séquence en tant que arguments à STR.
Une autre façon est d'utiliser clojure.string/join
, comme suit:
(require '[clojure.string :as str] )
(assert (= (vec "abcd") [\a \b \c \d] ))
(assert (= (str/join (vec "abcd")) "abcd" ))
(assert (= (apply str (vec "abcd")) "abcd" ))
Il y a une forme alternative de clojure.string/join
qui accepte un séparateur. Voir:
http://clojureocs.org/clojure_core/clojure.string/join
Pour des problèmes plus compliqués, vous pouvez également souhaiter regarder strcat
de la bibliothèque de Tupelo :
(require '[tupelo.core :as t] )
(prn (t/strcat "I " [ \h \a nil \v [\e \space (byte-array [97])
[ nil 32 "complicated" (Math/pow 2 5) '( "str" nil "ing") ]]] ))
;=> "I have a complicated string"
Comme cas particulier, si le type sous-jacent de la séquence en question est clojure.lang.StringSeq
vous pouvez aussi faire:
(.s (my-seq))
ce qui est extrêmement performant car il s'agit simplement de tirer le champ de charcutage final public de la classe Clojure StringSeq.
Exemple:
(type (seq "foo"))
=> clojure.lang.StringSeq
(.s (seq "foo"))
=> "foo"
(type (.s (seq "foo")))
=> Java.lang.String
un exemple des implications de synchronisation (et notez la différence lors de l'utilisation d'un indice de type):
(time
(let [q (seq "xxxxxxxxxxxxxxxxxxxx")]
(dotimes [_ 1000000]
(apply str q))))
"Elapsed time: 620.943971 msecs"
=> nil
(time
(let [q (seq "xxxxxxxxxxxxxxxxxxxx")]
(dotimes [_ 1000000]
(.s q))))
"Elapsed time: 1232.119319 msecs"
=> nil
(time
(let [^StringSeq q (seq "xxxxxxxxxxxxxxxxxxxx")]
(dotimes [_ 1000000]
(.s q))))
"Elapsed time: 3.339613 msecs"
=> nil