Паттерны Command и Strategy с точки зрения функционального программирования

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

Паттерны проектирования и функциональное программирование? Как это вообще связано?


В умах многих разработчиков, привыкших к объектно-ориентированной парадигме, возникает впечатление, что проектирование программного обеспечения, как таковое, неразрывно связано с ООП и всё остальное — суть ересь. UML, большей частью нацеленный на ООП, используется как универсальный язык для проектирования — хотя он таким, конечно, не является. И мы видим, как мир объектно-ориентированного программирования постепенно погружается в пучину преступного переинженеринга (1).
В силу этого зачастую даже не ставится вопрос о выборе парадигмы программирования. Тем не менее, этот вопрос является весьма существенным, и зачастую правильный ответ даёт большие преимущества (3). Это, вообще говоря, выходит за рамки того, что мы привыкли называть проектированием — это вопрос из области архитектуры.

Лирическое отступление: разница между архитектурой, проектированием и реализацией

Не так давно я наткнулся на весьма интересное исследование — (2). В нём рассматривается задача формализации понятий «архитектура», «проектирование» и «реализация», которые чаще всего употребляются неформально. И авторам удаётся вывести весьма интересный критерий: критерий Intension/Locality. Я не буду углубляться в философию и просто приведу краткое описание критерия (эта часть — фактически перевод) и мои выводы из него.
Свойство Intension (интенсионность) означает способность некой сущности описывать бесконечное множество предметов: например, понятие простого числа. Ему противоположно свойство экстенсионности — сущность описывает конечный набор предметов: например, понятие страны — члены НАТО.
Свойство локальности — сущность влияет только на отдельную часть системы. Соответственно, глобальность — сущность влияет на всю систему в целом.
Дак вот, учитывая эти два свойства, авторы указанного исследования составляют такую таблицу:
image
Пользуясь ей легко определить, что относится к уровню архитектуры, а что — к уровню проектирования. И вот мой вывод: выбор парадигмы программирования, платформы и языка — это решение уровня архитектуры, т.к. этот выбор глобален (затрагивает все части системы) и интенсионен (парадигмы определяют способы решения бесконечного множества задач).

Тем не менее, решить столь глобальную задачу (найти критерии выбора подходящей парадигмы) мне пока не по силам. Поэтому я решил выбрать два уже существующих класса задач и показать, что для них стоит использовать не привычный для многих ОО подход, а функциональный, который в последнее время приобретает (заслуженно) всё большую популярность.
Классы задач я выбрал необычным методом — я взял два паттерна ОО проектирования и показал, что они, по сути — ограниченная реализация понятия из области функционального программирования — функции высшего порядка (higher-order function, далее: ФВП). Гипотеза заключалась в том, что паттерны — это устоявшиеся решения определённых проблем, а раз возникают проблемы и их устоявшиеся решения, видимо есть некие слабости и недостатки, которые приходиться преодолевать. Для рассмотренных паттернов это действительно так.
Кстати говоря, подобный подход был использован в (5) и (6). В (6) вообще было указано на возможность замены большинства паттернов, но подробный анализ каждого не проводился. В (5) было более подробное рассмотрение Command и Strategy, но немного с другой стороны. Я решил сделать что-то более практичное, чем в (6), и с другими акцентами, чем в (5). Итак, приступим.

Higher-order functions


Думаю, практически все в той или иной форме знакомы с этой идей.
Функция высшего порядка – это функция, которая принимает в качестве аргумента или возвращает как результат другую функцию.
Такое становится возможным благодаря основной концепции функционального программирования: функции – это значения. Стоит отметить, что когда мы говорим, что функция и значение в функциональном программировании полностью соответствуют аналогичным понятиям из математики, мы имеем в виду именно полное соответствие. Это одно и то же. Пример широко распространённых в математике ФВП – операторы дифференцирования, интегрирования и композиции (вообще говоря, это близко к понятию оператора из функционального анализа). Оператор композиции имеет непосредственное выражение в большинстве языков, поддерживающих функциональную парадигму. Пример на F#:

let f = (+) 10
let g = (*) 2
let composition = f << g
printfn "%i" <| g 15
printfn "%i" <| f 30
printfn "%i" <| composition 15

Вывод:

30
40
40

Очевидно, что запись f << g соответствует записи f(g(x)) или F ○ G.
Чтобы лучше понять это, предлагаю обратить внимание на тип оператора композиции:

('a -> 'b) -> ('c -> 'a) -> 'c -> 'b

Участки описания типа функции в скобках — это тоже типы функций. То есть, это функция, принимающая в качестве аргументов:
  • Функцию, принимающую в качестве аргумента значение обобщённого типа 'a и возвращающую значение обобщённого типа 'b
  • Функцию, принимающую в качестве аргумента значение обобщённого типа 'c и возвращающую значение обобщённого типа 'a
  • Значение типа 'c

и возвращающая значение типа 'b. Фактически же она строит функцию, принимающую в качестве аргумента значение типа 'c и возвращающую значение типа 'b, т.е. тип можно переписать так:

('a -> 'b) -> ('c -> 'a) -> ('c -> 'b)

ФВП позволяют выделять общее поведение. За счёт этого они улучшают повторную используемость кода.
Это можно применить для разных целей – например, для обработки исключений. Предположим, что у нас есть много участков кода, которые могут вызвать определённый набор исключений. Мы можем записывать сам склонный к ошибкам код в виде функций, которые будем передавать в качестве параметра другой функции, производящей обработку исключений. Пример на C#:

private void CalculateAdditionalQuantityToIncreaseGain()
        {
                //получаем данные
                var unitPrice = ExtractDecimal(gainUnitPriceEdit);
                var quantityReleased = ExtractDecimal(gainQuantityEdit);
                ...
        }


А вот ФВП, обрабатывающая исключения:

private static void ExecuteErrorProneCode(Action procedure)
{
            try
            {
                procedure(); //исполняем переданную в качестве параметра функцию
            }
            catch (WrongDecimalInputInTextBoxException ex)
            {
                MessageBox.Show(ex.Message, "Ошибка во вводе");
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Ошибка");
            }
}

Тогда для обработки исключений, вызванных какой-либо функцией, достаточно писать:

ExecuteErrorProneCode(CalculateAdditionalQuantityToIncreaseGain);

Это существенно сокращает код, если обработчиков исключений много и/или много функций, который могут выкинуть исключения, которые необходимо обработать однотипно.
Также классическим примером выделения общего поведения является использование функций высшего порядка для сортировки. Очевидно, что для проведения сортировки необходимо иметь возможность сравнить элементы сортируемой коллекции между собой. В качестве такого «сравнителя» выступает функция, которая передаётся в качестве аргумента функции сортировки – соответственно, функция сортировки для обеспечения универсальности должна быть ФВП. В целом, возможность создавать ФВП – критически важное звено в цепочке действий, направленных на создание абстрактных обобщённых алгоритмов.
Кстати, так как ФВП, как и любые функции, являются значениями, их можно использовать для представления данных. Об этом смотрите статью про представление Чёрча.

Паттерн Command


