J'apprends Clojure et je voudrais des conseils sur l'utilisation idiomatique. Dans le cadre d'un petit paquet de statistiques, j'ai une fonction pour calculer le mode d'un ensemble de données. (Contexte: Le mode est la valeur la plus commune dans un ensemble de données.Il y a près d'une douzaine d'algorithmes publiés pour le calculer.Cela utilisé ici provient de "Fundamentals of Biostatistics" 6th Ed par Bernard Rosner.)Fonction du mode idiomatique dans Clojure
(defn tally-map
" Create a map where the keys are all of the unique elements in the input
sequence and the values represent the number of times those elements
occur. Note that the keys may not be formatted as conventional Clojure
keys, i.e. a colon preceding a symbol."
[aseq]
(apply merge-with + (map (fn [x] {x 1}) aseq)))
(defn mode
" Calculate the mode. Rosner p. 13. The mode is problematic in that it may
not be unique and may not exist at all for a particular group of data.
If there is a single unique mode, it is returned. If there are multiple
modes, they are returned as a list. If there is no mode, that is all
elements are present in equal frequency, nil is returned."
[aseq]
(let [amap (tally-map aseq)
mx (apply max (vals amap))
k (keys amap)
f (fn [x] (not (nil? x)))
modes (filter f (map #(if (= mx (get amap %)) %) k))
]
(cond (= 1 (count modes)) (first modes)
(every? #(= mx %) (vals amap)) nil
:else modes)
)
)
Il y a deux ou trois choses que j'ai des questions sur:
- L'argument. La fonction accepte une seule séquence. Est-il plus idiomatique d'accepter un nombre variable d'arguments comme la fonction d'addition?
- Odeur du code. Il semble que le "let" soit un peu plus compliqué qu'il ne devrait l'être - autant d'assignations de variables. Ai-je manqué des utilisations évidentes (ou pas si évidentes) du langage ou de la bibliothèque qui rendraient cette méthode plus concise?
Merci d'avance pour l'aide.
"La fonction que vous définissez est vraiment la fonction d'identité (puisque nil est logiquement faux)." Non, loin de là.Comparez les résultats de (identité de carte [true false nul 1]) et (carte # (non (néant?% 1)) [true false nul 1]). – pmf
Vous avez bien sûr raison, ce n'est pas la même fonction. Je voulais dire qu'il pourrait utiliser la fonction d'identité à sa place dans cet exemple. Je vais corriger cela. –
Merci pour l'analyse et la suggestion. C'est juste le changement de perspective que je cherchais. – clartaq