Kontynuując moje "naukowe" aktywności zakończyłem lekturę "The Joy of Clojure: Thinking the Clojure Way", którą podsumowałem recenzją The "Why" of Clojure - mind-bending for enlightenment with idiomatic Clojure code w serwisie Amazon.com (nakłaniam do oddaniu głosu) i zabrałem się za kolejną książkę Clojure – Grundlagen, Concurrent Programming, Java. Tym razem będzie po niemiecku, a przez to zdecydowanie trudniej (dawno to było, kiedy władałem tym językiem w stopniu zadowalającym).
Jakby celem utrudnienia i tak już niełatwego zadania nauki Clojure po niemiecku, dostałem od Manning Clojure in Action, co przyprawiło mnie o niemały ból głowy - brnąć w przypominanie sobie niemieckiego (jedno z postanowień noworocznych), czy odłożyć to i zabrać się za drugą książkę, która pisana była z myślą o tym "Jak to zrobić w Clojure". Na razie Clojure z niemieckim przeważa.
Przeglądając reakcję czytelników po ostatnim wpisie Clojure finansowo uzasadniłem moje wewnętrzne przekonanie, że należy kontynuować temat programowania funkcyjnego z Clojure.
I właśnie w tym momencie zorientowałem się, że w prezentowanej aplikacji najbardziej zabrakło idiomatycznego Clojure, o którym tak wiele pisano w "The Joy of Clojure".
Było tak:
; zakładam 366 dni w roku 2012 i kapitalizację w dni wolne (niesprawdzone)
(defn interest-rate-per-day [interest-rate-per-year]
(/ (* interest-rate-per-year 0.01) 366))
; funkcja pomocnicza do wyliczenia zysku (niewykorzystywana)
(defn interest [present-value interest-rate]
(- (* present-value (inc interest-rate)) present-value))
(defn future-value [present-value interest-rate periods]
(* present-value (Math/pow (inc (interest-rate-per-day interest-rate)) periods)))
(defn max-present-value [limit interest-rate periods]
(/ limit (Math/pow (inc (interest-rate-per-day interest-rate)) periods)))
(max-present-value 10000 8.1 31)Powinno być jednak tak (miejsca oznaczone przez ",,," w pierwszej funkcji służą *jedynie* wskazaniu, gdzie argument zostanie przekazany przez makro -> - usuń je, a zobaczysz zmianę, a raczej jej brak!):; zakładam 366 dni w roku 2012 i kapitalizację w dni wolne (niesprawdzone)
(defn interest-rate-per-day [interest-rate-per-year]
(-> interest-rate-per-year
(* ,,, 0.01)
(/ ,,, 366)))
(defn future-value [present-value interest-rate periods]
(-> interest-rate
interest-rate-per-day
inc
(Math/pow periods)
(* present-value)))
; teraz dopiero zauważyłem, że future-value jest skopiowane w części do max-present-value :(
(defn max-present-value [limit interest-rate periods]
(let [v (-> interest-rate interest-rate-per-day inc (Math/pow periods))]
(/ limit v)))
(max-present-value 10000 8.1 31)Od razu ładniej, nieprawdaż?Mówią, że po ilości idiomatyczych konstrukcji poznaje się poziom zaawansowania w danej dziedzinie i nie inaczej jest w programowaniu - czy to w Javie, czy Clojure, czy innym języku, nawet takim jak angielski, niemiecki, itp.
A jak to jest u Ciebie z idiomatycznymi konstrukcjami? Znasz jakieś w Javie? Ciekawym również Scali (pewnie _ jest swego rodzaju idiomem) czy JRuby.
Chyba coś Ci się pomyliło w drugiej implementacji max-present-value. Pierwsze wersja bez makra -> daje mi wynik 9931... a druga z makrem -> 1.0068834796647728E-4
OdpowiedzUsuńW końcu! (muszę jednak uważać z tymi wpisami z błędami, bo jeszcze wejdzie w krew) Wiesz dlaczego zwraca błędny wynik? (podpowiedź: kolejność)
OdpowiedzUsuńA co do uzycia samego makra ->. Jego użycia zaciemnilo mi troche obraz tego co tam napisane.
OdpowiedzUsuńOfftopic: daloby rade umieszczac komentarz tylko z nick/email/url a nie z tymi wszystkimi profilami?
Poprawiłem. Inaczej sformatowałem kod. Nie jestem z niego do końca zadowolony, ale niech zostanie dla potomności, jakie to potworki tworzyłem w okresie niemowlęctwa clojure'owego :)
OdpowiedzUsuń