среда, 9 июля 2014 г.

Введение в функциональное программирование

В последнее время увлекся функциональным программированием, в частности, изучил Erlang, продолжаю  изучать Haskell, посмотрел реализацию этой парадигмы в Python. Задумался, а не решить одну какую-нибудь простенькую задачку прикладного характера, используя всё вышеперечисленное. Наткнулся на такую (пример 1).
Реализация решений приведена ниже


Erlang


% напишем свою функцию округления чисел до нужного разряда после запятой
% функция round модуля erlang округляет до целого числа
tround(Number, Precision) ->
  P = math:pow(10, Precision),
  round(Number * P) / P.

otp() ->
  % определим структуру данных в виде списка кортежей
  Data = [{1, 2500, 2.84},
    {2, 15000, 29.3},
    {3, 15000, 29.3},
    {4, 15000, 29.3},
    {5, 12857.14, 25.39},
    {6, 15000, 29.3},
    {7, 15000, 29.3},
    {8, 15000, 29.3},
    {9, 15000, 29.3},
    {10, 15000, 29.3},
    {11, 15000, 29.3},
    {12, 15000, 29.3}],
  Tuple_res = otp_acc(Data, {0, 0}),
  K = 28,
  tround(tround(element(1, Tuple_res) / element(2, Tuple_res), 2)*K, 2).

% в Erlang нельзя применить свертку к кортежу - воспользуемся рекурсией
otp_acc([], {S1, S2}) -> {S1, S2};
otp_acc([Head|Tail], {S1, S2}) -> otp_acc(Tail, {S1+element(2, Head), S2+element(3, Head)}).

Вывод: Рекурсия - неотъемлемая часть функционального программирования.


Haskell


-- напишем свою функцию округления чисел типа Double до нужного разряда после запятой
-- функция round модуля Prelude округляет до целого числа
tround :: Double -> Int -> Double
tround n p = (fromInteger $ round $ n * (10^p)) / (10.0^^p)

otp :: Double
otp =
let
ldata = [(1, (2500, 2.84)),
(2, (15000, 29.3)),
(3, (15000, 29.3)),
(4, (15000, 29.3)),
(5, (12857.14, 25.39)),
(6, (15000, 29.3)),
(7, (15000, 29.3)),
(8, (15000, 29.3)),
(9, (15000, 29.3)),
(10, (15000, 29.3)),
(11, (15000, 29.3)),
(12, (15000, 29.3))]
z = foldl(\acc x -> (fst(acc) + fst(snd(x)), snd(acc) + snd(snd(x)))) (0,0) ldata
k = 28
in tround ((tround (fst(z)/snd(z)) 2) * k) 2

Вывод: Свертка с кортежем - это потрясающе.


Python 2.x


# определим структуру данных в виде словаря с кортежами
data = {1: (2500, 2.84),
          2: (15000, 29.3),
    3: (15000, 29.3),
    4: (15000, 29.3),
    5: (12857.14, 25.39),
    6: (15000, 29.3),
    7: (15000, 29.3),
    8: (15000, 29.3),
    9: (15000, 29.3),
    10: (15000, 29.3),
    11: (15000, 29.3),
    12: (15000, 29.3)}

def otp():
k = 28
tuple_res = reduce(lambda res, d: (res[0] + d[0], res[1] + d[1]), data.values(), (0,0))
return round(tuple_res[0] / tuple_res[1], 2)*k

Вывод: Вполне лаконичное решение. Жаль, что Python постепенно уходит от парадигмы функционального программирования в общем модуле.



Связанные по тематике посты



Комментариев нет:

Отправить комментарий