EDIT: tout ce que j'ÉCRITES A TORT
Lorsqu'une fonction d'un var-arg est appliqué avec un seq plus long que le nombre d'arguments discrets, le reste du seq est passé comme var-arg (voir RestFn.applyTo).
À Jürgen: Je suis stupide. Vous êtes intelligent. J'avais tort. Tu avais raison. Tu es le meilleur. Je suis le pire. Tu es très beau. Je ne suis pas attirant.
Ce qui suit est un compte rendu de mon idiotie ...
En réponse au commentaire de Jürgen Hötzel.
mapcat
n'est pas totalement paresseux car apply
n'est pas paresseux dans l'évaluation du nombre d'arguments à appliquer. En outre, apply
ne peut pas être paresseux car les fonctions doivent être invoquées avec un nombre discret d'arguments. Actuellement, si le nombre d'arguments dépasse 20, les arguments restants sont déversés dans un tableau, donc non-paresseux.
Donc regardant la source mapcat
:
(defn mapcat
"Returns the result of applying concat to the result of applying map
to f and colls. Thus function f should return a collection."
{:added "1.0"}
[f & colls]
(apply concat (apply map f colls)))
Si nous élargissons l'évaluation à l'aide de l'exemple, la apply
intérieure évaluerait à:
user=> (map seq str-coll)
((\a \b \c \d) (\e \f \g \h) (\j \k \l \m))
qui est bien puisque les str-coll
doesn pas complètement réalisé, mais alors l'extérieur apply
évaluerait à:
user=> (concat '(\a \b \c \d) '(\e \f \g \h) '(\j \k \l \m))
(\a \b \c \d \e \f \g \h \j \k \l \m)
Notez que le apply
externe applique n arguments à concat
, un pour chaque chaîne dans l'original str-coll
. Maintenant, il est vrai que le résultat de concat
est paresseux, et chaque arg est lui-même paresseux, mais vous devez encore réaliser toute la longueur de str-coll
pour obtenir ces n seqs paresseux. Si str-coll
a 1000 chaînes, alors concat
obtiendra 1000 arguments, et toutes les 1000 chaînes devront être lues dans le fichier et en mémoire avant que concat
puisse être appelé.
Pour les incroyants, une démonstration de la seq réalisant le comportement d'appliquer:
user=> (defn loud-seq [] (lazy-seq (println "HELLO") (cons 1 (loud-seq))))
#'user/loud-seq
user=> (take 3 (loud-seq)) ; displaying the lazy-seq realizes it, thus printing HELLO
(HELLO
HELLO
1 HELLO
1 1)
user=> (do (take 3 (loud-seq)) nil) ; lazy-seq not realized; no printing of HELLO
nil
user=> (do (apply concat (take 3 (loud-seq))) nil) ; draw your own conclusions
HELLO
HELLO
HELLO
nil
Et une démonstration que varargs ne sont pas paresseux:
user=> (defn foo [& more] (type more))
#'user/foo
user=> (foo 1 2 3 4)
clojure.lang.ArraySeq
user=> (apply foo (repeat 4 1))
clojure.lang.Cons
Bien que le contrepoint, que les œuvres suivantes me déroute:
user=> (take 10 (apply concat (repeat [1 2 3 4])))
(1 2 3 4 1 2 3 4 1 2)
Pas besoin d'aplatir, juste concatuer les séquences de caractères en utilisant mapcat: (partition-tous les 3 (mapcat seq str-coll)) –
ataggart et Jürgen, merci beaucoup pour les solutions: mappage à un seq était exactement ce que j'étais disparu. Surmonter cet obstacle m'a fait réaliser que la partition n'était pas aussi paresseuse que j'avais espéré. Alors que chaque partition est fournie de manière paresseuse, les composants individuels de chaque partition ne le sont pas; donc le partitionnement du fichier initial aux délimiteurs ne fournit pas les chaînes paresseuses désirées qui alimentent cela. –
@ Jürgen: mapcat n'est pas fainéant (il utilise apply), donc pourquoi je ne l'ai pas utilisé. –