Estoy aprendiendo Clojure y me gustaría obtener algunos consejos sobre el uso idiomático. Como parte de un pequeño paquete de estadísticas, tengo una función para calcular el modo de un conjunto de datos. (Antecedentes: el modo es el valor más común en un conjunto de datos. Hay casi una docena de algoritmos publicados para calcularlo. El que se usa aquí es de "Fundamentos de la bioestadística" 6ª edición de Bernard Rosner.)Función de modo idiomático en 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)
)
)
Hay un par de cosas que tengo preguntas sobre:
- El argumento. La función acepta una sola secuencia. ¿Es más idiomático aceptar una cantidad variable de argumentos como la función de suma?
- Código de olor. Parece que el "let" es un poco más complicado de lo que debería ser, tantas asignaciones variables. ¿Me he perdido algún uso obvio (o no tan obvio) del idioma o la biblioteca que haría este método más conciso?
Gracias de antemano por la ayuda.
"La función que define es realmente la función de identidad (ya que nil es lógicamente falsa)." No, ni mucho menos.Compare los resultados de (identidad de mapa [verdadero falso nulo 1]) y (número de mapa (no (nulo?% 1)) [verdadero falso nulo 1]). – pmf
Tienes razón, por supuesto, no es la misma función. Quise decir que él podría usar la función de identidad en su lugar en este ejemplo. Voy a corregir eso. –
Gracias por el análisis y la sugerencia. Ese es solo el cambio de perspectiva que estaba buscando. – clartaq