Паттерн проектирования Command, как и Strategy, относится к поведенческим паттернам проектирования. Его основная роль — инкапсуляция некой функции. У этого паттерна много применений, но чаще всего он используется для того, чтобы сделать следующее:
  • Посылать запросы к разным получателям
  • Выстраивать команды в очереди, вести логи, отменять запросы
  • Создавать сложные операции из простых
  • Реализовать команды Undo (отмена последнего действия) и Redo (повтор последнего отменённого действия)

В общем случае он выглядит так:

image

Я буду рассматривать пример с реализацией undo и redo — чистую ОО версию реализации этой функциональности вы можете посмотреть тут.
Распределение ролей на этой диаграмме:

image

Здесь Filter соответствует Receiver'у, LoggingInvokerInvoker'у, IFilterCommandICommand. Вот как мы будем вызывать операции (создавать команды можно как в Client'e, передавая их как параметр методу Execute() LoggingInvoker'а, так и в самом LoggingInvoker'e — выбор зависит от конкретной ситуации):

image

А вот как мы их будем отменять:

image

performedOps и undoneOps — это стеки, хранящие исполненные и отменённые команды.
Однако, после рассмотрения ФВП довольно очевидно, что всё это поведение можно реализовать в виде ФВП, если выбранный язык поддерживает такую возможность. Действительно, объект Invoker можно заменить ФВП, принимающей в качестве аргумента функцию, соответствующую конкретной операции – нам больше не нужны объекты Command, потому что функции сами являются значениями, и интерфейс ICommand, т.к. его функции выполняет система типов языка, поддерживающего функциональную парадигму.
Приведём схему замены этого паттерна на конструкцию в функциональной парадигме, могущей выполнять те же функции:

image

На псевдокоде (инспирированном F#) соответствующая функциональная реализация будет выглядеть так:

//стеки для выполненных и отменённых операций
//здесь мы создаём тип - кортеж из функции и первоначальных данных
type OpType = (DataType -> DataType) * DataType
//и стеки из значений этого типа
let performedOps = Stack<OpType>()
let undoneOps = Stack<OpType>()
 
//замена LoggingInvoker - ФВП
let execute operation data = 
    let res = operation data //выполняем операцию
    performedOps.Push(operation, data) //заносим операцию и предыдущее состояние в стек
    res //возвращаем результат выполнения операции
 
let undo () =
    if performedOps.Count > 0 then
        //переносим запись об операции из стека выполненных в стек отменённых
        undoneOps.Push(performedOps.Pop())
        //и возвращаем состояние до выполнения операции
        Some (snd undoneOps.Peek()) //здесь мы используем обобщённый тип 'a option, см. (5) или (7)
    else
        None
 
//Операции
let OperationOne data = 
    ...
 
let OperationTwo data = 
    ...

//выполняем операцию OperationOne 
let mutable a = execute OperationOne data
//отменяем операцию
let b <- undo ()

Мы передаём функцию, которую хотим выполнить, ФВП execute. Функция execute ведёт стек выполненных операций, выполняет операцию и возвращает результат её выполнения. Функция undo отменяет последнюю выполненную операцию.

Данный подход имеет некоторые дополнительные преимущества перед использованием паттерна Command:
  1. Результирующий код естественнее, короче и проще
  2. Можно легко создавать макросы и сложные операции с помощью композиции или pipe-lining’a (о pipe-lining'e см. (5) или (7)) простых операций
  3. Можно создавать сложные структуры данных, содержащие операции, например для динамического построения меню.

Кроме того, если мы используем мультипарадигменный язык, мы можем сочетать в разных пропорциях ОО паттерн Command и продемонстрированный здесь подход.
Многие современные языки поддерживают ФВП в той или иной степени. Например, в C# есть механизм делегатов. Пример решения задачи о создании undo с помощью делегатов вы можете найти в (4).

Паттерн Strategy


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

image

Контекст хранит в себе ссылку на одну из реализаций интерфейса IStrategy, при необходимости выполнить некую операцию он обращается к методу этого хранимого объекта. Меняя объекты — меняем методы.
Это так же легко преобразуется к функциональному стилю. На этот раз мы можем использовать список функций, чтобы сохранить возможные стратегии:

image

На псевдокоде:

let strategyA data = ...
let strategyB data = ...
let useStrategy strategy data =
    ...
    strategy data

...
useStrategy strategyA data

Функции strategyA, strategyB,… – это функции, реализующие возможные стратегии. Функция высшего порядка useStrategy применяет выбранную стратегию к данным. Стратегия передаётся просто как аргумент для функции useStrategy.
Кроме значительного упрощения и сокращения кода этот подход даёт нам дополнительное преимущество – теперь мы можем легко создавать функции, параметризованные сразу несколькими стратегиями, что при обычном ОО подходе приводит к очень сложной структуре программы. Мы можем вообще не задавать отдельные имена для стратегий с помощью такой возможности, как анонимные функции, если они достаточно просты в реализации. Например для сортировки данных в ФП можно использовать ФВП sort и в качестве параметра передавать ей не тип, который реализует интерфейс IComparer, в котором реализован метод сравнения, как это делается в ООП, а просто саму операцию сравнения:

let a = sort (<) data

Выводы


1. Правильный выбор парадигмы в соответствии с классом решаемой задачи зачастую может быть критическим фактором для успешности её решения. Если ваша задача относится к классу т.н. behavior-centric, стоит задуматься об использовании функционального подхода.
2. Паттерны Command и Strategy — это ограниченная реализация функций высшего порядка
3. Не обязательно переходить на чисто функциональный язык, чтобы использовать преимущества решения с помощью ФВП — большинство современных мейнстримовых языков в той или иной мере поддерживают ФВП.

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

Источники


1. Criminal Overengineering
2. Architecture, Design, Implementation. Amnon H. Eden, Rick Kazman. Portland: б.н., 2003. 25th International Conference on Software Engineering — ICSE
3. Banking Firm Uses Functional Language to Speed Development by 50 Percent. Microsoft Case Studies. март 2010 г.
4. Bishop, Judith. C# 3.0 Design Patterns. Sebastopol, California: O’Reilly, 2008.
5. Tomas Petricek, Jon Skeet. Functional Programming for the Real World. б.м.: Manning Publications, 2010.
6. Gabriel, Richard P. Objects Have Failed Slides DreamSongs.com.
7. Smith, Chris. Programming F#. Sebastopol, California: O’Reilly, 2010.

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

«Норвиг в 1996 году рассматривал паттерны в Lisp и Dylan. Собственно, результат аналогичный (многие паттерны становятся тривиальными или существенно упрощаются), но на более богатом материале.»

Средняя зарплата в IT

110 000 ₽/мес.
Средняя зарплата по всем IT-специализациям на основании 8 813 анкет, за 2-ое пол. 2020 года Узнать свою зарплату
Реклама
AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Подробнее

Комментарии 94

    +1
    Интересная статья. Стимулирует читать книги в сноске.
      +1
      Спасибо.
      Кстати говоря, тем, кто впервые сталкивается с функциональным программированием, я бы порекомендовал начинать с этой книги. Даже если Haskell — не тот язык, в котором вы заинтересованы, — ибо в этой книге есть отличные упражнения, сайт с ответами и комментариями пользователей (и вообще вся книга доступна он-лайн по вышеприведённой ссылке) и она учит именно мыслить в стиле ФП.
      +6
      Да, функциональные языки программирования поворачивают мозги в другую строну.
        0
        *сторону
        –2
        До некоторой части паттерны это реализация тех вещей, для которых «классический» (тот который был в языках типа явы\с++ в период их зарождения) ООП не очень подходит.

        Например паттерн композит — реализация миксинов/трайтов не средствами языка, а «вручную».
          +2
          По моему вы что-то путаете, паттерн composite ни разу не реализация паттерна mixin. Это очень даже разные вещи, преследующие разные цели.
            0
            Ах, да сорри, с декоратором перепутал.
              +1
              У декоратора и примеси разные цели. Разница между ними примерно такая-же как при обычном и множественном наследовании (но только примерно, так как все четыре подхода — суть разные вещи, служащие для достижения разных целей).
                –1
                Я не говорю, что это одинаковые вещи, просто паттерные зачастую создают с целью обойти ограничения накладываемые языком и привнести какие-то дополнительные конструкции, для реализации мета-программирования.
                  +1
                  Просто фраза о том, что декоратор — реализация примеси «вручную» — неверна, так как эти вещи преследуют разные цели. У одного класса может быть и примесь и декоратор, и они не будут взаимозаменяемы ни в одну ни в другую сторону.
          +4
          Резюме:
          При использовании паттернов команда и стратегия в ООП языках создаются классы которые содержат только одну функцию. Соответственно в языках с функциональными возможностями можна функцию в класс не оборачивать.

          Зачем такую простую мысль было так усложнять?

          И еще ИМХО: паттерны это архитектурные решения и они не привязаны к конкретной парадигме.
          Если в функциональном языке программирования вы реализовали алгоритм той же сортировки, который принимает функцию для сравнения обьекта — это тоже паттерн «стратегия», только реализованый через функторы а не через классы.

            +2
            Насчёт первого:
            1. Я исходил из предположения, что не всем известны сами паттерны достаточно хорошо. Поэтому я кратко их описал
            2. Я предполагал, что не всем известно само понятие ФВП — и я предполагаю, что гораздо ценнее знать, почему мы можем не создавать класс для обёртки функции и т.д.
            2. Я отметил во введении, что эта мысль (фактически в той же форме, что и у Вас) присутствует в книге «Functional Programming for the Real World» — и написал, что мне хотелось именно показать хоть какой-то пример, а не просто голую формулировку.

            Насчёт второго:
            Первая часть поста описывает как раз почему паттерны ООП — это решения уровня проектирования, а выбор парадигмы — решение уровня архитектуры. Есть архитектурные паттерны, например MVC, клиент-сервер и т.д. — они да, весьма мало связаны с целевой парадигмой. Но паттерны ОО проектирования — очевидно, абстракция более низкого уровня.
            Сама суть паттерна «стратегия» — это инкапсуляция функции в класс. Я не вижу класса в моём решении :) Вообще говоря, я думаю, что не надо придавать паттернам какой-то дополнительный смысл — паттерн «стратегия» решает конкретные задачи в рамках ООП.
              0
              Насчет первого:
              Для понимания статьи надо как минимум знать UML, читать C# и F#. Думаю таким людям про паттерны чтото известно и что такое функтор тоже.

              Насчет второго:
              Сама суть паттерна «стратегия» — разделение алгоритма и специфических для разных обьектов реализаций.
              И никак не инкапсуляция функции в класс.

              И если вы заглянете в википедию даже найдете там пример реализации. «Пример с использованием динамических (first-class) функций»
                –1
                ru.wikipedia.org/wiki/Стратегия_(шаблон_проектирования)#.D0.97.D0.B0.D0.B4.D0.B0.D1.87.D0.B0
                  +1
                  Если использовать такую логику, то надо или в каждой статье начинать с правил сложения, или же писать статью про сильное взаимодействие примерно так: «сильное взаимодействие — это сильное взаимодействие».
                  «Читать F#» особо не требуется — я, как мне кажется, даю кое-какие комментарии насчёт того, что значит приведённый код. Так получилось, что в ФП нет аналога UML — поэтому я даю достаточно подробные комментарии и в самом коде.

                  Сорри, крыша немного едет, я имел в виду Command, конечно, когда говорил про инкапсуляцию функции в класс.
                  Но, тем не менее, насчёт стратегии:
                  «Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from clients that use it.» (GoF)
                  Всё же суть — «объявить семейство алгоритмов, инкапсулировать их и сделать взаимозаменимыми».
                  Я думаю, что то, о чёс вы говорите («разделение алгоритма и специфических для разных обьектов реализаций») — это ближе к понятию ad-hoc polymorphism.

                  Я хочу ещё раз заметить: я не занимаюсь реализацией этих паттернов с помощью x. Моя цель — показать, что паттерны, зачастую, не нужны, ибо имитируют нечто, что отсутствовало в большинстве распространённых языков в явном виде на момент создания паттернов. И опять же, я привёл ссылку на книгу Judith Bishop, где она использует механизм делегатов. Есть весьма тонкая грань (но она всё же есть) между реализацией паттерна X с помощью Y для достижения цели Z и между использованием Y для достижения цели Z :)
                    –1
                    Приблизительно то что в GoF я и имел ввиду. Просто непонятно выразился.

                    В том то и дело что «инкапсулировать реализацию алгоритма» — а куда инкапсулировать в класс или функтор — дело десятое. Например в C нету ООП, но паттерн стратегия реализуется.

                    «что отсутствовало в большинстве распространённых языков в явном виде» — вообще то функторы в явном виде существуют в С и в С++.
                    Из всех языков, с которыми я работал их нету только в Java.

                      +2
                      Эм. Мне действительно трудно понять, как можно инкапсулировать 1 в 1. Функция в данном случае — это функция, которая сама по себе значение. Её никуда инкапсулировать не нужно. Сама идея инкапсулировать функцию происходит от того, что она не является в неком языке объектом первого класса.

                      Тем не менее, использовать ссылки на функции, переданные другим функциями — это ой как неприятно (Вы ведь эту технику подразумевали под «функтором в С и С++»?). Насколько я понимаю, этот метод не типобезопасен?
                      Как можно реализовать передачу объекта (!), содержащего функцию, в языке, в котором вообще нет объектов? Я опять хочу заметить, что излишнее обобщение в данном случае не приведёт ни к чему хорошему.
                        0
                        стратегия не есть «инкапсулирование функции», а есть «инкапсулирование конкретной реализации алгоритма».
                        В С — ссылка на функцию. в С++ — перегрузка оператора ().
                        В С — нетипобезопасен, в С++ типобезопасен. Хотя к чему это?

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

                          0
                          Чем «конкретная реализация алгоритма» отличается от функции?
                          убейВсехЧеловековЯдернойБомбой() — «функция» и «конкретная реализация алгоритма».
                          убейВсехЧеловековЧумой() — опять «функция» и «конкретная реализация алгоритма».

                          Заметьте, Вы подменяете методы реализации
                          — передача ссылки на функцию другой функции
                          — перегрузка ()
                          и понятие ФВП паттерном Strategy, который используется только в ОО проектировании. Это разные абсолютно уровни абстракции. Весь паттерн — это, по сути, workaround в ситуации: «нам нужны функции как объекты первого класса для решения задачи, но у нас нет функций как объектов первого класса». Странно представлять само понятие функтора/функции высшего порядка/оператора как «реализацию» паттерна ОО проектирования, Вам не кажется?

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

                          Я думаю, я недостаточно чётко сформулировал цель: моя задача — не реализовывать паттерны, моя задача показать, что некоторые паттерны в некоторых ситуациях не нужны. Поэтому во введении акцент делается именно на том, что паттерны — это не альфа и омега, а просто метод выбора классов задач.
                            –3
                            у вас пробелы в базовых понятиях. подозреваю это изза отсутствия практики. слова курсовая и преподаватель многое обясняют
                              +1
                              )) Я студент 4ого курса и занимаюсь программированием с 12 лет. Если Вы можете привести контраргументы — приведите их, но ссылаться на возраст и «отсутствие практики» — по меньшей мере странно.

                              Самое интересное, что Вы, похоже, не очень поняли то, что написано в главе «Лирическое отступление: разница между архитектурой, проектированием и реализацией». Возможно, я так плохо объясняю, так что советую почитать это.

                              Ну и да, странно слышать про «пробелы в базовых понятиях» от человека, который утверждает, судя по всему, что даже ссылки на функции и те, бедняжки, реализуют паттерн Strategy :)
                                –2
                                ссылаюсь на возраст и отсутствие практики, так как обьяснил довольно просто, а вы не поняли.
                                >странно слышать про «пробелы в базовых понятиях» от человека
                                Мне не надо доказывать мой уровень. Я просто пишу хорошие проекты и они хорошо работают. Можете посмотреть в профиле.
                                  +2
                                  Я посмотрел и мне понравилась Ваша игра, про которую Вы писали пост насчёт AppStore. С удовольствием поиграл, спасибо :)
                                  Но это никак не показывает уровень ваших теоретических знаний, особенно в области функционального программирования.
                                  –3
                                  Вы баловались турбо паскалем и считаете это «занимаюсь программированием»?
                                  Ну… мне было лет 8, батя притянул домой правец и мама мне показывала чето в бейсике даже — сама была программист на PL1. Лет 20 прошло с тех пор…

                                  Но я почемуто считаю, что я занимаюсь программированием всегото 5 лет. Ровно столько сколько решаю реальные задачи, за которые мне платят деньги, за которые я живу.
                                    +1
                                    Вы опытнее меня, да. Ну и что? Вам не кажется, что вы совершаете логическую ошибку?
                                      –2
                                      еще раз повторю. я не говорю «я опытнее потому я прав». Я говорю «я пробую обяснить, вы не понимаете простых вещей, потому больше обяснять не буду так как вижу, что обьяснить не получится. но воспользуюсь случаем и укажу на вашу некомпетентность»
                                        +2
                                        А я говорю: «У Вас неправильные представления об уровнях абстракции и Вы, вместо того, чтобы попытаться понять мои аргументы, занимаетесь демагогией».

                                        Об уровне моей компетентности уж поверьте, судить не Вам :) При всём уважении, мы занимаемся разными вещами. И заметьте, я спокойно пытался объяснить Вам свою позицию, а Вы перешли на личности.
                                0
                                ок. чтоб не быть голословным разжую максимально просто.

                                есть задача — найти человеков и убить.
                                реализация 1:
                                найтиИУбить1
                                {
                                человеки=найтивсехчеловеков()
                                убиваем_каждого_по_очереди_чумой(человеки)
                                }реализация 1:
                                найтиИУбить2
                                {
                                человеки=найтивсехчеловеков()
                                убиваем_каждого_по_очереди_ядом(человеки)
                                }

                                Здесь ЕСТЬ функции. но НЕТ стратегии. ЕСТЬ 2 реализации алгоритма из одного семейства но стратегии НЕТ.

                                теперь стратегия:
                                найтиИУбить(как)
                                {
                                человеки=найтивсехчеловеков()
                                как(человеки)
                                }

                                ЭТО СТРАТЕГИЯ!
                                использование:
                                найтиИУбить(убиваем_каждого_по_очереди_ядом)

                                Да, это ФВП и это стратегия. Но не каждая ФВП — стратегия.

                                Если вы считаете, что патерн стратегия в функциональных языках отстутствует — вперед редактировать вики. Так как там есть пример реализации на функциональном языке.

                                >Странно представлять само понятие функтора/функции высшего порядка/оператора >как «реализацию» паттерна ОО проектирования, Вам не кажется?
                                Странно, а кто так делает?

                                >функтора/функции
                                Вообще функтор и функция разные вещи и через дробь их писать не хорошо

                                  –1
                                  О боже.

                                  «Здесь ЕСТЬ функции. но НЕТ стратегии. ЕСТЬ 2 реализации алгоритма из одного семейства но стратегии НЕТ.»
                                  Вы понимаете, что такое higher-order functions и functions as first-class objects? Здесь нет ни того, ни другого.

                                  «ЭТО СТРАТЕГИЯ!»
                                  Это функция высшего порядка найтиИУбить(), которая реализует поведение характерное для паттерна Strategy. Это не Strategy.
                                  Вот Strategy:
                                  interface СпособУбийства {
                                  void Убить();
                                  }

                                  class УбитьЯдом {
                                  void Убить(){
                                  ...;
                                  }
                                  }

                                  class УбитьЧумой {
                                  void Убить(){
                                  ...;
                                  }
                                  }

                                  void УбитьВсехЧеловеков(СпособУбийства как){ //передаём объект, а не функцию => не ФВП!
                                  ...
                                  как.Убить();
                                  }


                                  «Если вы считаете, что патерн стратегия в функциональных языках отстутствует.»
                                  В чистых функциональных — да. В поддерживающих ООП — Вы можете его реализовать, но зачем?

                                  «Странно, а кто так делает?»
                                  Я так понял, что Вы этим занимаетесь последние несколько постов :)

                                  «Вообще функтор и функция разные вещи и через дробь их писать не хорошо»
                                  Вообще говоря понятие «функтор» имеет много значений. Одно из них — «функция высшего порядка». Не просто функция, а именно функция_высшего_порядка.
                                    +1
                                    * class УбитьЯдом: СпособУбийства
                                    * class УбитьЧумой: СпособУбийства
                                      –1
                                      про очевидные вещи больше спорить не буду.
                                      В русской википедии реализация стратегии на функторах. Без классов для реализации алгоритмов. Вперед редактировать википедию — ссылку я приводил выше.

                                      Теперь про пробелы в ваших знаниях.
                                      Функтор имеет одно значение. Это «функция как обьект». Все. Нет других значений.

                                      >Одно из них — «функция высшего порядка». Не просто функция, а именно >функция_высшего_порядка.
                                      Функция высшего порядка это функция которая принимает функторы как аргумент или возвращает функтор. Все. Никак иначе.
                                      Учите матчасть, потом редактируйте википедию, и дважды думайте перед тем как спорить о том в чем не разбираетесь.

                                        +1
                                        Русская википедия — это тот самый авторитетный источник, по сравнению с которым материалы научных конференций и книги малоизвестного)) издательства O'Reilly ничто.

                                        «Функтор имеет одно значение.»
                                        1. en.wikipedia.org/wiki/Function_object
                                        2. en.wikipedia.org/wiki/Functor
                                        3. en.wikipedia.org/wiki/Map_(higher-order_function)#Generalization
                                        4. en.wikipedia.org/wiki/Function_word
                                        5. caml.inria.fr/pub/docs/manual-ocaml/manual004.html#toc15
                                        Всё ещё в этом уверены?

                                        «Функция высшего порядка это функция которая принимает функторы как аргумент или возвращает функтор. Все. Никак иначе.»
                                        Общепринятое определение приведено в статье:
                                        «Функция высшего порядка – это функция, которая принимает в качестве аргумента или возвращает как результат другую функцию
                                        Оно такое. Открываете любой учебник по ФП и читаете.

                                        Я бы рекомендовал Вам немного выйти из поклонения ООП и почитать хорошие книжки по ФП. И перестать считать себя умнее всех :)
                                          –1
                                          Ну это простите вообще смешно.

                                          ссылка 1. A function object, also called a functor,
                                          ссылка 2. For functors as a synonym of «function objects»
                                          ссылка 3., higher-order functions, functional forms, or functionals are functions which do at least one of the following:
                                          take one or more functions as an input
                                          output a function

                                          итд.

                                          Везде сказано именно то, что я сказал выше. Практически слово в слово.
                                          Конкретно сказано Functor == Function object.

                                          >«Функция высшего порядка это функция которая принимает функторы >как аргумент или возвращает функтор. Все. Никак иначе.»
                                          > «Функция высшего порядка – это функция, которая принимает в >качестве аргумента или возвращает как результат другую функцию.»

                                          Вы че, на самом деле не понимаете, что это написано одно и тоже?? На полном серьезе?
                                            +1
                                            Вы попытайтесь прочитать полностью то, что там написано :) не вырывая словосочетания из контекста.

                                            Я понимаю что это разные вещи. Функция в математике и ФП — это одно и то же. Они по умолчанию являются объектами первого класса (никакой связи с ООП!). Поэтому понятие функтор там чаще всего используется в том же смысле, что и в теории категории.
                                            Вы же говорите про ООП-функторы: т.е. workaround для изображения «функций, как объектов первого класса».

                                            Товарищи, минусующие карму: вы хотя бы высказались, что ли.
                                              –1
                                              еще раз повторюсь — там сказано именно то что сказал я
                                              и нигде не сказано, такого как
                                              > «функтор» имеет много значений
                                              и
                                              >Одно из них — «функция высшего порядка»
                                              Так как фвп не обязательно функтор и функтор не обязательно фвп

                                              >Функция в математике и ФП — это одно и то же.
                                              Ну это извините вобще ни в какие ворота не лезет.

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

                                              Функция в программировании — проименованая(или анонимная) последовательность операций, которая может быть вызвана повторно
                                                +1
                                                «Ну это извините вобще ни в какие ворота не лезет.»
                                                Да что Вы?

                                                «In particular, in a functional language variables are variables: the mathematical concept of variables, which is given meaning by substitution, is precisely the programming concept of variable. It’s not analogous, it’s the same.»
                                                existentialtype.wordpress.com/2011/04/17/some-advice-on-teaching-fp/

                                                «The differential is an operator acting on functions that produces a linear approximation to the function at each point in its domain (if the function in fact has such).»
                                                existentialtype.wordpress.com/2011/04/02/functions-are-values/

                                                Пишет один из крупнейших учёных в теории типов. Сложите эти мысли, переварите их и подумайте.

                                                «Функция в математике — зависимость одной величины от другой.
                                                Функция в программировании — проименованая(или анонимная) последовательность операций, которая может быть вызвана повторно»
                                                Вы не понимаете разницы между понятием функции в ФП и в императивном программировании.
                                                То, что Вы считаете «функцией в программировании» — это «функция в императивном программировании». Функция в ФП- это сущность, принимающая нечто и возвращающая нечто. Отображение между двумя множествами. Именно поэтому мы так трясёмся с immutable data structures. Они гарантируют чистоту функций, отсутствие сайд-эффектов. И если функция чистая — мы получаем именно ту самую сущность, которая однозначно отображает одно множество в другое. Почитайте:
                                                en.wikipedia.org/wiki/Side_effect_(computer_science)
                                                en.wikipedia.org/wiki/Pure_function

                                                Я говорю в другой парадигме, поймите же. И да, как раз Ваш опыт может играть с Вами злую шутку: ибо понимание всего этого требует серьёзной ломки стереотипов.

                                                «Так как фвп не обязательно функтор и функтор не обязательно фвп»
                                                Я этого нигде не утверждал.
                                                Вы знаете английский?
                                                  +2
                                                  Вообще говоря, если Вам интересно понять в чём различия, я с удовольствием пообщаюсь с Вами в личке. Это действительно очень объёмная тема. Я извиняюсь, что ввёл Вас в заблуждение не указав явно, что я использую отличную от Вашей терминологию.
                                                    0
                                                    Если хотите я кину в личку скайп и поговорим голосом- будет в разы быстрее.
                                                      +1
                                                      Я не могу пользоваться скайпом, к сожалению, я сменил звуковуху и теперь мои наушники к ней не подходят(
                                                      Вы есть на вконтакте? В крайнем случае можно использовать хабрапочту :)
                                                      И да, мне пора уходить, так что я, вероятно, не буду отвечать ближайшие 10 часов.
                                                    –1
                                                    разницу между словами function и variable вы видимо не признаете.

                                                    >Я этого нигде не утверждал.
                                                    Утверждали, цитирую:
                                                    >«функтор» имеет много значений. Одно из них — «функция высшего порядка»

                                                    Это все класно. Сущность… нечто… Только от проблемка одна. Программирование это чисто прикладная дисциплина. И вся теория придумана для того, чтоб писать программы проще и еффективнее. А так как центральный процессор не оперирует понятиями «сущность» и «нечто» то функции и получаються последовательностями комманд.
                                                    И в C# и в F#.
                                                    И перестаньте мне кидать линки на то, что я итак знаю.

                                                    А вы, хоть знаете, откуда пошел весь сыр бор про ФП??? Какую проблему ФП должно бы решить? В чем фишка того, что функция чистая??

                                                    Английский я знаю.
                                                      +1
                                                      ">«Так как фвп не обязательно функтор и функтор не обязательно фвп»
                                                      >Я этого нигде не утверждал.

                                                      >>Утверждали, цитирую:
                                                      >>>«функтор» имеет много значений. Одно из них — >>«функция высшего порядка»"
                                                      Окей, формально моё высказывание:
                                                      "∃ значение слова функтор ≡ ФВП"
                                                      Вы отрицаете высказывание:
                                                      "∀ значение слова функтор ≡ ФВП"

                                                      «И вся теория придумана для того, чтоб писать программы проще и еффективнее.»
                                                      Да. Вы считаете, что проще написать 5 строчек или 15?
                                                      Безусловно функции в конечном счёте преобразуются в последовательность команд. Только я говорю о проектировании и архитектуре, и меня в данном контексте не интересуют машинные команды. Вы вот тоже понятиями «функтор» и «объект» оперируете. Сомневаюсь, что ими оперирует процессор.

                                                      Вообще-то знаю. Почему хорошо, что функция чистая — как раз в одном из тех линков, которые вы «знаете».

                                                      Можно задать несколько вопросов?
                                                      — Какие языки ФП Вы знаете? Как долго Вы занимались ФП?
                                                      — Почему Вы постоянно отрицаете то, что знаете? Ибо в тех ссылках, которые я вам кидал, слова противоположные Вашим. Dissociative identity disorder?
                                                      — Вы прочитали мой пост полностью или пробежали его по диагонали, думая что Вы уже всё это знаете?
                                                        –1
                                                        >— Какие языки ФП Вы знаете? Как долго Вы >занимались ФП?
                                                        Ни одного. Не занимался ФП вообще.

                                                        Встречный вопрос
                                                        -Как долго вы занимались программирование вообще.

                                                        Ответ то я знаю. Вообще не занимались.

                                                        >слова противоположные Вашим.
                                                        приведите слова противоположные моим из этих линков.
                                                          0
                                                          «Ни одного. Не занимался ФП вообще.»
                                                          Я занимаюсь им и соответствующими разделами математики последние 1,5 года. Я не гуру ни в коем разе, но.

                                                          «Ответ то я знаю. Вообще не занимались.»
                                                          Poor me.

                                                          «приведите слова противоположные моим из этих линков.»
                                                          Например, почитайте ссылки, которые я Вам привёл касательно функторов)) Внимательно)

                                                          Итак, мне пора спать :) Продолжим этот разговор позже в личке, если желаете.
                                                          –1
                                                          Но всетаки хочется услышать — какие прикладные проблеммы решает ФП и чистые функции? Ваш вариант.
                                                          Подсказка — это НЕ упрощение паттерна стратегия на 3 строчки кода.
                                                            +1
                                                            Облегчение параллелизации ПО, например. Очень непрактичная вещь, правда ведь?)
                                                              +1
                                                              И да, забавно, что Вы так глубоко разобрались в ФП, даже к нему не прикасаясь. Вот бы мне так :)
                                                                0
                                                                Забавно что вы разобрались в программировании вообще к нему не прикасаясь.

                                                                У нас просто критерии разные. Я не написал ни одной программмы на ФЯП которая пошла в продакшен. Потому я считаю, что я НЕ занимаюсь ФП вообще.

                                                                Вы чтото читали про ФП и (ВАУ) написали курсовую и считаете что «занимаетесь» им 1.5 года.

                                                                вот и вся разница.
                                                                  –1
                                                                  Ну я, к примеру, написал небольшой язык программирования на F#, ради интереса. Ещё что-то там было. Естественно, это не могло пойти в продакшен, потому что нафиг никому не надо :)

                                                                  Тем не менее, мне тут «программисты», которые вполне много чего-то там выпускают и делают для заказчиков, кидают мне код с параллельными массивами. Ну я ж не написал тыщу ПХПстраничек и 200 флеш-игр, так что куда им слушать меня, убогого, вопиющего, что так никто не делает с 60ых?

                                                                  Я писал про аргументум ад хоминем. Вы не вняли. Извините, я умею спорить только опираясь на логику :)

                                                                  Я думаю, конструктива тут больше не будет, так что пора завязывать. И спать, наконец. Мир, дружба, чистые функции и машинные инструкции? :)
                                                                    –1
                                                                    логика:
                                                                    1.все парадигмы программирования для упрощения решения прикладных задач.
                                                                    2. вы не решили ни одной прикладной задачи.
                                                                    следствие:
                                                                    придумайте сами. мне кажется все итак ясно
                                                                      +1
                                                                      Т.е. книгу, скажем, указанной J. Bishop мне выкинуть? Ну вот не решила, бедняжка, ни одной практической задачи. И вообще _все_ книги и статьи мне выкинуть, кроме «я вот тут решил создать игрушку, вот вам топик с её кодом: ...»?

                                                                      Вообще, теория не имеет право на существование, да?)
                                                                        –1
                                                                        да кто ж говорит что книгу выкинуть. Я говорю что вы книгу не поняли.
                                                                        Что и доказали в коментариях выше. Когда я формулировал определение по своему, но абсолютно правильно, а вы «опровергали» меня определением из книги, которое отличается немногим более чем порядком слов.
                                                                          +1
                                                                          Вы постоянно путали термины и понятия и утверждали, что я (и весь остальной мир) реализовывал паттерн Strategy.
                                                                          Правда, будьте ласка, почитайте что-нибудь по логике, что ли и по лингвистике ^_^
                                                                            –1
                                                                            ссылку или цитату, где я попутал термины в студию. ^_^
                                                                              +1
                                                                              Первое попавшееся:
                                                                              код озаглавленный — «ЭТО СТРАТЕГИЯ!»
                                                                              ^_^
                                                            –2
                                                            понятиями функтор и обьек оперирует ЯП. А понятиями «сущность и „нечто“ не оперирует никто.

                                                            >не интересуют машинные команды
                                                            меня тоже. разговор был про команды — операторы и конструкции языка программирования.

                                                            >»∃ значение слова функтор ≡ ФВП"
                                                            > Вы отрицаете высказывание:
                                                            > "∀ значение слова функтор ≡ ФВП"
                                                            Понимаю. Тяжело признавать свою неправоту. От только вы сказали такой бред вроде
                                                            «одно из значений слова существо — паук тарантул».
                                                            да. паук тоже существо. никто ж не спорит.

                                                              +1
                                                              «А понятиями «сущность и „нечто“ не оперирует никто.»
                                                              Наука есть такая. Философия. И да, ещё одна. Математика. А ещё есть ER-диаграммы. И анализ предметной области. Печаль им.

                                                              «От только вы сказали такой бред вроде»
                                                              Я указал Вам на то, что Вы допускаете ещё одну логическую ошибку, самую частую, кстати. Вы путаете кванторы. Ах да. Кванторы не решили практической задачи, нафиг кванторы.

                                                              Кстати, а какую практическую задачу решили Вы, всеми этими комментариями? :)
                                                                +1
                                                                Может действительно, займитесь философией. Там код писать не надо. И работать ничего не должно. Ладно. На этом разрешите откланятся. Жизнь расставит все на свои места. Вас же жизнь поставит на место на первом же собеседовании на должность джуниор девелопера.
                                                                  +3
                                                                  признайтесь честно, вам обоим просто не спалось))
                                                                    +4
                                                                    image
                                                                    –2
                                                                    А кванторы попутали вы, так как утверждение
                                                                    ∃ функтор ≡ ФВП
                                                                    однозначно верно, но утверждение
                                                                    ∃ значение слова функтор ≡ ФВП
                                                                    однозначно ложно.
                                                                    Или вы просто не понимаете слова «значение».
                                                                    Опять на простом примере
                                                                    «Термин язык программирования имеет много значений — одно из них ассемблер».

                                                                      0
                                                                      2mokus,
                                                                      А я люблю его писать, видите, какое трагическое противоречие. И когда у тех самых «практиков» возникают проблемы, они бегут ко мне. Ангст.

                                                                      «Вас же жизнь поставит на место на первом же собеседовании на должность джуниор девелопера.» — посмотрим :) Когда-нибудь я Вам сообщу о результатах :)

                                                                      «Так как фвп не обязательно функтор и функтор не обязательно фвп»
                                                                      Перечитайте 15 раз, пожалуйста.
                                                                      Её богу, если я Вам сейчас начну пересказывать курс мат. логики в комментариях, это будет странно :)

                                                                      2Meroving,
                                                                      ^_____^
                                                        0
                                                        Функтор — это придуманный способ обмана, но для ФП функтор — марихуана
                                                    +1
                                                    Если вы будете везде, где достаточно передать функцию, строить классическую схему построение патернов, то вы утонете в коде раньше чем решите задачу. GAF-ы пишут именно об этом, когда говорят, что люди отказываются от использования патернов.

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

                                                    Взгляните на передачу функции в качестве аргументов под углом достаточности и вы поймете, что mokus прав
                                                  0
                                                  Вы спорите о словах: называть паттерном реализацию без класса или не называть. По-моему тут важнее возможность построения изоморфизма: если возможно построить изоморфизм с описанием паттерна — то это тот же паттерн, иначе — нет.
                                                  В этом случае легко понять, что предложенные подходы на основе функций являются одними из возможных реализаций паттернов.
                                                    0
                                                    Чем «конкретная реализация алгоритма» отличается от функции?


                                                    Функция — это абстракция над алгоритмом. Функция инкапсулирует его. Если там где вызывается функция ввести её тело без «обвязки» (но с соответствующими изменениями, чтобы, например, избежать конфликтов имён), то результат работы алгоритма не изменится (и даже будет получен быстрее — не будут тратиться ресурсы на вызов функции, хотя если в программе функция вызывается в разных местах и в каждом заменить вызов на тело, то размер кода увеличится, а поддержка его превратится в ад).
                                                    моя задача — не реализовывать паттерны, моя задача показать, что некоторые паттерны в некоторых ситуациях не нужны.

                                                    Вы реализуете паттерн путем выделения алгоритма в функцию :)

                                                    Не смотря на некоторые заблуждения всё равно спасибо за статью, появились мысли для чего можно использовать элементы ФП в PHP.
                                                      +1
                                                      Дело в том, что мы по разному определяем исходные понятия :) Я подразумеваю под функцией нечто оторванное от физической реализации в принципе. Когда Вам говорят о функции синуса, вы же не представляете это как ряд шагов, которые реализуют, например, подсчёт суммы соответствующего разложения в ряд? Точно так же паттерны говорят о том, как организовать объекты так, чтобы достичь некоторых свойств системы. Т.е. в случае функции в ФП мы абстрагируемся от её реализации, а в случае паттернов в ООП — мы абстрагируемся от, скажем, конкретной реализации объектов в языке или системы наследования (ну в js, например), но всё же от самого понятия объекта мы абстрагироваться не можем.
                                                      Поэтому я всё же, если говорить строго, показываю, что один из приёмов ФП можно использовать для того, чтобы достичь тех свойств системы, которые обычно достигаются путём использования паттерна.
                                                      Паттерн — это метод достижения определённой цели, ФВП — тоже метод достижения определённой цели, цели иногда отличаются, иногда совпадают, но это просто параллельные миры на одном уровне абстракции :)
                                                      Вот как можно кратко сформулировать всё то, о чём мы спорили с mokus :)

                                                        +1
                                                        * И да, пожалуйста :)
                                                          0
                                                          Точно так же паттерны говорят о том, как организовать объекты так, чтобы достичь некоторых свойств системы.

                                                          Не согласен. Паттерны в моём понимании — это выражение задачи и типичного способа её решения. Например, задача стратегии это выбор алгоритма динамически. Типичный способ решение — отделение логики выбора от логики собственно алгоритма. Будет логика выбора реализована через наследование или через ФВП — это уже летали реализации. Но это мое понимание, на академическую строгость не претендую.

                                                    0
                                                    Как можно реализовать передачу объекта (!), содержащего функцию, в языке, в котором вообще нет объектов?


                                                    Вообще говоря, объект — это сущность, имеющая состояние и поведение, атрибуты и методы. Реализовать его можно хоть на ассемблере в виде, например структуры данных с общим базовым адресом и доступом к данным и адресам функций по смещению к базовому адресу. Различные obj = new SomeClass; obj.attr = 1; obj.method() — это лишь синтаксический сахар, ведь программа хоть на Си, хоть на Хаскеле в итоге сводится даже не к ассемблеру, а к машинному коду.
                                                      +1
                                                      «ведь программа хоть на Си, хоть на Хаскеле в итоге сводится даже не к ассемблеру, а к машинному коду.» — безусловно. Но мы на уровень выше этого :)
                                                      Я приведу контрпример: фраза хоть на китайском, хоть на русском в итоге сводится к одному и тому же смыслу, который понимает и китаец, и русский. Тем не менее, хотя языки позволяют выражать одно и то же, в китайской грамматике есть такие вещи, как, например, счётные слова, которые не имеют аналога в русском. А в русском есть падежи, которых, очевидно, нет в китайском. У нас та же ситуация :) Мы говорим про правильные грамматические конструкции для выражения смысла: и т.к. языки разные, грамматические конструкции меняются :)
                                                        +1
                                                        Уверен, что есть такие понятия, которые можно понять только будучи с самого рождения воспитанным в определенной среде, даже если язык один. :)
                                                          0
                                                          Ситуация аналогичная :) Тут ещё всё от устройства мозгов зависит. Кому-то удобно представлять задачу как набор чётко определённых для себя паттернов, кому-то — как набор процессов, кому-то — как потоки данных, ну и т.д. :)
                                            0
                                            > паттерны это архитектурные решения и они не привязаны к конкретной парадигме.

                                            Вы ошибаетесь. Паттерны привязаны не только к парадигме, они даже от языка зависят (в рамках одной парадигмы). Некоторые паттерны языка C++, например, бессмысленны в SmallTalk.
                                              0
                                              Паттерны это просто стандартные решения стандартных проблем. Они могут быть мультипарадигменными и могут быть очень частными. Я имел ввиду именно указаные в статье — стратегия и комманда.
                                                0
                                                mokus говорит истину.
                                            0
                                            >Паттерны Command и Strategy — это ограниченная реализация функций высшего порядка
                                            категорически не согласен с такой формулировкой.

                                            Мой вариант: В функциональных языках паттерны Command и Strategy реализуются с помощью ФВП.
                                              +2
                                              Ну, это нечто вроде спора, что первично: курица или яйцо. Я действительно не думаю, что никому из GoF не были известны ФВП — а учитывая, что Lisp появился несколько раньше, чем ООП… Хотя, в любом случае, как кто-то говорил, паттерны возникают сами — и Command, и Strategy переоткрывались и теми, кто понятия не имел про ФВП. В общем, я считаю, что и Ваша, и моя формулировка правильны и, фактически, эквиваленты.
                                                0
                                                См. выше.
                                                  0
                                                  Здесь лучше подходит не «курица и яйцо», а «кто первый встал — того и тапки» или «в чужой монастырь со своим уставом не ходят».
                                                +3
                                                Уж скоро 20 лет как GoF вышел, а люди все никак не успокоятся.
                                                Почему никак нельзя принять факт что для каждой парадигмы есть свое направления движения и свой _правильный_ подход по интерпретации и реализации какой либо сущности.
                                                Почему нельзя отойти от умных книжек и википедий и решить что функция это просто некая сущность переносящая логику. И без разницы как оно это делает и чем в каком либо языке по факту является.
                                                Есть много уровней абстракций и точек обзора. И программа написанная на C\C++\C#\F#\Prolog может идентично отображаться в любой реализации, но не коррелировать со своим описание на UML\SDL и других блокнотиках. Детали имплементации понимаешь.
                                                Может еще на уровне логики, поведения или битиков в памяти однозначно реализовывать какой либо патерн, но на жестком и не праведном уровне кода быть чем-то иным?
                                                  0
                                                  «Гипотеза заключалась в том, что паттерны — это устоявшиеся решения определённых проблем, а раз возникают проблемы и их устоявшиеся решения, видимо есть некие слабости и недостатки, которые приходиться преодолевать. Для рассмотренных паттернов это действительно так.»
                                                  Занятные у вас гипотезы; главное, очень актуальные.

                                                  Скажите, а вас не смущает, что ваша «гипотеза» озвучивается как данность на любом вменяемом архитектурном семинаре (я вот ее встречал у Казмана, что в книге, что на семинарах)?
                                                    0
                                                    Гипотеза для выбора классов задач, заметьте :)
                                                    +2
                                                    И второе.

                                                    Анализируя паттерн «стратегия», вы сразу берете его реализацию для объектно-ориентированных языков. И потом успешно ее разносите, показывая «какой неудачный паттерн, он придуман потому что ООЯ ущербны». Но.

                                                    Паттерн «стратегия» — это всего лишь прием, позволяющий поменять поведение алгоритма, передав в него другой алгоритм. И мне наплевать, реализован он в рамках ООП, ФП, ООП-с-делегатами или еще как-то. Мне важно только то, что с точки зрения поведения это «стратегия».

                                                    В частности, в том же (насквозь ОО) c# стратегии уже давно можно реализовывать с помощью Func{Of T,T1,T2...}. Мне плевать, что внутри платформа сделает из этого класс — мне важно только то, что для меня оно ведет себя как функция. Именно в этом красота паттерна — он абстрагирует меня от конкретики.

                                                    (С другой стороны, стратегия может быть настолько сложна, что реализовать ее в одной функции — сложно. И тут тем более выгодно работать с объектом, потому что он позволяет как угодно декомпоновать нужное мне поведение.)
                                                      –1
                                                      :-) Фактически, уважаемые спорщики говорят об одном и том же разными словами и терминами, имея свое субъективное мнение об их назначении.
                                                      Легко убедиться, что они хорошо владеют терминологией, пусть с небольшими погрешностями в понимании.
                                                      Проблема состоит в стыковке: если одинаковые понятия имеют разные формулировки, бывает довольно сложно понять, что это одно и то же.
                                                        –2
                                                        Собственно для того, чтобы избежать этого, я и привёл исследование, рассказывающее, почему же я так смело утверждаю, что к чему относится и кто кого реализует :) Но, похоже, никто не удосужился…
                                                        Короче говоря, мне надоело спорить на эту тему. Если Вы так хотите воспринимать это как реализацию паттерна — пожалуйста :) Кому-то моя статья сэкономит пару строк кода, а кого-то познакомит с весьма важными понятиями. Это уже очень много.
                                                        –1
                                                        Вы повторили то, что я пытался доказать автору целую ночь :)
                                                        От себя добавлю, что например в AS3 в отличие от C# функция даже при компиляции не будет запакована в класс.
                                                          0
                                                          «От себя добавлю, что например в AS3 в отличие от C# функция даже при компиляции не будет запакована в класс.»
                                                          Так пофиг же! На паттерн это не влияет.
                                                            0
                                                            Пофиг. Согласен на все 100. Уточнил чтоб никто не доколупывался со словами «а на самом деле оно после компиляции всеравно класс»
                                                        +1
                                                        Норвиг в 1996 году рассматривал паттерны в Lisp и Dylan. Собственно, результат аналогичный (многие паттерны становятся тривиальными или существенно упрощаются), но на более богатом материале.
                                                          0
                                                          О. Вот за это спасибо огромное! Будем просвещаться.
                                                          0
                                                          У меня вопрос такой: можно ли данную парадигму ФВП как-нибудь представить в UML? Возможно ли представить, скажем, процедурно написанный код на обычном Си в UML, где есть только функции, классы не применялись? Если да, то как, подскажите, может есть пример для этого?
                                                            0
                                                            Для конкретной задачи практически всегда можно создать некую структуру из классов, которая будет отражать тот или иной аспект применения функций высших порядков — и изобразить её на UML-диаграмме. Но сам концепт представить сложно в таком виде, разве что нарисовать компилятор для функционального языка :) UML, всё же, язык объектного моделирования :)
                                                            Были попытки разработать графический язык для функционального программирования, например, тут, но, на мой взгляд, неудачные и не имеющие смысла. Тут ситуация аналогичная блок-схемам — с появлением структурного программирования они потеряли смысл, ибо сами языки были нагляднее, чем представление алгоритма в блок-схеме.
                                                            И ещё, процедурное программирование и функциональное — две большие разницы. Функциональное представляет функции как значения, за счёт этого Вы можете представить списки функций, композицию функций и прочие подобные вещи. И вообще говоря, Вы представляете решение задачи как последовательное применение функций, по сути — Вы описываете, что хотите получить.
                                                            В процедурном программировании Вы как раз представляете решение задачи как последовательность шагов, вся идея заключается в изменении состояний памяти, значений переменных и прочее.
                                                            UML же отражает сущности из другой области — он представляет классы, интерфейсы, отношения между ними — в чистом функциональном или в обычном процедурном (хотя ООП является потомком процедурного программирования) программировании этого всего нет. ООП изображает программу как передачу сообщений между объектами — это просто другая точка зрения, взгляд с другого угла на проблему.
                                                            Поэтому использовать UML и для процедурного, и для функционального программирования бессмысленно :)
                                                              0
                                                              Спасибо за ответ! Погуглил, есть такой ДРАКОН (Дружелюбный Русский Алгоритмический язык, Который Обеспечивает Наглядность) (ссылку не могу дать, карму мою сегодня поглотили ))), может он подойдет? =)

                                                              А по написанному, с Вами согласен, Я просто использовал у себя диаграммы процессов, dfd- и erd — диаграммы, а тут пришло время писать отчет — подумал заморочиться…
                                                                0
                                                                ДРАКОН — те же блок-схемы, вид сбоку. Я про него слышал краем уха, но он предназначен, насколько я понял, для такого традиционного структурного программирования. И он сам вроде бы язык, только визуальный :)
                                                                У меня был опыт работы с Max/MSP — тоже визуальный язык, но объектный и для работы с аудио и MIDI. С тех пор если есть выбор, писать или рисовать, я предпочитаю писать :)
                                                                DFD и ERD — это совсем другая история, они да, нужные и полезные :)

                                                          Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                                          Самое читаемое