Здравствуйте, Воронков Василий, Вы писали:
ВВ>И никакого отличия между ней и классом нет, да?
С обьектом
Класс — это всё же тип, а не экземпляр.
Построим простенький класс:
public class LinearTransform
{
private double _k;
private double _b;
public Vector(double k, double b) { _k = k; _b = b}
publuc double Transform(double x) { return _k*x+_b;}
}
Он у нас получился immutable. Поэтому его крайне легко превратить в функцию (пишу на псевдокоде)
function LinearTransform(k, b)
{
return function(x)
{
return k*x+b;
}
}
Вот, собствено, замкнули. Вся разница — в том, что не нужно руками замыкать результат на параметры конструктора.
Та функция, которая связана с данными — наш анонимный аналог метода Transform — играет роль объекта.
А классом здесь выступает функция-генератор, LinearTransform.
Если бы мы развивали тему дальше в рамках ООП, то у нас бы возник ITransform с методом double Transform(double x), который бы реализовывали все, кому не лень. Ну, или (если учиться по старым книжкам), class TransformBase с аналогичным методом, и целая иерархия перегрузок. А в рамках ФП нам достаточно иметь тип x -> x, чтобы бесплатно получить возможность подставлять туда всё, что угодно — хоть результат вызова LinearTransform, хоть вручную сконструированное замыкание, хоть константу.
ВВ>>> В ООП у тебя функции привязаны к структурам данных всегда.
ВВ>Твоя позиция, видимо, сводится к тому, что программирование в "функциональном стиле" ООП никак не противоречит. Но "функциональный стиль", который уверенно насаждается в последних версиях того же Шарпа, это не ФП. Полноценно писать в ФП на Шарпе практически невозможно. Причем мешать будут всякие "мелочи". Например, у тебя объявления типов функций через Func<>, которые к тому же не выводятся, будут просто в километр длиной.
Есть подозрение, что это не из-за несоместимости моделей.
ВВ>Может, касательно "соединения функция и данных" ты меня тоже как-то превратно понимаешь? Ибо я не въезжаю, как можно сравнивать каррированную функцию с классом в ООП.
Пример выше, скорее всего, поясняет смысл сравнения каррированной функции с классом.
ВВ>А *что* делает их несовместимыми я уже писал и повторял раз надцать — ООП приводит к тому, что программирование строится на инкапсуляции побочных эффектов, ФП напротив стремится избежать этого. Побочные эффекты есть, конечно, и там, и там. Но последовательный дизайн программы в ООП стиле противоречит ФП стилю — они идут в разные стороны. Программа не может быть одновременно ООП и ФП. А прикрутить сбоку пару функциональных фишек к ООП-ной программе конечно можно без проблем.
Интересное замечание. Программа — это такая штука, которую каждый понимает по-своему. Вот в Паскале было хорошо: там программа начиналась с ключевого слова program, и всё сразу понятно. А тут один под программой понимает какое-нибудь "решето Эратосфена", а другой — поисковую машину Гугла. Это я к тому, что насчёт решета я с тобой легко соглашусь, а вот насчёт поисковой машины — как-то непонятно. Не вижу, почему бы "программе" не быть в одном углу объектно-ориентированной, а в другом — функциональной.
ВВ>Я тебе уже говорил — покажи мне совместимый с ФП ООП дизайн. Дизайн, понимаешь? Ты в ответ написал одно слово — linq. Что linq?
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Воронков Василий, Вы писали:
ВВ>Ну это можно вполне успешно сэмитировать без прямой поддержки в языке. Хоть на указателях, как в Си, хоть на классах, как в Джава.
У меня deja vu. Не напомнишь, как имитировать ФВП в чистом С?
Там же нет функторов, так что скрытым параметром замкнутые данные не передашь.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
S>Здравствуйте, Воронков Василий, Вы писали:
ВВ>>Ну это можно вполне успешно сэмитировать без прямой поддержки в языке. Хоть на указателях, как в Си, хоть на классах, как в Джава. S>У меня deja vu. Не напомнишь, как имитировать ФВП в чистом С? S>Там же нет функторов, так что скрытым параметром замкнутые данные не передашь.
А зачем именно скрытым?
Я не знаток "C", но думаю что можно вместо функтора передавать адрес стурктуры, где первым полем идет указатель на функцию, далее замыкаемые данные. Вызывающий должен первым параметром в метод подавать адрес структуры. Как-то так:
struct IntFunctor;
typedef IntFunctor* fptr;
struct IntFunctor
{
int (*f)(fptr, int);
};
struct ConcreteFunctor
{
IntFunctor functor;
int x;
};
Здравствуйте, Mr.Cat, Вы писали:
KO>>Учитывая, что процессы эрланга это, по сути, те же объекты, сам факт критики ООП выглядит неадекватно. MC>Вообще, системы с объектоподобными агентами тот же Танненбаум отделял от ООП в отдельную категорию (у него "object-based" vs. "object-oriented"). Но если уж проводить параллели эрланга с ООП — надо обязательно вспомнить о его параметризованных модулях.
Не надо. Экземпляр параметризованного модуля не содержит мутабельного состояния, не имеет "идентити", и объектом не является. Соответственно — модуль это абстрактный тип данных, но не класс объектов.
Из встроенных штуковин — определению объекта в эрланге удовлетворяет только процесс.
Здравствуйте, k.o., Вы писали:
S>>Скорее всего баян, но эта статья кажется мне более адекватной.
KO>Учитывая, что процессы эрланга это, по сути, те же объекты, сам факт критики ООП выглядит неадекватно.
Ага. На эту тему мы как-то сцеплись с Джо в эрланговском мейллисте. Процессы эрланга один в один являются объектами Smalltalk 72. Просто одно и то же, без всяких натяжек.
Здравствуйте, samius, Вы писали:
S>А зачем именно скрытым?
S>Я не знаток "C", но думаю что можно вместо функтора передавать адрес стурктуры, где первым полем идет указатель на функцию, далее замыкаемые данные. Вызывающий должен первым параметром в метод подавать адрес структуры. Как-то так:
Скрытым — затем, чтобы избежать разбегания сигнатур.
Вот, допустим, пишу я алгоритм, который принимает в качестве callback функцию трансформации координат, (x, y) -> (x', y').
Интуитивно ожидаю получить в качестве сигнатуры что-то типа
Point (*Transform)(Point)
А на деле что? Вместо этого у меня transform превращается в структуру, да ещё и такую, которую я вынужден использовать вот так:
То есть это ещё хуже, чем ручная реализация замыкания на "ООП", как в моём примере. Потому как мы сначала эмулируем ООП, а потом на этой эмуляции ООП эмулируем замыкание.
И это всё ещё нифига не функции высшего порядка.
Реализация в этой идеологии чего-нибудь простого, типа fold, я так понимаю, будет довольно-таки весёлым упражнением.
И ах, да — у нас же здесь будет гарантия неоптимизируемости исполняемого кода: сплошные косвенные вызовы, без информации о типах, на основе которой компиляторы спекулируют...
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
S>Здравствуйте, samius, Вы писали:
S>>А зачем именно скрытым?
S>А на деле что? Вместо этого у меня transform превращается в структуру, да ещё и такую, которую я вынужден использовать вот так: S>
S>То есть это ещё хуже, чем ручная реализация замыкания на "ООП", как в моём примере. Потому как мы сначала эмулируем ООП, а потом на этой эмуляции ООП эмулируем замыкание.
Конечно хуже. Лучше не может быть по определению.
S>И это всё ещё нифига не функции высшего порядка. S>Реализация в этой идеологии чего-нибудь простого, типа fold, я так понимаю, будет довольно-таки весёлым упражнением.
Не сомневаюсь.
S>И ах, да — у нас же здесь будет гарантия неоптимизируемости исполняемого кода: сплошные косвенные вызовы, без информации о типах, на основе которой компиляторы спекулируют...
На деле получилось криво, медленно и неудобно. Но вполне возможно.
Здравствуйте, samius, Вы писали:
S>На деле получилось криво, медленно и неудобно. Но вполне возможно.
Возможно примерно также как встретить динозавра по дороге на работу.
Если за столько времени никто ниче подобного не сделал, то и не сделает никогда. Поэтому можно считать такое невозможным.
А про теоретическую возможность спорить и не надо, у нас все языки полны по тьюрингу и то что умеет делать один теоретически умеет и другой.
Здравствуйте, gandjustas, Вы писали:
G>Здравствуйте, samius, Вы писали:
S>>На деле получилось криво, медленно и неудобно. Но вполне возможно. G>Возможно примерно также как встретить динозавра по дороге на работу.
G>Если за столько времени никто ниче подобного не сделал, то и не сделает никогда. Поэтому можно считать такое невозможным.
Здравствуйте, samius, Вы писали:
S>Здравствуйте, gandjustas, Вы писали:
G>>Здравствуйте, samius, Вы писали:
S>>>На деле получилось криво, медленно и неудобно. Но вполне возможно. G>>Возможно примерно также как встретить динозавра по дороге на работу.
G>>Если за столько времени никто ниче подобного не сделал, то и не сделает никогда. Поэтому можно считать такое невозможным.
S>Точно известно, что никто подобного не делал?
Здравствуйте, Klapaucius, Вы писали:
K>По-моему, парадигма — это базис, в котором другая парадигма может быть выражена как набор паттернов. Так что это отношение ФП-ООП и в обратную сторону работать будет.
Это почти верно, только не для парадигм, а языков, поддерживающих ту или иную парадигму.
Парадигма программирования — это методология + наработанные практики.
FR>>>Во всех, неизолированное изменяемое состояние — зло.
T>>Фанат ?
FR>Нет, и фраза выше справедлива и для императивных языков.
Дык,в ООП изменяемое состояние изолируется(инкапсулируется) в объекте.Поскольку ООП появилось как
надстройка над императивным языком,то можно сказать,что изоляция изменяемого состояния-одна из проблем,которую решает ООП в императивных языках.
Про вред употребления глобальных (PUBLIC)переменных — открытого изменяемого состояния,знаю не понаслышке.Доводилось разгребать кучу кода.Впрочем,инкапсуляции в закрытых переменных модуля вполне достаточно во многих случаях.В принципе модуль можно рассматривать как одиночный экземпляр класса(объект).И во многих случаях этого экземпляра достаточно.
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Авторов, использующих такую аргументацию, читать не стоит.
Если это единственная оплошность авторов, то можно считать их труд успешным.
Здравствуйте, Skynin, Вы писали:
S>Дык не понял — какой именно король голый, если нет разницы? Обое тогда голые.
ООП в свое время преподносился как парадигма, повышающая продуктивность разработчиков по сравнению с процедурной.
Здравствуйте, Gaperton, Вы писали: G>Экземпляр параметризованного модуля ... не имеет "идентити", и объектом не является.
Почему не имеет? Не помню точно, как это реализовано в эрланге, но мы бы могли считать идентичными экземпляры модулей, созданные с идентичными параметрами.