Uczę się Clojure i chciałbym porady na temat używania idiomatycznego. Jako część małego pakietu statystyk, mam funkcję obliczania trybu zbioru danych. (Tło: tryb jest najczęstszą wartością w zbiorze danych, jest ich prawie tuzin opublikowanych algorytmów, z których korzysta się w "Podstawach biostatystyki", 6th Ed, Bernard Rosner.)Funkcja trybu Idiomatic w 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)
)
)
Istnieje kilka rzeczy, mam pytania dotyczące:
- argumentu. Funkcja akceptuje pojedynczą sekwencję. Czy bardziej idiomatyczne jest przyjmowanie zmiennej liczby argumentów, takich jak funkcja dodawania?
- Zapach kodu. Wygląda na to, że "let" jest nieco bardziej skomplikowany, niż powinien być - tak wiele zadań zmiennych. Czy przegapiłem oczywiste (lub nie tak oczywiste) zastosowania języka lub biblioteki, które sprawiłyby, że ta metoda byłaby bardziej zwięzła?
Z góry dziękuję za pomoc.
"Funkcja f, którą definiujesz, jest tak naprawdę funkcją tożsamości (ponieważ zero jest logicznie fałszywe)." Nie, z dala od tego.Porównaj wyniki (tożsamość mapy [true false nil 1]) i (map # (nie (nil?% 1)) [true false nil 1]). – pmf
Masz rację, oczywiście, nie jest to ta sama funkcja. Chciałem powiedzieć, że mógłby użyć funkcji tożsamości w swoim miejscu w tym przykładzie. Poprawię to. –
Dzięki za analizę i sugestię. To była tylko zmiana perspektywy, której szukałem. – clartaq