20 stycznia 2012

Clojure finansowo z makrem -> (wplatanie na drugą pozycję)

Pisałem w poprzednim wpisie o moich ponownych poczynaniach wokół Clojure, aby w końcu zrozumieć jego istotę i w ogóle istotę programowania funkcyjnego.

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.