Рубрики
Без рубрики

Многопарадигм программирование в C ++ и JavaScript

Лучшая парадигма – многомасштабная. Tagged с CPP, JavaScript, функциональным, ООП.

Недавно я работал в Elixir – один из наиболее популярных функциональных языков, построенных вокруг трех столбов функционального программирования:

  • Первоклассные функции
  • Неизменные данные
  • Нет побочных эффектов (чистые функции)

Они часто вступают в конфликт с тремя столпами объектно -ориентированного программирования:

  • Объекты владеют как состоянием, так и поведением
  • Объединения объектов через сообщения
  • Объекты специфичны для задачи

Предметы наиболее в конфликте являются последним из функциональных столбов и первым из ООП. Оказывается, что если объект владеет своим собственным состоянием, то его методы иногда будут изменять это состояние.

Но C ++ и JavaScript позволяют программисту использовать либо – или оба – стиля программирования, и действительно больше.

Функционально совершенен?

И C ++, и JavaScript могут довольно легко выполнять функции как первоклассные значения. Современный C ++ имеет std:: function Для этого, в то время как JavaScript имеет более очевидное функция тип.

Данные довольно легко сделать в C ++ с const Ключевое слово, и это часто бывает в JavaScript (хотя const тоже может помочь здесь).

Но в библиотеках языка можно найти больше помощи.

Императив программиста

В C ++ или JavaScript у нас есть ряд конструкций цикла императивного стиля. Например, оба разрешают итерацию по значению через итерабильный контейнер. Давайте просто добавим их:

В C ++ мы будем использовать цикл диапазона от C ++ 11:

int sum = 0;
for (auto i : iterable) {
  sum += i;
}

В JavaScript мы можем использовать этот изящный бит ES6:

let sum = 0;
for (let i of iterable) {
  sum += i;
}

Объявление программиста

Конечно, мы также можем сделать это, используя стиль уменьшения.

Версия C ++ использует тот факт, что инициатор по умолчанию – это T () и бинарная операция по умолчанию std:: plus <> , это означает, что суммирование массива довольно простое – я использую C ++ 17’s std:: уменьшение Здесь из -за того первого аргумента, что я приду к позже:

auto result = std::reduce(std::execution::par, iterable.begin(), iterable.end());

В JavaScript мы используем Array.reduce метод и посыпать лямбда – или, скорее, функция стрелки – в:

let result = iterable.reduce((sum, val) => sum + val);

Для версии JavaScript мало что можно выбрать между ними. Array.reduce указывает порядок операций, поэтому по определению точно так же. Для версии C ++, благодаря политике выполнения там, она автоматически параллелизирует выполнение на более крупных итерациях – std:: plus <> Вызовы могут быть выполнены в любом порядке.

Правильный инструмент для работы

В C ++ шаблоны написаны с использованием декларативного языка – на самом деле чистый функциональный. На самом деле, если вы посмотрите на Fibonacci ++, вы обнаружите, что две реализации шаблонов являются чистыми функциональными, а два рекурсивных тоже.

Но средние два оба обязательны. Во время сборки чистые функциональные победы – но во время выполнения, императивные бегут намного быстрее. Тем не менее, императивные из них определенно сложнее следовать – и, как мы видели, функциональный код часто можно параллелизировать автоматически в отличие от императивного кода.

В JavaScript две парадигмы программирования также используются в разное время. JSX React сильно декларативен, Redux является чистым функциональным, и все же компоненты React – это простое ООП.

Парадигма коктейли

Чистый функциональный язык, тем не менее, не позволяет выбирать – программист ограничен единственным способом ведения дел. Для программиста, привыкаемого к наличию полной доступности методов, это ужасно сужает.

Однако в JavaScript и C ++ мы можем объединить их, как нам нужно. Допустим, у нас есть тип Foo, который можно вспыхнуть вместе.

auto result = std::reduce(std::experimental::par, iterable.begin(), Foo(), iterable.end(),
  [](auto acc, auto curr) {
    return acc.flarb(curr);
  });

Я мог бы, вероятно, решил сделать Flarb статической функцией, там, и, следовательно, просто пропустил ее как Foo:: Flarb – но это дает мне возможность показать синтаксис Lambda или функционировать, если хотите.

Или, если вы предпочитаете JavaScript:

let result = iterable.reduce((acc, curr) => acc.flarb(curr));

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

На функциональных языках вы получаете что -то вроде «протоколов», в которых конкретная названная операция получает серию реализаций в зависимости от типа аргумента. Это может быть мощным, но оно опирается на то, что поведение и данные являются совершенно различными, и из -за чистых функциональных требований это означает, что вы никогда не сможете иметь измененное состояние в объекте.

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

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

В C ++ программисты часто дрейфуют между различными парадигмами в зависимости от потребностей в то время.

Функциональный объект ориентирован?

Конечно, это не означает, что вам нужно отказаться от совершенно хороших идей из чистого функционального программирования, когда вы делаете немного. В C ++ вы даже получаете помощь здесь – const Ключевое слово делает экземпляры неизменными, и методы CONST можно использовать для работы с ними. Конечно, вам все равно нужно избегать глобальных ущерб, но это, как правило, хорошая практика. Это чистые функциональные методы? Может быть. Это действительно имеет значение?

JavaScript const Немного отличается, но все еще полезно – самые основные типы данных в JavaScript в любом случае неизменны, и const предотвращает повторение. Опять же, вам нужно избегать глобалов – и в равной степени, очевидно, документ и окно будут случаи, когда вы, скорее всего, согните это правило.

И победителем становится…

Лучшая парадигма-это всегда многопарадигма.

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

Точно так же C ++ продолжает идти, несмотря на то, что вокруг него появляются сотни новых языков (включая JavaScript!), Потому что разработчик может легко переключаться между парадигмами в соответствии с работой.

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

Оригинал: “https://dev.to/dwd/multi-paradigm-programming-in-c-and-javascript-3h6a”