Здравствуйте, AlexCab, Вы писали:
AC>Думал ключевым отличием ИП от ФП именно в подходе к решению задачи: AC>ИП — последовательность операций над данными, ФП — "прохождение" данных через функции. AC>А процедур от функций, в способе вызова и способе передачи аргументов: AC>Процедуры — вызов как одна из операций в последовательности операций, данные предаются и возвращаются в/из процедуры через те же аргументы(параметры). AC>Функция — вызов при "поступлении" данных, данные предаются в функцию только через аргументы, возвращаются только через "возвращаемое значение". AC>А уж насколько процедура/функция "изолирована" дело второе, я не прав?
Не прав. Как раз детали передачи данных — дело второе. Главное как раз наличие или отсутствие побочных эффектов. В этом суть. Общая идя может быть описана так:
1. ИП — деструктивное изменение данных.
2. ФП — преобразование (с копированием) данных.
ФП даен некоторые гарантии надежности. По этому оно и имеет преимущество. Но то самое копирование является недостатком с точки зрения производительности.
Наличие гарантий дает просто для оптимизаций. Во многих случаях ФП код можно сделать более быстрым устранив копирование. По сути это преобразует ФП-кад в ИП-код, но так как это делает автомат (компилятор), то ошибок быть не может. Жаль только что хороших оптимизаторов для ФЯ пока что не много. Да и не во всех случаях можно оптимизировать код. Так что, в общем, ИП позволяет добиваться большей производительности.
AC>И второй вопрос(как к человеку разбирающемуся), допустим нам необходимо чтобы некоторое значение было известно везде в программе(например, ИД пользователя), традиционно это решается при помощи глобальной переменной, как это решается в чистом ФП?
Никак. Для чистого ФП нужно все данные передавать в качестве параметров. Если данные неизменяемые их можно сделать глобальными, но изменяемые — нет.
Решением проблемы является передача сложных структур данных или смешивание ИП и ФП.
Скажу по секрету, что даже самый пуриски-чистый ФЯ — Хаскель, на самом деле поддерживает ИП, и оно частенько в нем применяется. Только в случае Хаскеля ИП выделяется в монады.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Undying, Вы писали:
U>Здравствуйте, samius, Вы писали:
S>>Термин понятен, суть его ясна, но что под ним подразумеваешь ты — не знаю. Общепринятый термин "детерминированная функция" ортогонален сайд эффектам, т.е. могут существовать детерминированные функции без сайд эффектов, с ними, либо недетерминированные с сайд эффектами и без них же.
U>Еще в первом ответе тебе я указал для какого определения мне нужен термин:
U>
U>Т.е. чистая функция эта такая функция, для работы которой достаточно только входных параметров и ничего более. Изменять входные параметры чистая функция имеет право, соответственно чистая процедура (т.е. функция без возвращаемого значения) вполне возможна.
U>Что тут может быть непонятным?
Ты слишком легко даешь новые определения и подменяешь термины. Спрашивал суть детерминированности, процитировал чистоту. Хорошо, согласно этому определению, твоя "чистая" функция может работать с внешними массивами. разве нет?
S>>По общепринятому определению чистоты функции (детерминированность + отсутствие сайд эффектов) — может. Как- просто определение чистоты не накладывает органичений на отношение используемых данных к функции (внешние либо внутренние). Отсутствие сайд эффектов — это отсутствие изменений внешних данных.
U>Функция обращающаяся к внешним переменным не является детерминированной, т.к. по ее декларации непонятно неизменность чего мы должны обеспечить для получения одного и того же результата.
Я же тебе написал, что детерминированность функции к незименности переменных отношения не имеет. Или давай сюда своё собственное определение детерминированности.
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, AlexCab, Вы писали:
AC>>А уж насколько процедура/функция "изолирована" дело второе, я не прав?
VD>Не прав. Как раз детали передачи данных — дело второе. Главное как раз наличие или отсутствие побочных эффектов. В этом суть. Общая идя может быть описана так: VD>1. ИП — деструктивное изменение данных. VD>2. ФП — преобразование (с копированием) данных.
VD>Скажу по секрету, что даже самый пуриски-чистый ФЯ — Хаскель, на самом деле поддерживает ИП, и оно частенько в нем применяется. Только в случае Хаскеля ИП выделяется в монады.
Если под ИП подразумевать "деструктивное изменение данных", то хаскель с монадами к этому отношения не имеет.
Здравствуйте, samius, Вы писали:
U>>Еще в первом ответе тебе я указал для какого определения мне нужен термин:
U>>
U>>Т.е. чистая функция эта такая функция, для работы которой достаточно только входных параметров и ничего более. Изменять входные параметры чистая функция имеет право, соответственно чистая процедура (т.е. функция без возвращаемого значения) вполне возможна.
S>Ты слишком легко даешь новые определения и подменяешь термины. Спрашивал суть детерминированности, процитировал чистоту. Хорошо, согласно этому определению, твоя "чистая" функция может работать с внешними массивами. разве нет?
Ты за сутью дискуссии вообще следишь? Я тебе привел цитату из своего раннего поста и указал, что правильным в цитате было определение. "Чистая функция" это термин, а не определение и я уже признал, что более удачным термином для данного определения является "детерминированная функция". Тебе разжевывать все приходится до последней буквы, из-за чего дискутировать с тобой и неинтересно, и занимает кучу времени.
S>Я же тебе написал, что детерминированность функции к незименности переменных отношения не имеет. Или давай сюда своё собственное определение детерминированности.
Детерминированная функция это такая функция, результат работы которой определяется только ее аргументами и ничем более.
Здравствуйте, Undying, Вы писали:
U>Здравствуйте, samius, Вы писали:
S>>Ты слишком легко даешь новые определения и подменяешь термины. Спрашивал суть детерминированности, процитировал чистоту. Хорошо, согласно этому определению, твоя "чистая" функция может работать с внешними массивами. разве нет?
U>Ты за сутью дискуссии вообще следишь? Я тебе привел цитату из своего раннего поста и указал, что правильным в цитате было определение. "Чистая функция" это термин, а не определение и я уже признал, что более удачным термином для данного определения является "детерминированная функция". Тебе разжевывать все приходится до последней буквы, из-за чего дискутировать с тобой и неинтересно, и занимает кучу времени.
Это было не дискутирование, а выяснение значений терминов, которые ты употребляешь. Без этого смысл всякого дискутирования стремится к нулю. Да, кстати, я замаялся разжевывать
S>>Я же тебе написал, что детерминированность функции к незименности переменных отношения не имеет. Или давай сюда своё собственное определение детерминированности.
U>Детерминированная функция это такая функция, результат работы которой определяется только ее аргументами и ничем более.
Это определение более менее похоже на общепринятое. Но из контекста твоего поста
S>Но чистые функции, работающие с массивами не противоречат и определению Влада. Твоего определения я не видел. Откуда ты сделал вывод что раз массив, значит нечисто — не понятно.
Речь шла о внешнем массиве. Внешний это значит не являющийся аргументом. Как функция использующая внешние переменные может быть чистой?
можно сделать предположение, что функция, вычисляющая сумму элементов массива не может являться детерминированной. Ладно с массивом, длина односвязного списка — тоже, т.к. узлы списка — это внешние по отношению к функции данные, не являющиеся аргументом (кроме одного).
Из твоей трактовки детерминированности вытекает что значительная часть функций ФП недетерминирована. Не видишь противоречий?
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, samius, Вы писали:
S>>Если под ИП подразумевать "деструктивное изменение данных", то хаскель с монадами к этому отношения не имеет.
VD>Имеется в виду создание любых побочных эффекто, а не только изменение данных. Так что еще как имеет. Иначе это был бы сфероконь вакуумный.
Так согласен. Только за работу с побочными эффектами отвечают лишь некоторые из монад.
Здравствуйте, samius, Вы писали:
S>Если под ИП подразумевать "деструктивное изменение данных", то хаскель с монадами к этому отношения не имеет.
Ну почему не имеет? Вот, например, быстрая сортировка массива:
iqsort :: (Vector v a, Ord a) => v a -> v a
iqsort = modify iqsort' where
iqsort' xs | len < 2 = return ()
| otherwise = do
p <- xs `M.read` (len `div` 2)
m <- M.unstablePartition (< p) xs
iqsort' $ M.slice 0 m xs
iqsort' $ M.slice (m+1) (len-m-1) xs
where len = M.length xs
Процедура iqsort' деструктивно изменяет массив, все императивное программирование внутри монады ST, функция iqsort чистая, никаких сайд-эффектов.
... << RSDN@Home 1.2.0 alpha 4 rev. 1476>>
'You may call it "nonsense" if you like, but I'VE heard nonsense, compared with which that would be as sensible as a dictionary!' (c) Lewis Carroll
Здравствуйте, samius, Вы писали:
S>можно сделать предположение, что функция, вычисляющая сумму элементов массива не может являться детерминированной.
Из чего сделан такой вывод? Если функция принимает массив и считает по нему сумму, то эта детерминированная функция, т.к. если мы в двух разных местах передали функции идентичные массивы, то результат будет одинаковым, т.е. детерминированным.
S>Ладно с массивом, длина односвязного списка — тоже, т.к. узлы списка — это внешние по отношению к функции данные, не являющиеся аргументом (кроме одного).
Если узел хранит ссылку на список, то идентичность узлов означает идентичность списков.
Здравствуйте, Klapaucius, Вы писали:
K>Здравствуйте, samius, Вы писали:
S>>Если под ИП подразумевать "деструктивное изменение данных", то хаскель с монадами к этому отношения не имеет.
K>Ну почему не имеет? Вот, например, быстрая сортировка массива:
Дык я до этого походу не дошел еще
Здравствуйте, Undying, Вы писали:
U>Здравствуйте, samius, Вы писали:
S>>можно сделать предположение, что функция, вычисляющая сумму элементов массива не может являться детерминированной.
U>Из чего сделан такой вывод? Если функция принимает массив и считает по нему сумму, то эта детерминированная функция, т.к. если мы в двух разных местах передали функции идентичные массивы, то результат будет одинаковым, т.е. детерминированным.
Верно, но вывод сделан из твоего высказывания
Речь шла о внешнем массиве. Внешний это значит не являющийся аргументом. Как функция использующая внешние переменные может быть чистой?
Оно было сделано с термином "чистый", который ты потом заменил на "детерминированный".
S>>Ладно с массивом, длина односвязного списка — тоже, т.к. узлы списка — это внешние по отношению к функции данные, не являющиеся аргументом (кроме одного).
U>Если узел хранит ссылку на список, то идентичность узлов означает идентичность списков.
Если использование внешних данных вроде массива (без их изменения), перестает быть критерием для детерминированности, то вопрос снимается.
Здравствуйте, samius, Вы писали:
U>>Если узел хранит ссылку на список, то идентичность узлов означает идентичность списков. S>Если использование внешних данных вроде массива (без их изменения), перестает быть критерием для детерминированности, то вопрос снимается.
Если массив принимается как аргумент, то он не является внешним и функция детерминирована. Если массив принимается через замыкание (через обращение к полю класса или статическому полю не суть важно), то он является внешним и функция недетерминирована.
Здравствуйте, Undying, Вы писали:
U>Здравствуйте, samius, Вы писали:
U>>>Если узел хранит ссылку на список, то идентичность узлов означает идентичность списков. S>>Если использование внешних данных вроде массива (без их изменения), перестает быть критерием для детерминированности, то вопрос снимается.
U>Если массив принимается как аргумент, то он не является внешним и функция детерминирована. Если массив принимается через замыкание (через обращение к полю класса или статическому полю не суть важно), то он является внешним и функция недетерминирована.
Если массив immutable, то всетаки детерминированной функция будет.
Здравствуйте, Undying, Вы писали:
U>Здравствуйте, samius, Вы писали:
U>>>Если узел хранит ссылку на список, то идентичность узлов означает идентичность списков. S>>Если использование внешних данных вроде массива (без их изменения), перестает быть критерием для детерминированности, то вопрос снимается.
U>Если массив принимается как аргумент, то он не является внешним и функция детерминирована. Если массив принимается через замыкание (через обращение к полю класса или статическому полю не суть важно), то он является внешним и функция недетерминирована.
Когда говорят "функция принимает", то подразумевают передачу аргумента. Я не встречал употребление термина "принимает" в отношении функции, которая достает данные сама.
Функция Enumerable.Where() удовлетворяет твое определение детерминированности, т.к. ее результат не зависит ни от чего, кроме аргумента. Но является недетерминированной в общеупотребимом смысле.
Функция Foo.GetSum() берет данные из поля, нарушая тем самым твое следствие (т.к. это "внешний" массив), но детерминирована в общеупотребимом.
class Foo
{
int[] _array = new [] {1, 2, 3};
public int GetSum()
{
return _array.Sum();
}
}
По-моему именно твои формулировки бессмысленны с точки зрения практики.
Здравствуйте, samius, Вы писали:
S>Функция Foo.GetSum() берет данные из поля, нарушая тем самым твое следствие (т.к. это "внешний" массив), но детерминирована в общеупотребимом. S>
S>class Foo
S>{
S> int[] _array = new [] {1, 2, 3};
S> public int GetSum()
S> {
S> return _array.Sum();
S> }
S>}
S>
S>По-моему именно твои формулировки бессмысленны с точки зрения практики.
Чем плоха функциональность прибитая к классам?
1) Тяжело понять с какими именно сущностями функция класса работает. Т.к. классы обычно включают в себя гораздо больше сущностей, чем требуется конкретной функции класса.
2) Функции класса тяжело использовать повторно. Т.к. если подобная функциональность понадобилась в другом месте, то сущности необходимые для ее работы в этом месте обычно есть, а вот сущностей необходимых для конструирования класса содержащего эту функцию очень часто нет, т.к. для создания класса требуются дополнительные сущности, не нужные функции.
Поэтому разница в качестве кода при реализации функциональности в виде свободных функций по сравнению с функциональностью прибитой к классам очень велика. Это именно разница с точки зрения практики.
зы
Наконец-то удачный термин подобрал, то чему я давал определение должно называться "свободными функциями".
Здравствуйте, Undying, Вы писали:
U>Чем плоха функциональность прибитая к классам?
U>1) Тяжело понять с какими именно сущностями функция класса работает. Т.к. классы обычно включают в себя гораздо больше сущностей, чем требуется конкретной функции класса.
На правах инкапсуляции все что тебе должно быть известно о методе класса, должно быть известно из сигнатуры и документации
U>2) Функции класса тяжело использовать повторно.
Единица повторного использования в ООП — класс.
U>Поэтому разница в качестве кода при реализации функциональности в виде свободных функций по сравнению с функциональностью прибитой к классам очень велика. Это именно разница с точки зрения практики.
Покажи с точки зрения практики, как будет выглядеть код, вычисляющий сумму элементов в произвольном наборе, не используя функциональность, прибитую к классам/интерфейсам.
U>зы U>Наконец-то удачный термин подобрал, то чему я давал определение должно называться "свободными функциями".
С тем что нестатические методы System.String не являются свободными — я согласен
Здравствуйте, samius, Вы писали:
U>>2) Функции класса тяжело использовать повторно. S>Единица повторного использования в ООП — класс.
Поэтому в ООП с повторным использованием кода все очень плохо. Впрочем от этого недостатка нетрудно избавиться, если львиную долю функциональности держать в свободных функциях, а функции классов сводить к вызовам свободных функций при минимуме дополнительной логики.
U>>Поэтому разница в качестве кода при реализации функциональности в виде свободных функций по сравнению с функциональностью прибитой к классам очень велика. Это именно разница с точки зрения практики. S>Покажи с точки зрения практики, как будет выглядеть код, вычисляющий сумму элементов в произвольном наборе, не используя функциональность, прибитую к классам/интерфейсам.
T Sum(IEnumerable<T> items, Func<T, T, T> summator);
Здравствуйте, Undying, Вы писали:
U>Здравствуйте, samius, Вы писали:
U>>>2) Функции класса тяжело использовать повторно. S>>Единица повторного использования в ООП — класс.
U>Поэтому в ООП с повторным использованием кода все очень плохо. Впрочем от этого недостатка нетрудно избавиться, если львиную долю функциональности держать в свободных функциях, а функции классов сводить к вызовам свободных функций при минимуме дополнительной логики.
Покажи как это будет выглядеть на примере Dictionary<TKey,TValue>.Add.
U>>>Поэтому разница в качестве кода при реализации функциональности в виде свободных функций по сравнению с функциональностью прибитой к классам очень велика. Это именно разница с точки зрения практики. S>>Покажи с точки зрения практики, как будет выглядеть код, вычисляющий сумму элементов в произвольном наборе, не используя функциональность, прибитую к классам/интерфейсам.
U>
Здравствуйте, samius, Вы писали:
S>Покажи как это будет выглядеть на примере Dictionary<TKey,TValue>.Add.
А чего-нибудь попроще нельзя? Мне как-то лень лезть в рефлектор, разбираться в не самой очевидной механике и думать как ее наилучшим образом свести к вызовам свободных функций с минимумом обвязки над ними.
S>Как ты собираешься исключительно свободными функциями доставать элементы из items?
Откуда взялось требование "исключительно"? Объясни, как из:
Впрочем от этого недостатка нетрудно избавиться, если львиную долю функциональности держать в свободных функциях, а функции классов сводить к вызовам свободных функций при минимуме дополнительной логики.
можно сделать вывод, что функции должны быть "исключительно" свободными?