Перейти к публикации
Форум - ComputerCraft
LeshaInc

[MoonJam] Функциональное Программирование

Рекомендованные сообщения

p8bU3JR.png     MoonyLambda

 

Вы наверное знаете что сейчас проходит конкурс MoonJam. В общем суть в том что бы написать что-нибудь на MoonScript за неделю. Как говорил уже тотора, что-то серьезное за неделю не написать, но попробовать, поразвлечься, и написать что-нибудь интересное можно.
 
В общем в этой теме буду показывать мой проект. И это... Библиотека для функционального программирования (далее просто - ФП)!
 
Луа не предоставляет стандартных средств для ФП, потому я написал свою библиотеку. Чем то она похожа на реализацию такового функционала в языке Python, а чем то нет.
 
Суть в том что функциональное программирование очень сильно упрощает работу с данными, например вместо пяти строк мы напишем одну строку.

 



 

Все примеры в MoonScript, но в спойлерах будет эквивалент на луа. f - библиотека подключенная через require

 

Начнем с самого простого, сложить массив чисел.

f.reduce f.add, {1, 2, 3} --> 6

 

 

f.reduce(f.add, {1, 2, 3}) --> 6

 

 

 

Точно таким же образом, мы можем перемножить все числа f.mul вместо f.add, или соответственно разделить, вычесть или возвести в степень - f.div, f.sub и f.pow

 

А если, к примеру, нам нужно взять массив и выкинуть из него все нечетные числа. Это тоже возможно.

f.filter f.even, {1, 2, 3, 4} --> {2, 4}

 

 

f.filter(f.even, {1, 2, 3, 4}) --> {2, 4}

 

 

 

А теперь, достанем все числа которые одновременно и меньше пяти, и четные. Это не составит труда

f.filter f.even, f.filter ((a) -> a < 5), {1, 2, 4, 5, 6, 7} --> {2, 4}

 

 

f.filter(f.even, f.filter((function(a)
  return a < 5
end), {1, 2, 4, 5, 6, 7})) --> {2, 4}

 

 

 

Хочу отметить, что нам не обязательно постоянно писать огромные цепочки из вызовов. Все функции в библиотеке каррированы.

selectEven = f.filter f.even
selectEven {1, 2, 3, 4, 5} --> {2, 4}

 

 

local selectEven = f.filter(f.even)
selectEven({1, 2, 3, 4, 5}) --> {2, 4}

 

 

 

...Но мы можем каррировать свою функцию!

pow = f.curry (a, b) -> a ^ b
pow2 = pow 2

pow 3, 3 --> 27
pow2 3   --> 8

 

 

local pow = f.curry(function (a, b)
  a ^ b
end)

local pow2 = pow(2)

pow(3, 3) --> 27
pow2(3)   --> 8

 

 

 

К слову, именно так определена в библиотеке функция f.pow.

 

Каррированная функция сама определяет, что ей вернуть, функцию которая примет недостающие аргументы, или результат. Мы можем каррировать функцию с любым количеством аргументов, так просто! :dance3:

 

Реверс таблицы - легко, расплющить таблицу - легко, изменить таблицу - легко.

Но самое главное... Все функции чистые. Ни одна функция этой библиотеки не изменяет данные, и не зависит от внешних данных.

 

Вполне продакшен-ready пример:

first_letter = (a) -> a\sub 1, 1
f.group first_letter, {"Miku Chan", "Mayonnaise", "LeshaInc", "Loli", "Totoro"}
--> {M: {"Miku Chan", "Mayonnaise"}, L: {"LeshaInc", "Loli"}, T: {"Totoro"}}

 

 

local first_letter = function(a)
  return a:sub(1, 1)
end
f.group(first_letter, {"Miku Chan", "Mayonnaise", "LeshaInc", "Loli", "Totoro"})
--> {M = {"Miku Chan", "Mayonnaise"}, L = {"LeshaInc", "Loli"}, T = {"Totoro"}}

 

 

 

 

И все это становится таким простым используя библиотеку MoonyLambda.

 


 

Скачать

 

Документация

...будет постепенно писаться в этой теме. Ссылки будут тут.

 

 

Функциональный стиль выглядит гораздо читаймей, чем императивней стиль. Когда в императивном стиле мы пишем непонятный цикл, который непонятно что делает, тут мы пишем несколько строк кода, который понятен с первого взгляда.

Изменено пользователем LeshaInc
  • Like 3

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Создайте аккаунт или войдите в него для комментирования

Вы должны быть пользователем, чтобы оставить комментарий

Создать аккаунт

Зарегистрируйтесь для получения аккаунта. Это просто!

Зарегистрировать аккаунт

Войти

Уже зарегистрированы? Войдите здесь.

Войти сейчас

×