Рубрика «функциональное программирование» - 40

Идея для Clojure Cup этого года родилась примерно вот здесь:

Как мы писали Clojure Cup в этом году: The Hat
(город Вырица, Ленобласть)

Ожидая обратную электричку мы убивали время, как могли, и грустили, что под рукой нет чего-то вроде Alias'а или Шляпы — всё же салонные игры это интеллигентнее, чем косплей гопоты в заброшке. TL;DR:

Как мы писали Clojure Cup в этом году: The Hat

Играть: http://playthehat.com (ещё с багами и не работает не на хроме, мы не можем править до окончания голосования судей)
Голосовать: https://clojurecup.com/#/apps/thehat

Более длинная версия поста — ниже.
Читать полностью »

Оригинальная статья — Understanding Monads With JavaScript (Ionuț G. Stan).
Буду признателен за комментарии об ошибках/опечатках/неточностях перевода в личку

От автора

Последние несколько недель я пытаюсь понять монады. Я все еще изучаю Haskell, и, честно говоря, думал, что знаю, что это такое, но когда я захотел написать маленькую библиотечку — так, для тренировки — я обнаружил, что хотя и понимаю, как работают монадические bind (>>=) и return, но не представляю, откуда берется состояние. Так что, вероятно, я вообще не понимаю, как это все работает. В результате, я решил заново изучить монады на примере Javascript. План был тот же, когда я выводил Y Combinator: взял изначальную задачу (здесь это взаимодействие с неизменяемым явно состоянием), и проделал весь путь к решению, шаг за шагом изменяя изначальный код.
Читать полностью »

Всем привет!

Увидел, что статья о трансдьюсерах на JavaScript стала вполне популярной и хотел отметить, что уже давно доступен генераторов парсеров на транзисторах^W трансдьюсерах. По крайней мере, очень на это похоже. У меня есть статья с подробным описанием на английском «Generating Functional Parsers» и, собственно, исходники.

Тут какие-то новые правила, постов-ссылок уже нет, просят всё обильно описывать — так что я подчинюсь и парой слов (разбавленных необходимой водой), расскажу, о чём это, а то могу ведь и не прав оказаться. Тем более русской версии статьи пока нет, да и скорее всего не будет. Одна надежда, что эта пройдёт.
Читать полностью »

В первой части мы остановились на следующей спецификации: Трансдьюсер — это функция принимающая функцию step, и возвращающая новую функцию step.

step⁰ → step¹

Функция step, в свою очередь, принимает текущий результат и следующий элемент, и должна вернуть новый текущий результат. При этом тип данных текущего результата не уточняется.

result⁰, item → result¹

Чтобы получить новый текущий результат в функции step¹, нужно вызвать функцию step⁰, передав в нее старый текущий результат и новое значение, которое мы хотим добавить. Если мы не хотим добавлять значение, то просто возвращем старый результат. Если хотим добавить одно значение, то вызываем step⁰, и то что он вернет возвращаем как новый результат. Если хотим добавить несколько значений, то вызываем step⁰ несколько раз по цепочке, это проще показать на примере реализации трансдьюсера flatten:

function flatten() {
  return function(step) {
    return function(result, item) {
      for (var i = 0; i < item.length; i++) {
        result = step(result, item[i]);
      }
      return result;
    }
  }
}

var flattenT = flatten();

_.reduce([[1, 2], [], [3]], flattenT(append), []); // => [1, 2, 3]

Т.е. нужно вызывать step несколько раз, каждый раз сохраняя текущий результат в переменную, и передавая его при следующем вызове, а в конце вернуть уже окончательный.

В итоге получается, что при обработке каждого элемента, одна функция step, вызывает другую, а та следующую, и так до последней служебной функции step, которая уже сохраняет результат в коллекцию (append из первой части).

Итак, сейчас мы можем:

  1. Изменять элементы (прим. map)
  2. Пропускать элементы (прим. filter)
  3. Выдавать для одного элемента несколько новых (прим. flatten)

