Функция фильтра - вторая в нашей святой троице

Ричард Уотерс разработал программу, которая автоматически анализирует традиционные программы Fortran, просматривая их с точки зрения карт, фильтров и накоплений. Он обнаружил, что полностью 90% кода в пакете подпрограмм Fortran Scientific полностью вписывается в эту парадигму.

- SICP 1979 г.

У нас, программистов на JavaScript, есть возможность попрактиковаться в многопарадигмном языке, поддерживающем функциональное программирование.

Вы хотите изучить эту силу?

Начнем с 24 уроков от Α до Ω, посвященных решению наших повседневных проблем.

Обзор уроков:

«Α. для каждого",

«Β. карта",

γ.фильтр.

Войти

Я регулярно говорю о сигнатурах функций. Подписи - это однострочный оператор, обозначающий намерение (или имя), а также входные и выходные данные функции, например double::number -> number.

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

Подумайте о том, чего вы хотите достичь, прежде чем писать, жизненно важно соблюдать гигиену кода. Вы почувствуете, что контролируете свой код, и будете готовы решать проблемы по частям. Это не дает вам потеряться в спагетти-коде, безумно исправляя все до тех пор, пока кажется, что это не сработает.

В JavaScript сигнатуры жестко не запрограммированы, поскольку это язык со слабой / динамической типизацией. Совет - просто используйте комментарии. Представим, что наш домен - это казино, особенно игра в рулетку. Вот несколько полезных сигнатур с базовыми реализациями.

Присоединяйтесь к Ордену

Map, filter и reduce - простые функции высшего порядка, как описано в предыдущих сообщениях этой серии. Когда вы используете только один уровень более высокого порядка, вас всегда интересуют две подписи: подпись вашей функции второго (более высокого) порядка (функция, которая запускает другую) и подпись вашей функции первого порядка (полученная классическая функция в качестве аргумента, который будет запущен, например, обратный вызов).

Как видите, filter имеет очень интересную сигнатуру: он возвращает коллекцию элементов того же типа, в конечном итоге подмножество исходного списка, содержащего только элементы, соответствующие условию. Фактически, он не может ничего добавить или преобразовать в вашей коллекции.

Это условие проверяется обратным вызовом, выполняемым один за другим для каждого элемента исходной коллекции.

Сигнатура обратного вызова будет чем-то вроде callback::(a) -> boolean, принимая текущее a в цикле. Действительно, обратный вызов, возвращающий истинное значение, является дверью «годен / не годен», которая позволяет функции высшего порядка filter сохранять только результаты поиска.

Здесь приветствуются наши even и odd функции, касающиеся их number -> boolean сигнатур, совместимых с нашим массивом number[].

Логически нашу color функцию нельзя использовать как есть, но это всего лишь шаг вперед.

Я знаю, что вы не согласны с этой play нечистой функцией, разделяющей некоторые константы с глобальной областью видимости. Сначала я подумал то же самое, но нам придется подождать и посмотреть, какие уроки мы узнаем о closures, currying, и memoization , чтобы вылечить эту неприемлемую нечистоту.

Отказавшись от нашей гипотезы о казино, вы вместо этого можете рассматривать свой код как большую фабрику с повсюду бегающими ремнями. Filter руки забирают то, что у нас есть, кладут на новый пояс, а остальное выбрасывают в мусор. Затем специальные map оружия преобразуют то, что они нашли на новом поясе. И эти машины совместимы с коллекциями любого размера в нашем домене. Фактически, я работаю над проектом под названием Functorio - игрой, в которую можно играть с классиками функционального программирования на большом заводе.

Моя собственная алгебра

Видите ли вы какую-нибудь другую нестандартную алгебру? Мы очень согласованно определяем миры данных и функций, домен за доменом, один для казино, другой для сайта знакомств. Вот почему map-filter-reduce - наша святая троица: они могут легко совпадать практически с любыми доменами. Предупреждение о спойлере: map и filter - это лишь некоторые из наиболее распространенных вариантов использования reduce. Функциональные программисты предпочитают разделять их, потому что они очень распространены. Это не обязательно относится к odd, even, min, max, reverse и т. Д. В конце концов, речь идет о предметно-ориентированной алгебре - например, хорошо составленная профессиональная кодовая база.

Функциональное программирование - не новая парадигма. Это способ думать о кодировании: мы хотим определить сплоченную виртуальную вселенную, которой человеческий мозг может управлять - как виртуальный DOM в React. Он основан на машине Тьюринга: истинные и ложные цепочки - поэтому мы зависим от булевой алгебры. Функции - это наши минимальные элементы как абстрактные комбинируемые инструменты для анимации этой живой области, поэтому мы принимаем Лямбда-исчисление. Он построен на основе связанных списков и наборов, поэтому мы принимаем Теорию категорий. А остальные типы и расчеты будут сделаны нашими собственными руками, поэтому мы создаем новую алгебру для нашей конкретной области: онлайн-казино, монитор бронирования пиццерий, ветеринарный бэк-офис, ERP банка или сайт орнитолога.

Как вы, наверное, знаете, filter существует во встроенной реализации любого массива JavaScript. Это прототип метода, который вы можете использовать (если вы не пишете свой собственный фильтр, как мы). Мы можем представить ее реализацию вместе и просто связать ее с некоторыми maps, чтобы почувствовать нашу новую силу.

А как насчет того, чтобы объединить наши filter в цепочку, не создавая каждый раз новый const? Это возможно по композиции, но в нашем любимом языке пока нет встроенного оператора. Но в будущем JavaScript (ES9, ES10?) Должен быть способ передачи функций по конвейеру с помощью этого оператора конвейера: |>. Его уже можно использовать с Babel.

После следующего урока мы сможем создавать pipe и compose операторные функции, что позволит нам связывать функции до 2020 года, особенно наши map, filter и reduce более высокого порядка. .