Читать полностью »

Рич Хикки, автор языка Clojure, недавно придумал новую концепцию — Трансдьюсеры. Их сразу добавили в Clojure, но сама идея универсальна и может быть воспроизведена в других языках.

Сразу, зачем это нужно:

  • трансдьюсеры могут улучшить производительность, т.к. позволят не создавать временные коллекции в цепочках операций map.filter.takeWhile.etc
  • могут помочь переиспользовать код
  • могут помочь интегрировать библиотеки между собой, например underscore/LoDash могут уметь создавать трансдьюсеры, а FRP библиотеки (RxJS/Bacon.js/Kefir.js) могут уметь их принимать
  • могут упростить FRP библиотеки, т.к. можно будет выбросить кучу методов, добавив один метод для поддержки трансдьюсеров

Трансдьюсеры — это попытка переосмыслить операции над коллекциями, такие как map(), filter() и пр., найти в них общую идею, и научиться совмещать вместе несколько операций для дальнейшего переиспользования.

Читать полностью »

Наверняка многие уже слышали о подходе FRP для организации асинхронного кода. На хабре уже писали об FRP (Реактивное программирование в Haskell, FRP на Bacon.js) и есть хорошие доклады на эту тему (Программировние UI с помощью FRP и Bacon.js, Functional Reactive Programming & ClojureScript, О Bacon.js от Juha Paananen — автора бекона)

Если коротко, FRP это подход похожий на Promise, но с неограниченным количеством возвращаемых значений, и бОльшим количеством методов для комбинирования / модифицирования потоков событий. Другими словами, если Promise позволяют работать со значением, которого у вас еще нет, так, будто оно у вас уже есть, то FRP позволяет работать со значением, меняющимся во времени, так, будто оно не меняется.

Вот что это дает по сравнению с обратными вызовами:

1) Поток событий (Event stream) и значение меняющаяся во времени (Property / Behavior) становятся объектами первого класса. Это значит что их можно передавать в функции и возвращать из функций.

Например, можно создать объект содержащий клики на кнопку (поток событий), и дальше делать с этим объектом всё, что можно делать с обычной переменной — передавать в функцию, возвращать из функции, сохранять как свойство другого обекта и т.д. Или можно создать объект отражающий текущий размер окна браузера (значение меняющаяся во времени).

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

К примеру можно написать функцию, возвращающую поток перетаскиваний (drag). В качестве параметров она будет принимать 3 потока — начало перетаскивания, движение, конец перетаскивания. Дальше можно передать в эту функцию: либо потоки для соответствующих событий мыши (mousedown, mousemove, mouseup), либо для touch событий (touchstart, touchmove, touchend). Сама же функция не будет ничего знать об источниках событий, а будет работать только с абстрактными потоками. Пример реализации на Bacon.

2) Явный state

Второе большое преимущество FRP это явное управление состоянием. Как известно, state — один из самых главных источников сложности программ, поэтому грамотное управление им позволяет писать более надежные и простые в поддержке программы. Отличный доклад от Рича Хикки о сложности (complexity) «Simple Made Easy».

FRP позволяет писать бОльшую часть кода на «чистых функциях» и управлять потоком данных (dataflow) явно (с помощью потоков событий), а состояния хранить тоже явно в Property.

Читать полностью »

Компания Wolfram Research открыла сервис Tweet a Program: интересных программ на языке Wolfram Language, длина которых не превышает 140 символов

В языке Wolfram Language небольшой код может делать крайне много. Используя это, мы сделали сервис, который позволит вам получить от этого удовольствие, сегодня мы открываем его — Tweet-a-Program.

Этот сервис соединяет в себе программы на языке Wolfram Language длиной в одно сообщение твиттера и возможность их автоматической отправки в @WolframTaP. Наш Твиттер-бот запустит вашу программу в Wolfram Cloud (Облаке Wolfram), после чего опубликует результат.

Hello World from Tweet-a-Program: GeoGraphics[Text[Style[&quot;Hello!&quot;,150]],GeoRange->&quot;World&quot;]
Читать полностью »

(пятница)
Всё началось с того, что я прочитал у Станислава Лема в романе «Мир на Земле» (1985), что в будущем общение на языке будет заменено общением при помощи пиктограмм. Мне показалось это довольно пророческим в связи с возрастающим интересом к различным смайликам и другим видам более крупных картинок и я подумал: а что если программировать при помощи emoji? Поискав в сети я убедился, что мысль такая уже приходила в головы людей и воплотилась в проект https://github.com/wheresaddie/Emojinal
но этот проект меня не впечатлил, во-первых язык не обладает полнотой и вообще подход автора как попытка заменить часть операторов при помощи emoji показалась не сильно интересной.
Читать полностью »

Доброе время суток, уважаемая аудитория хабра.

В данной публикации я хотел описать свой опыт перехода с корпоративного Java на Erlang.

Погружения в Erlang в первом приближении

С недавнего времени начал замечать, что у большего числа людей просыпается интерес к функциональному программированию. Многих в это направление разработки приводит чисто академический интерес, некоторые пытаются решать задачи более подходящими средствами, а другие просто сталкиваются с этим на новых проектах.

После довольно продолжительного времени Java/Python разработки, я решил кардинально изменить сферу деятельность и открыл для себя Erlang.
Читать полностью »

Параллельное программирование для начинающих на ЯП Elixir   Erlang VM на примере задачи «конь Эйлера»

Вступление

Чуть больше года назад я сделал очень важный в своей жизни поступок — скачал с сайта Microsoft IDE Visual Studio и написал на языке C++ свою первую в жизни программу, как это ни странно — «Hello, World!». За следующие полгода я прочитал небезызвестную книжку Страуструпа, устроился на работу джуниор С++ разработчиком, попробовал писать на Lua, Python, но каких-либо значительных успехов не добился — мои библиотеки не работали, программы с трудом компилировались и падали в runtime, указатели указывали не на те участки памяти (которая, кстати, всегда куда-то утекала), а попытки использовать больше одного потока (С++11 же!) приводили к порче памяти и дедлокам. О том, как выглядел код, лучше просто промолчать.

К чему это я? К тому, что по моему личному мнению/опыту императивные языки в силу своих особенностей совершенно не подходят начинающим разработчикам. Без знаний промышленных паттернов программирования, каких-то сведений о работе операционной системы и элементарной культуры кода написать что-то сносное на них очень тяжело. Они дают слишком много свободы и пространства для костылей и велосипедов, в то время как функциональные языки жёстко ограничивая разработчика в некоторых вещах оставляют ему не так много возможностей писать плохой код, заставляя думать и развиваться.

Примерно полгода назад я понял, что пора что-то менять, и после получаса поиска в интернете нашёл спецификации ЯП Erlang. В статье автор представлял Erlang как «чудесную таблетку» от всех вышеописанных мою проблем, и в общем-то по большей части он оказался прав. Так я начал программировать на Erlang, а затем и на Elixir.

Elixir Language

Elixir — язык, построенный поверх Erlang, результат компиляции — байткод Erlang VM. От Erlang он выгодно отличается простотой синтаксиса и мощным инструментарием для мета-программирования (люди, знакомые с Lisp сразу узнают quote-unquote конструкции). Соответственно, для использования доступен весь функционал Erlang, любые его модули и, что самое главное — фреймворк OTP.

Типы данных — те же самые, что и в Erlang. Данные — неизменяемые, результат действий с ними — новые данные. В Elixir как и во многих функциональных языках работает принцип «Всё — выражение». Любое выражение вернёт значение.

У ЯП Elixir есть отличный интерпретатор, который устанавливается вместе с языком, в нём можно опробовать примеры.
Читать полностью »


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js