DG>>>соответственно, первое задание более устойчивое — ряд ошибок автоматически выявляются на более поздних этапах, второе задание — неустойчивое, допущенная ошибка больше никогда не проявляется, и лишь скрыто пакостит. S>>Первое задание не всегда корректное. Второе — всегда.
DG>корректность того, что все элементы исходной последовательности X перебираются в результате последовательности — волнует больше, чем корректность работы самой последовательности. DG>в частности в задачах обеспечения безопасности, надежности и т.д., т.к. понятно как можно защититься от некорректной последовательности, но не понятно как защитится от некорректности полноты перебора.
Если последовательность некорректна, о каких пробежках вообще речь? Нет последовательности = нет пробежек по ней.
{ 1, 2, (3 или 4 ?), ...)
Ну и как тут доказывать что все элементы перебраны? 3 перебрали? А 4?
S>>Если последовательность некорректна, о каких пробежках вообще речь? Нет последовательности = нет пробежек по ней.
DG>наткнулись на ошибку — ее исправили, и побежали дальше (заново) DG>а в другом случае — даже натыкаться не на что.
В первом случае будет проще лишь для конечных X (а значит и длина последовательности будет конечной при задании через F::X->Nat). В аналогичном случае проверка полноты покрытия при определении через F::Nat->X будет ничуть не сложнее.
Если X хотя бы счетно, то первый случай ничем не лучше.
S>Итак, библиотека от реальной программы не отличается ничем.
с основной мыслью твоей согласен, но часть выводов считаю неполными.
остановлюсь на ряде моментов..
сначала небольшое отступление, что такое понятия, как они используются и какой они смысл несут...
понятия появляются как краткое обозначение распространенных ролей использования:
понятие "чайник" может обозначать роль "чайник" — эту роль имеет предмет, в котором готовят воду для чая,
понятие "стол" может обозначать роль "стол" — эту роль имеет предмет, на поверхности которого человек выполняет определенную деятельность,
понятие "программная библиотека" может обозначать роль "програмная библиотека" — эту роль имеет код, который используется другой программой
понятие "декларативная программа" может обозначать роль "декларативная программа" — эту роль имеет код, который позволяет понять, что будет сделано, без выполнения кода.
понятие "чайник" может обозначать объект "чайник" — это предмет, который заточен под преимущественное выполнение роли "чайник"
или в общем виде:
понятие X может обозначать объект X — это предмет, который заточен под преимущественное выполнение роли X.
при этом у такого объекта начинают появляться свойства, которые упрощают использование объекта в роли X.
у объекта "чайник" появляется носик, ручка, крышка и т.д., которые упрощают использование в роли "чайник", в частности, носик упрощает наливание воды в кружку.
у объекта "стол" появляется место для ног под поверхностью, чтобы было удобно сидеть.
у объекта "программная библиотека" появляется программное метаописание, возможность связываться с библиотекой напрямую в памяти и т.д.
у объекта "декларативная программа" появляется близость к логической нотации, требования иммутабельности и т.д.
понятия могут использовать как классы, и тогда подразумевается, что объект принадлежащий одному классу не может принадлежать другому классу.
например, для класса "чайник" подразумевается, что он непересекается с классами "кастрюля", "котелок", "термос", "кружка" и т.д.
класс "стол" непересекается с классом "стул", "тумбочка", "подоконник" и т.д.
класс "программная библиотека" непересекается с классом "программа".
класс "декларативная программа" непересекается с классом "императивная программа".
непротиворечивое деление объектов на такие классы можно сделать только для объектов, которые специализируется на выполнение одной роли, и только пока они выполняют только эту роль.
например, термопот (который одновременно предназначен, и для роли чайник, и для роли термос) или чайник, в котором студенты варят пельмени — уже тяжело однозначно и непротиворечиво классифицировать как чайник, термос или кастрюля.
можно продолжать классифицировать по исходным классам и неоднофункциональные объекты, но здесь уже классификация будет плавать от задачи к задаче, от одной точки зрения к другой точке зрения и т.д.
при этом в каждой конкретной задаче необходимо явно определить, о чем идет речь: о ролях, об объектах, и какие свойства необходимы, чтобы объект входил в класс X.
от рассмотрения отдельных задач можно перейти к рассмотрению классов задач, и здесь уже удобно будет ввести аппарат нечетких множеств http://ru.wikipedia.org/wiki/%D0%9D%D0%B5%D1%87%D1%91%D1%82%D0%BA%D0%BE%D0%B5_%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D1%81%D1%82%D0%B2%D0%BE.
и зафиксировать, что степень отнесение объекта к нечеткому множеству "чайник" показывает насколько объект похож на классический чайник, и показывает в насколько широком классе задач можно считать, что этот объект есть "чайник".
из-за того, что метрику похожести и метрику подсчета отношения кол-ва задач в определенном классе задач ко всему множеству задач — можно брать произвольные, это и будет давать нечеткие множества: термопот сильно похож на чайник, т.к. включает большинство свойств чайника, и средне похож на термос, потому что такая вспомогательная функция, как мобильность, слабо поддержана.
при этом можно продолжать работать и в четких определениях, а нечеткие определения, утверждения и классификация использовать как направление, с которого начинается четкое специфицирование.
при этом переиспользование терминов делается для того, чтобы облегчить вхождение людей в задачу.
человеку проще представить один раз нечеткий класс "чайник" и восстанавливать его до четкого определения в каждой задаче, чем переключаться между четкими классами "Ч381 дробь 137 бис", "Ч53 штрих дробь 2" и т.д.
S>Итак, библиотека от реальной программы не отличается ничем.
как именно ты в данном случае рассматриваешь эти понятия? как роли? как однофункциональные объекты? как непересекающиеся классы? как нечеткие классы?
твое утверждение близко к последнему рассмотрению "нечеткие классы", и к задаче — в какой роли конкретный код может использоваться.
и при этом твое утверждение лучше переформулировать как грань: между библиотекой и реальной программой очень нечеткая. объект "программа" может легко может выступать в роли "библиотека" (например, когда некая программа использует word для обработки doc-файлов), или объект "библиотека" может использоваться в роли "программа" (например, asp.net сайт, который выпускается в виде библиотеки, но для пользователя, выступает как отдельная программа)
при этом для задачи "спецификация результата" классы "программа" и "библиотека" при классификации объектов можно определить как:
программа: внешняя граница кода — это только ввод/вывод (консоль, файлы, gui, socket-ы и т.д.)
программная библиотека: внешняя граница — только все публичные члены всех публичных классов (и отсутствие ввода-вывода).
таких чистых программ и библиотек почти не бывает, поэтому введем метрику отношения к тому или иному классу как процент function point приходится на ввод-вывод и функции уровня ЯП. 0% ввода-вывода — библиотека, 100% — программа.
классы "программа" и "библиотека" при классификации ролей можно определить как нечеткие множества с двумя чистыми крайностями:
программа — из всего кода реально используется одна функциональная точка с одним и тем же значением аргументов
библиотека — из всего кода реально используется все 100% функциональных точек на всем множестве аргументов.
общую метрику Z для объекта "программа/библиотека" выступающего в роли "программы/библиотеки" — можно задать, как, например, перемножение одного другого.
метрика Z корреллирует с трудностью восстановления спецификации результата. чем выше значение, тем выше вероятность, что спецификация результата будет совпадать с самим кодом.
S>В первом случае будет проще лишь для конечных X (а значит и длина последовательности будет конечной при задании через F::X->Nat). В аналогичном случае проверка полноты покрытия при определении через F::Nat->X будет ничуть не сложнее. S>Если X хотя бы счетно, то первый случай ничем не лучше.
сходу не вижу, как это можно использовать для проверки последовательности заданной как (вырожденный случай paging-а со страницей из одного элемента):
вот что здесь надо потребовать, чтобы эта функция корректно перебирала все элементы, и что делать если в реальности эти требования не возможно выполнить?
с помощью какого алгоритма такие требования можно выделить?
Здравствуйте, DarkGray, Вы писали:
S>>В первом случае будет проще лишь для конечных X (а значит и длина последовательности будет конечной при задании через F::X->Nat). В аналогичном случае проверка полноты покрытия при определении через F::Nat->X будет ничуть не сложнее. S>>Если X хотя бы счетно, то первый случай ничем не лучше.
DG>сходу не вижу, как это можно использовать для проверки последовательности заданной как (вырожденный случай paging-а со страницей из одного элемента): DG>
Твоя F(i) это не отображение. Аппелирую к определению отображения(функции). Каждому i нужно сопоставить один конкретный элемент из множества. В твоей F(i) нет детерминированности, значит речи о последовательности нет. Хочешь проверять его свойства — вперед. Честно говоря, не понимаю, как это у тебя получится лучше с функцией Items->N.
DG>вот что здесь надо потребовать, чтобы эта функция корректно перебирала все элементы, и что делать если в реальности эти требования не возможно выполнить? DG>с помощью какого алгоритма такие требования можно выделить?
Хочешь продолжить разговор о последовательностях — приведи пример с последовательностью. Можем рассмотреть в качестве последовательности набор элементов, выбранных с помощью F(i) и зафиксированных после этого выбора. Только F(i) в таком продолжении будет за бортом.
Здравствуйте, DarkGray, Вы писали:
S>>Итак, библиотека от реальной программы не отличается ничем. DG>как именно ты в данном случае рассматриваешь эти понятия? как роли? как однофункциональные объекты? как непересекающиеся классы? как нечеткие классы?
Я продемонстрировал, как я рассматриваю понятия библиотеки и программы. В вашей классификации — это рассмотрение с точки зрения функциональных ролей, попытка формализовать трактовку "реальной программы" как того, чем пользуется пользователь, и "библиотеки" как того, чем пользуются программы.
DG>таких чистых программ и библиотек почти не бывает, поэтому введем метрику отношения к тому или иному классу как процент function point приходится на ввод-вывод и функции уровня ЯП. 0% ввода-вывода — библиотека, 100% — программа.
Я ведь знал, что вам захочется ввести метрику. И я предупреждал, что вы упаритесь вводить её мало-мальски непротиворечивым способом.
Вот и это определение метрики никуда не годится. Посчитайте процент function point в программе grep.
DG>метрика Z корреллирует с трудностью восстановления спецификации результата. чем выше значение, тем выше вероятность, что спецификация результата будет совпадать с самим кодом.
Гуманитарщина. Т.е. наукообразные рассуждения ни о чём.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, DarkGray, Вы писали: DG>какое готовое? http://ru.wikipedia.org/wiki/%D0%9F%D0%BE%D1%81%D0%BB%D0%B5%D0%B4%D0%BE%D0%B2%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%BE%D1%81%D1%82%D1%8C
Читать раздел "определение". DG>и как его использовать для моего утверждения, что если хочется записать сложную последовательность из всех элементов множества X в декларации программы, то: DG>лучше использовать F(X)->N (требование left-unique при этом автоматически подразумевается) для однозначных последовательностей (или F(X)->set<N> для последовательностей, где одни и те же элементы используются несколько раз) и использовать автоматическое восстановление F(N)->X из F(X)->N, DG>вместо того, чтобы задавать F(N)->X, а потом пытаться доказать, что эта функция полная справа.
А его не надо использовать для вашего утверждения. Ваше утверждение изоморфно "для заворачивания шурупов лучше использовать плоскогубцы, чем молоток", и само по себе никуда не годится.
Вот вам другое утверждение: "если хочется записать сложную последовательность из всех элементов множества X без повторений в декларации программы, то лучше задать на этом множестве отношение строгого полного порядка, чем любые приседания с многозначными отображениями".
Для всех воображаемых вами конструкций математики придумали удобные определения и формулировки.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
S> И я предупреждал, что вы упаритесь вводить её мало-мальски непротиворечивым способом.
во-первых, то что ты сейчас требуешь называется однозначность, а не непротиворечивость.
во-вторых, любое фиксирование(декларирования, измерения и т.д.) делается ради цели (появление возможности делать доп. выводы, передача образа от одного человека другому и т.д.)
ради какой цели ты сейчас хочешь однозначно зафиксировать метрику?
S>Вот вам другое утверждение: "если хочется записать сложную последовательность из всех элементов множества X без повторений в декларации программы, то лучше задать на этом множестве отношение строгого полного порядка, чем любые приседания с многозначными отображениями".
утверждение неверное для случаев, когда понятие "лучше" включает в себя критерии:
1. "требует меньше вычислительных ресурсов для достоверной проверки своей корректности",
2. "накладывает меньше ограничений на применимость"
Здравствуйте, DarkGray, Вы писали:
DG>во-первых, то что ты сейчас требуешь называется однозначность, а не непротиворечивость.
Непротиворечивость. Это когда у нас результат вычисления метрики не противоречит нашим ожиданиям. Например, будет забавно, когда библиотека для логгирования окажется "менее библиотечной", чем программа для разводки печатных плат.
DG>во-вторых, любое фиксирование(декларирования, измерения и т.д.) делается ради цели (появление возможности делать доп. выводы, передача образа от одного человека другому и т.д.) DG>ради какой цели ты сейчас хочешь однозначно зафиксировать метрику?
Я — не хочу. Это вам очень хочется вводить метрики на неизмеримых вещах.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, DarkGray, Вы писали:
S>>Вот вам другое утверждение: "если хочется записать сложную последовательность из всех элементов множества X без повторений в декларации программы, то лучше задать на этом множестве отношение строгого полного порядка, чем любые приседания с многозначными отображениями".
DG>утверждение неверное для случаев, когда понятие "лучше" включает в себя критерии: DG>1. "требует меньше вычислительных ресурсов для достоверной проверки своей корректности", DG>2. "накладывает меньше ограничений на применимость"
Вы заблуждаетесь.
1. Вычислительных ресурсов нужно ровно O(N), где N — длина последовательности.
2. Ограничений на применимость вовсе нет.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
V>>>>Зачем же от ленивости-то? Я сейчас с удовольствием почитал собственный аргумент, но в твоей озвучке. Итак... если нет возможности ощутить как-либо побочный эффект, он есть, или его нет? S>>>Смотри определение
V>>Не в Вики случайно? S>Да я там его смотрел. У тебя есть свое, лучше?
Конечно есть лучше. Например от нашего коллеги Синклера: побочные эффекты — это неявные зависимости. (Хотя на сегодня уже лучше оперировать понятием прозрачности ссылок, ИМХО).
А определение в Вики — это выхолощенная малопоследовательная в рассуждениях каша, сорри, которая родилась как некий собирательный ответ на объективные возражения относительно первоначального определения побочных эффектов. Попробуй дать ты своими словами, только без вот этих компрометирующих всю затею частностей, типа упоминания операций ввода-вывода в том определении, которое должно претендовать на общность и универсальность.
V>>Да запусти любую программу на хаскеле, да посмотри. S>Проблема в том, что результат выполнения main на хаскеле (без использования бэкдоров) является функцией, ну или его можно воспринимать как фукнцию. И увидеть побочный эффект от выполнения main я затрудняюсь. А с тем что эта функция (результат main) может иметь побочные эффекты, я не спорю.
Дык, давай тогда с тем же успехом рассматривать в С++ только шаблоны, порождающие целевой код. А что... очень "чистый" язык получается...
Кароч, с таким подходом, "тут смотрим, тут не смотрим" мы далеко не уедем. Речь идет о целевой исполняемой программе. То, что в Хаскеле некая часть кода безусловна чиста не говорит о том, что чист язык целиком, если рассматривать программу целиком. В С++ тоже часть кода обычно чиста, речь может идти лишь о гарантиях чистоты. И то, после моих замечаний относительно мощности современных компиляторов, вот эти условные визуальные и объятные человеческим разумом гарантии выглядят малость жалко и являются попыткой извратить смысл происходящего, т.е. натянуть происходящее на аналогию исполнения программы у нас в голове, а не современных компах.
V>>Мои рассуждения в пред. посте применимы к технике ООП, ведь если объект не имеет зависимостей от глобальных данных, то любые вызовы его методов в однопоточном апартаменте сводятся к эквивалентным чистым S>Чушь!
Вот, ЧТД. Не подумав. А ведь именно так реализовано ФП "унутре" на современных архитектурах.
S>Возьмем пример DarkGray-а, где создается объект C, который не зависит ни от каких глобальных данных (напрямую). Но зависит от GetTickCount, который seed в rnd, что данными назвать затруднительно. Тем не менее, считать такой объект чистым — весьма наивно. S>Да, пусть объект C имеет зависимость от rnd лишь в конструкторе. Но эта зависимость могла бы быть в методе. И эта зависимость не от данных. Имей в виду, когда будешь карежить определения в другой раз.
Я имею. Мы вообще декларативность обсуждали, а на побочные эффекты съехали из-за этого недоразумения:
While functional languages typically do appear to specify "how", a compiler for a purely functional programming language is free to extensively rewrite the operational behavior of a function, so long as the same result is returned for the same inputs. This can be used to, for example, make a function compute its result in parallel, or to perform substantial optimizations (such as deforestation) that a compiler may not be able to safely apply to a language with side effects.
Характерно, что я еще помню те времена, когда декларативным считали не функциональный подход (бо он такой же низкоуровневый как ООП или даже еще ниже, из-за плохой инкапсуляции), а некие высокоуровневые языки программирования или DSL, в которых невозможно было постановку задачи (т.е. исходник) перепутать с "что" на "как". Самые яркие представители — это Пролог и SELECT в SQL.
Вот это новое определение насчет приписывания ФП в декларативные языки появилось относительно недавно и сразу же успело устареть. Я уже делал замечание, что компилятор в состоянии выводить зависимости, поэтому по-факту мы не видим функциональных языков, компиляторы которых выполняют все эти предполагаемые преобразования кода лучше, чем компиляторы того же С++, которые на основе полного анализа кода и вывода всех зависимостей делают все эти перечисленные преобразования на сегодня лучше всех остальных компилторов вместе взятых. Т.е. все эти техники: перестановку кода, спекулятивные вычисления во время компиляции, преобразования выражений и т.д. и т.п., т.е. те преобразования, которые якобы характерны только для ФП. В общем, по факту тот самый аргумент, за счет которого ФП некоторое время пытаются приписывать декларативному программированию не выдерживает никакой критики — действительность опровергает такой поверхностный подход.
И да, пока что компиляторы С++ не занимаются автоматическим распараллеливанием (на всякий случай дабы избежать лишних итераций обсуждения относительно одной неиспользуемой таки техники), но это не от того, что они неспособны вывести все зависимости... они-то их выводят замечательно, я предлагаю поверить на слово человеку, который много изучает генерируемый ассемблерный код, особенно в местах, где происходят интенсивные вычисления... Просто по сегодняшним реалиям создание дополнительных потоков и синхронизация их результатов в конце суммарно очень дорогие, чтобы поручать это компилятору (особенно когда все вычисления происходят в таком режиме). Не всегда овчинка стоит выделки, во время компиляции ты этого не узнаешь ни на какой технике, на на ФП ни на ООП, это определяется только во время профилирования/тестов. Пусть лучше это происходит с помощью специальных либ, типа PLINQ которые программист использует под свою ответственность.
S>>>Теперь по поводу, нельзя ли выкидывать сразу копию... Копию выкидывать сразу можно при определенных условиях. Но это трюк вычислителя, а не языка программирования. Из того что копия может быть выкинута вычислителем, не следует ровно ничего в отношении императивности языка, описывающего порождение копии.
V>>Нет, из этого следует детерминированность, а только она и является целью, а вовсе не абстрактная "чистота". S>Напоминаю о примере с якобы детерминированным printf-ом. Детерминированности недостаточно для изменения порядка.
Понимаешь... заданный порядок доступа к любому ресурсу можно получить только из одного потока, либо через явную синхронизацию, что есть аналог однопоточности для ресурса, коль разные потоки обращаются к нему строго по-очереди. И в этом плане мы уже обсудили достаточно относительно того, как заданный порядок обращений к ресурсу обеспечить в императиве или в ФП (через явное задание вложенности ф-ий, например). А коль разделяемый ресурс используется из произвольных потоков, то и картинка на нем произвольная. Ключевое здесь "разделяемый" — вот где более фундаментальный водораздел м/у подходами к программированию, чем ФП vs императив, бо в случае локальных зависимостей для императива (или выводимости этой зависимости через мощщи современных компиляторов) обе техники ведут себя одинаково. А в случае необходимости доступа к разделяемому ресурсу, увы, обе техники тоже ведут себя одинаково, обеспечивая некий обязательный порядок операций обращений к такому ресурсу (IO в Хаскеле мы уже обсуждали).
Вот и получается, что (А) обе техники ФП и императив программируют в стиле "как" (даже Вики с этим согласна), (B) для случая обращения к локальным и нелокальным ресурсам обе техники тоже ведут себя одинаково на современных компиляторах, (C) отличаются только тем, что в ФП (например в Хаскеле) чистота вносится в контракт для обеспечения явности зависимостей, а в императиве зависимости выводятся компилятором (ИМХО, в ФП тоже нечистые места могли бы выводиться автоматически, вряд ли сложно доработать Хаскель до этой фичи), т.е. обоим техникам в итоге доступны преобразования, которые по мнению Вики рассматривают программу ФП в терминах "как" в кач-ве "что".
Вот и получается, что разницы толком никакой, она сугубо в голове, т.е. в фанатизме и ангажированности, от непонимания, как всё устроено и работает. Разумеется, современная императивная программа на С++ столь же декларативна и даже еще больше, чем эквивалентная программа на любом ФП, бо компиляторы С++ на сегодня больше всех остальных компиляторов абстрагируют исходный код от конечного результата, используя его лишь как некую отправную декларативную точку для череды серьезных преобразований с учетом всех обнаруженных компилятором зависимостей.
==============
Сорри, на другие ветки отвечать не буду, у нас там пошло много повторений, к сожалению.
Здравствуйте, vdimas, Вы писали:
V>Здравствуйте, samius, Вы писали:
V>>>>>... если нет возможности ощутить как-либо побочный эффект, он есть, или его нет? V>>>Не в Вики случайно? S>>Да я там его смотрел. У тебя есть свое, лучше?
V>Конечно есть лучше. Например от нашего коллеги Синклера: побочные эффекты — это неявные зависимости.
Это не определение, это пояснение, выдранное из контекста. V>(Хотя на сегодня уже лучше оперировать понятием прозрачности ссылок, ИМХО).
Вообще говоря, побочный эффект и ссылочная прозрачность — это довольно разные вещи, и подменять одно другим несколько наивно, ИМХО.
V>А определение в Вики — это выхолощенная малопоследовательная в рассуждениях каша, сорри, которая родилась как некий собирательный ответ на объективные возражения относительно первоначального определения побочных эффектов. Попробуй дать ты своими словами, только без вот этих компрометирующих всю затею частностей, типа упоминания операций ввода-вывода в том определении, которое должно претендовать на общность и универсальность.
Ты об этом определении?
In computer science, a function or expression is said to have a side effect if, in addition to returning a value, it also modifies some state or has an observable interaction with calling functions or the outside world.
Мне оно нравится. Конечно, если ты мне подскажешь как общно и универсально выразить "изменение некоторого состояния" и "обозримое взаимодействие с внешним (по отношению к функции) миром", то я попробую переформулировать.
S>>Проблема в том, что результат выполнения main на хаскеле (без использования бэкдоров) является функцией, ну или его можно воспринимать как фукнцию. И увидеть побочный эффект от выполнения main я затрудняюсь. А с тем что эта функция (результат main) может иметь побочные эффекты, я не спорю.
V>Дык, давай тогда с тем же успехом рассматривать в С++ только шаблоны, порождающие целевой код. А что... очень "чистый" язык получается...
Шаблоны шаблонам рознь. И код на шаблонах вполне может быть декларативным, коль не изменяет состояние. А может быть и нет. Но код не будет декларативным только лишь потому что ты приписал к нему template<class X>. Если функция плодила побочные эффекты, то она их и будет плодить, даже будь записанной в виде шаблона. V>Кароч, с таким подходом, "тут смотрим, тут не смотрим" мы далеко не уедем. Речь идет о целевой исполняемой программе. То, что в Хаскеле некая часть кода безусловна чиста не говорит о том, что чист язык целиком, если рассматривать программу целиком. В С++ тоже часть кода обычно чиста, речь может идти лишь о гарантиях чистоты. И то, после моих замечаний относительно мощности современных компиляторов, вот эти условные визуальные и объятные человеческим разумом гарантии выглядят малость жалко и являются попыткой извратить смысл происходящего, т.е. натянуть происходящее на аналогию исполнения программы у нас в голове, а не современных компах.
Мощь компиляторов не имеет никакого отношения к определению декларативности подхода. Предлагаю к этому не возвращаться более.
V>>>Мои рассуждения в пред. посте применимы к технике ООП, ведь если объект не имеет зависимостей от глобальных данных, то любые вызовы его методов в однопоточном апартаменте сводятся к эквивалентным чистым S>>Чушь!
V>Вот, ЧТД. Не подумав. А ведь именно так реализовано ФП "унутре" на современных архитектурах.
Вот тебе пример:
class X {
public int Add(int a, int b) { Console.WriteLine(); return a + b; }
}
Зависимости от глобальных данных нет. Можешь свести вызов метода Add к эквивалентному чистому?
S>>Возьмем пример DarkGray-а, где создается объект C, который не зависит ни от каких глобальных данных (напрямую). Но зависит от GetTickCount, который seed в rnd, что данными назвать затруднительно. Тем не менее, считать такой объект чистым — весьма наивно. S>>Да, пусть объект C имеет зависимость от rnd лишь в конструкторе. Но эта зависимость могла бы быть в методе. И эта зависимость не от данных. Имей в виду, когда будешь карежить определения в другой раз.
V>Я имею. Мы вообще декларативность обсуждали, а на побочные эффекты съехали из-за этого недоразумения: V>
V>...This can be used to, for example, make a function compute its result in parallel, or to perform substantial optimizations (such as deforestation) that a compiler may not be able to safely apply to a language with side effects.
На побочные эффекты мы съехали вот почему:
declarative programming is a programming paradigm that expresses the logic of a computation without describing its control flow (control flow (or alternatively, flow of control) refers to the order in which the individual statements, instructions, or function calls of an imperative or a declarative program are executed or evaluated.)
V>Характерно, что я еще помню те времена, когда декларативным считали не функциональный подход
Извини, но я с тобой не могу согласиться даже в текущие времена. Поэтому, то что ты помнишь о тех временах, не является для меня аргументом.
V>Вот это новое определение насчет приписывания ФП в декларативные языки появилось относительно недавно и сразу же успело устареть. Я уже делал замечание, что компилятор..., компиляторы которых... компиляторы того же С++... лучше всех остальных компилторов вместе взятых ... во время компиляции. В общем, по факту тот самый аргумент, за счет которого ФП некоторое время пытаются приписывать декларативному программированию не выдерживает никакой критики — действительность опровергает такой поверхностный подход. V>пока что компиляторы С++ не занимаются автоматическим распараллеливанием ... чтобы поручать это компилятору... во время компиляции ты этого не узнаешь.
Я не считаю что компиляторы каким-то образом влияют на то, что называется декларативным подходом. Потому множественное упоминание компиляторов на мое мнение не повлияло.
Понимаешь, даже если код на хаскеле вместо компилятора хаскеля будет кем-то преобразован в дремучий императив на C++, а потом C++ его будет компилировать в коды, то исходный код на хаскеле будет все равно декларативен (конечно, если не будет использовать бэкдоры). Мне чихать, на то, кто компилит, как оптимизирует и распараллеливает. Пока мы говорим о парадигме, в которой записан код, это все значения не имеет. Да, некоторые хорошие свойства кода позволяют делать кое-что чуть лучше. Или не позволяют. Но это ПРИНЦИПИАЛЬНО другой этаж обсуждения.
Итого, сначала надо научиться отличать декларативный код от императивного, а потом уже говорить о возможностях компиляции и оптимизации. А ты опять заходишь с противоположного конца. Говоришь что компилируется все в один и тот же код, потому пофигу как написано.
S>>Напоминаю о примере с якобы детерминированным printf-ом. Детерминированности недостаточно для изменения порядка.
V>Понимаешь... заданный порядок доступа к любому ресурсу можно получить только из одного потока, либо через явную синхронизацию, что есть аналог однопоточности для ресурса, коль разные потоки обращаются к нему строго по-очереди. И в этом плане мы уже обсудили достаточно относительно того, как заданный порядок обращений к ресурсу обеспечить в императиве или в ФП (через явное задание вложенности ф-ий, например). А коль разделяемый ресурс используется из произвольных потоков, то и картинка на нем произвольная. Ключевое здесь "разделяемый" — вот где более фундаментальный водораздел м/у подходами к программированию, чем ФП vs императив, бо в случае локальных зависимостей для императива (или выводимости этой зависимости через мощщи современных компиляторов) обе техники ведут себя одинаково. А в случае необходимости доступа к разделяемому ресурсу, увы, обе техники тоже ведут себя одинаково, обеспечивая некий обязательный порядок операций обращений к такому ресурсу (IO в Хаскеле мы уже обсуждали).
Ты опять ушел куда-то на фронт. До потоков мы так и не дойдем, если не поймем что даже в одном потоке вызовы переставлять нельзя по причине побочных эффектов. ФП тут хорошо не тем, что оно позволяет явно выстроить последовательность без ";". А тем, что чистое ФП не оперирует побочными эффектами.
Т.е. если ты возьмешь ИП и скомпозируешь его функции дабы избежать";", то все равно ты будешь зависеть от порядка вычисления аргументов. В чистом ФП — нет.
V>Вот и получается, что (А) обе техники ФП и императив программируют в стиле "как" (даже Вики с этим согласна), (B) для случая обращения к локальным и нелокальным ресурсам обе техники тоже ведут себя одинаково на современных компиляторах, (C) отличаются только тем, что в ФП (например в Хаскеле) чистота вносится в контракт для обеспечения явности зависимостей, а в императиве зависимости выводятся компилятором (ИМХО, в ФП тоже нечистые места могли бы выводиться автоматически, вряд ли сложно доработать Хаскель до этой фичи), т.е. обоим техникам в итоге доступны преобразования, которые по мнению Вики рассматривают программу ФП в терминах "как" в кач-ве "что".
Забудь ты про компиляторы. main у хаскеля описывает свой результат. main в C++ описывает последовательность действий с побочными эффектами (кроме тривиального случая int main() { return 0;}). Разница в этом.
V>Вот и получается, что разницы толком никакой, она сугубо в голове, т.е. в фанатизме и ангажированности, от непонимания, как всё устроено и работает. Разумеется, современная императивная программа на С++ столь же декларативна и даже еще больше, чем эквивалентная программа на любом ФП, бо компиляторы С++ на сегодня больше всех остальных компиляторов абстрагируют исходный код от конечного результата, используя его лишь как некую отправную декларативную точку для череды серьезных преобразований с учетом всех обнаруженных компилятором зависимостей.
Разница тривиальна, меня удивляет почему ты не хочешь ее увидеть!
printf работает на побочный эффект. putString работает на свой результат и только на него, не производя побочного эффекта.
V>============== V>Сорри, на другие ветки отвечать не буду, у нас там пошло много повторений, к сожалению.
Не надо на другие ветки отвечать
Здравствуйте, samius, Вы писали:
V>>Конечно есть лучше. Например от нашего коллеги Синклера: побочные эффекты — это неявные зависимости. S>Это не определение, это пояснение, выдранное из контекста. V>>(Хотя на сегодня уже лучше оперировать понятием прозрачности ссылок, ИМХО). S>Вообще говоря, побочный эффект и ссылочная прозрачность — это довольно разные вещи, и подменять одно другим несколько наивно, ИМХО.
Ну, судя по данному тобой ниже определению, ты их с легкостью подменяешь. И таки это зависимые вещи, второе — лишь уточнение первого.
S>
In computer science, a function or expression is said to have a side effect if, in addition to returning a value, it also modifies some state or has an observable interaction with calling functions or the outside world.
S>Мне оно нравится. Конечно, если ты мне подскажешь как общно и универсально выразить "изменение некоторого состояния" и "обозримое взаимодействие с внешним (по отношению к функции) миром", то я попробую переформулировать.
ЧТД. Что есть "внешний мир"? Как именно он тебе доступен? Чаще всего через непрозрачные ссылки (хендлы и т.д.) Степень "внешнести" некоторого объекта — это степень прозрачности для нас его внутреннего устройства и ничего более... остальное — надуманно.
S>Мощь компиляторов не имеет никакого отношения к определению декларативности подхода. Предлагаю к этому не возвращаться более.
Имеет, предлагаю таки сначала аргументы, а потом, так и быть, не возвращаться. Напомню, что изначальный смысл термина "декларативность" это написание кода в духе "что", вместо "как". Остальное было притянуто за уши чуть позже и держится эта притянутость с большим трудом, я уже показал. А потому она держится с большим трудом, что программирование в ФП требует ничуть не меньших подробностей, чем в императивном ООП, например. А по остальным доводам, почему можно рассматривать код как "что" я уже высказывался неоднократно. Хотел бы или услышать возражения по существу аргумента, или не заходи на новый круг плиз. Просто, без аргументации, ты меня всё равно не уговоришь.
V>>Вот, ЧТД. Не подумав. А ведь именно так реализовано ФП "унутре" на современных архитектурах. S>Вот тебе пример: S>
S>class X {
S> public int Add(int a, int b) { Console.WriteLine(); return a + b; }
S>}
S>
S>Зависимости от глобальных данных нет. Можешь свести вызов метода Add к эквивалентному чистому?
Как это нет? Вызов WriteLine статический, то бишь оперирует некими глобальными данными, используемыми в этом вызове неявно.
V>>Я имею. Мы вообще декларативность обсуждали, а на побочные эффекты съехали из-за этого недоразумения: V>>
V>>...This can be used to, for example, make a function compute its result in parallel, or to perform substantial optimizations (such as deforestation) that a compiler may not be able to safely apply to a language with side effects.
S>На побочные эффекты мы съехали вот почему: S>
declarative programming is a programming paradigm that expresses the logic of a computation without describing its control flow (control flow (or alternatively, flow of control) refers to the order in which the individual statements, instructions, or function calls of an imperative or a declarative program are executed or evaluated.)
Я уже показал, что при вычислении компилятором всех зависимостей для императивного подхода мы получаем ровно тот же эффект, что и для ФП. Разница тут лишь в некоей дополнительной статической гарантии, в дополнительных признаках к типам (и сигнатурам), т.е. вот если IO не указано, что ты не можешь прочитать байт из памяти, потому что ссылка на байт идет тоже как IO. Это что-то вроде дополнительного признака, есть же дополнительные признаки типов в С++, например const и volatile.
V>>Характерно, что я еще помню те времена, когда декларативным считали не функциональный подход S>Извини, но я с тобой не могу согласиться даже в текущие времена. Поэтому, то что ты помнишь о тех временах, не является для меня аргументом.
Аргументы я как раз-таки привел. Ты в ответ постоянно повторяешь "не согласен". Оригинально спор проходит, однако...
V>>Вот это новое определение насчет приписывания ФП в декларативные языки появилось относительно недавно и сразу же успело устареть. Я уже делал замечание, что компилятор..., компиляторы которых... компиляторы того же С++... лучше всех остальных компилторов вместе взятых ... во время компиляции. В общем, по факту тот самый аргумент, за счет которого ФП некоторое время пытаются приписывать декларативному программированию не выдерживает никакой критики — действительность опровергает такой поверхностный подход. V>>пока что компиляторы С++ не занимаются автоматическим распараллеливанием ... чтобы поручать это компилятору... во время компиляции ты этого не узнаешь. S>Я не считаю что компиляторы каким-то образом влияют на то, что называется декларативным подходом. Потому множественное упоминание компиляторов на мое мнение не повлияло.
Давай уже по буквам разбирать то самое нововведение к определению декларативного подхода, которое я постоянно критикую. Итак, почему ФП отнесли к декларативному (мой корявый перевод):
Хотя функциональные языки, как правило, производят впечатление спецификаций (указаний)"как", компилятор для чисто функционального языка программирования имеет право значительно переписать поведение функции, до тех пор, пока возвращается тот же результат для тех же входных данных. Это может быть использовано, например, для преобразования вычислений в параллельный вид или для выполнения существенной оптимизации (например, упрощение), аналогичное компилятор не может безопасно применяться к языку с побочными эффектами.
Итак, де-фако это пояснение, почему ФП пытаются приписать декларативному, не выдерживает критики. Саму критику уже привел. Прошу спорить по-существу, если я ошибся в рассуждениях.
Предупреждаю сразу, что такие эфемерности как "взгляд на вещи" я обсуждать не собираюсь, сорри. Во-первых этими материями можно спекулировать до бесконечности, во-вторых, нет ни одной полностью "чистой" в ФП-смысле программы, которая бы делала хоть что-то полезное, кроме собственной компиллируемости. Это проза жизни из которой мы исходим. Повторять как работает ленивость в Хаскеле не надо, спасибо, все и так понимают. Так же как понимают и то, что вычисление оператора if, например, обязательно императивно даже в полностью чистых ф-иях, без IO. Императивно — это значит аргументы вычисляются во времени в строго известном порядке, заданном спецификацией языка. Именно поэтому эту "чистую" ф-ию if можно безопасно применять в IO-контексте, т.к. детерминировано ее поведение с т.з. последовательности ожидаемых побочных эффектов при вычислении операндов ф-ии if.
S>Понимаешь, даже если код на хаскеле вместо компилятора хаскеля будет кем-то преобразован в дремучий императив на C++, а потом C++ его будет компилировать в коды, то исходный код на хаскеле будет все равно декларативен (конечно, если не будет использовать бэкдоры).
Я не вижу, чем он будет более декларативен, чем аналогичный код на C++. Покажи, где декларативность. Чуть больше аннотаций к типам/сигнатурам в плане признака их чистоты?
S>Мне чихать, на то, кто компилит, как оптимизирует и распараллеливает. Пока мы говорим о парадигме, в которой записан код, это все значения не имеет.
Обычная такая функциональная парадигма, где надо писать с той же подробностью, а иногда и более подробно, чем в ООП. Всегда надо писать в терминах "как".
S>Итого, сначала надо научиться отличать декларативный код от императивного, а потом уже говорить о возможностях компиляции и оптимизации.
Имя, сестра, имя... Что же так слабо-то, а?
S>А ты опять заходишь с противоположного конца. Говоришь что компилируется все в один и тот же код, потому пофигу как написано.
Нет, я привел вполне конкретную критику вполне конкретного популярного определения. Не приписывай мне лишнего.
S>Ты опять ушел куда-то на фронт. До потоков мы так и не дойдем, если не поймем что даже в одном потоке вызовы переставлять нельзя по причине побочных эффектов. ФП тут хорошо не тем, что оно позволяет явно выстроить последовательность без ";". А тем, что чистое ФП не оперирует побочными эффектами.
Тебе то что? Не ты же вызовы переставляешь, а компилятор. Выходи до боли знакомое кино, которое тыщу раз видел от функциональщиков: то они призывают компилятор в свидетели, что ему, оказывается, можно порядки вызовов менять как угодно, то когда говорю, что в императивном языке компилятор может делать тоже самое, т.к. способен довольно глубоко просмотреть все зависимости и увидеть степень их "локальности" — то ай, стоп, не надо обсуждать компилятор... Сорри, это несерьезно.
Меня на самом деле интересует лишь кол-во описываемых подробностей в программе, а не то, каким образом компилятор будет колдовать над этим кодом в процессе его оптимизации. Вот что тебе с того, что компилятор способен там что-то менять в твоей программе без твоего ведома? Как это тебе помогает или мешает? Делая тоже самое для С++ компилятор не делает мне ни холодно ни жарко до тех пор, пока заданная мною семантика сохраняется. (Доп. быстродействие, конечно бонус, но оно пока не доступно функциональным языкам, несмотря на все эти обещанные вещи)
S>Т.е. если ты возьмешь ИП и скомпозируешь его функции дабы избежать";", то все равно ты будешь зависеть от порядка вычисления аргументов. В чистом ФП — нет.
Не я буду зависеть, а компилятор. А мне-то что? А компиятор тоже не особо ко мне прислушается... Вот ты в упор не понимаешь, что тебе пишут. компилятор как раз тоже сможет вычислять в произвольном порядке до тех пор пока способен установить отсутствие неявных зависимостей м/у аргументами.
Кароч давай ты сделаешь паузу и подумаешь, что же есть побочный эффект, для начала. Вот есть пара вычисляемых выражений-аргументов ф-ии. Предположим, что эта пара не пишет ничего во "внешний мир" в процессе своих вычислений. Так вот, возвращаясь к началу поста относительно побочных эффектов: если эти выражения имеют пересекающиеся зависимости, которые модифицируются в процессе вычисления, то порядок вычисления аргументов важен, если же не имеют — не важен. Точка. Вот почему определение побочных эффектов Синклера всяко грамотнее рассуждений о "внешнем мире", бо последнее нечетко и неграмотно.
S>Забудь ты про компиляторы. main у хаскеля описывает свой результат. main в C++ описывает последовательность действий с побочными эффектами (кроме тривиального случая int main() { return 0;}). Разница в этом.
Поправочка, main у Хаскеля описывает КАК ИМЕННО вычислить результат, что бы там кто ни говорил. И это описание в Хаскеле идет с ничуть не меньшими подробностями чем в каком-нить другом языке с уборкой мусора (не обязательно С++).
S>Разница тривиальна, меня удивляет почему ты не хочешь ее увидеть!
Если честно, я прекрасно понимаю т.з. оппонентов, твою например. Я просто надеялся выбить ответные аргументы, вместо слышимых по этому вопросу только лишь "не согласен, это другая т.з." и т.д. Бо противоречие в нынешних определениях налицо. А противоречие это возникло не на пустом месте, так всегда бывает, когда взятое изначально слово в кач-ве термина для обозначения похожих происходящих вещей потом пытается быть пересомтренным. И тогда вместо аксиоматичного понимания сути термина возникают поправки, толкования, объяснения и прочее чтобы показать, почему это некое знакомое слово используется в незнакомом качестве. По мне вся эта возня с насильственной мутацией терминов искуственна и притянута за уши, лучше было бы придумать другой термин, например для обсуждаемого подходит "прозрачность" или что-то в этом духе.
Здравствуйте, vdimas, Вы писали:
V>Здравствуйте, samius, Вы писали:
S>>Вообще говоря, побочный эффект и ссылочная прозрачность — это довольно разные вещи, и подменять одно другим несколько наивно, ИМХО.
V>Ну, судя по данному тобой ниже определению, ты их с легкостью подменяешь. И таки это зависимые вещи, второе — лишь уточнение первого.
Я их не могу путать просто потому что это вещи скорее противоположные, чем подменяемые. Если есть ссылочная прозрачность, значит побочный эффект не торчит наружу. Если торчит, значит прозрачности быть не может.
S>>
In computer science, a function or expression is said to have a side effect if, in addition to returning a value, it also modifies some state or has an observable interaction with calling functions or the outside world.
S>>Мне оно нравится. Конечно, если ты мне подскажешь как общно и универсально выразить "изменение некоторого состояния" и "обозримое взаимодействие с внешним (по отношению к функции) миром", то я попробую переформулировать.
V>ЧТД. Что есть "внешний мир"? Как именно он тебе доступен? Чаще всего через непрозрачные ссылки (хендлы и т.д.) Степень "внешнести" некоторого объекта — это степень прозрачности для нас его внутреннего устройства и ничего более... остальное — надуманно.
Это ты надумал. Если ты о ссылочной прозрачности, то нет никакой степени прозрачности. Либо прозрачно (абсолютно), либо нет и тоже абсолютно. Внешний мир по отношению к функции — это состояние программы. Если оно изменяется после вызова и это можно как-то обнаружить — значит функция имеет побочный эффект.
S>>Мощь компиляторов не имеет никакого отношения к определению декларативности подхода. Предлагаю к этому не возвращаться более.
V>Имеет, предлагаю таки сначала аргументы, а потом, так и быть, не возвращаться. Напомню, что изначальный смысл термина "декларативность" это написание кода в духе "что", вместо "как".
Вот в этом "что" вместо "как" где ты видишь место компилятора и его мощи?
V>Остальное было притянуто за уши чуть позже и держится эта притянутость с большим трудом, я уже показал.
Остальное тянешь ты — компиляторы, оптимизаторы, распараллеливатели, и даже уровень языка. V>А потому она держится с большим трудом, что программирование в ФП требует ничуть не меньших подробностей, чем в императивном ООП, например. А по остальным доводам, почему можно рассматривать код как "что" я уже высказывался неоднократно. Хотел бы или услышать возражения по существу аргумента, или не заходи на новый круг плиз. Просто, без аргументации, ты меня всё равно не уговоришь.
Я тоже высказывался неоднократно. Меня твои высказывания не очень убеждают, т.к. ты ходишь слишком далеко от определения декларативности. Тебя мои не убеждают. Значит надо завязывать.
Вот тут ты теперь привел число либо качество подробностей. А подробности не имеют отношения к декларативности, покуда это не подробности изменения состояния.
S>>Зависимости от глобальных данных нет. Можешь свести вызов метода Add к эквивалентному чистому?
V>Как это нет? Вызов WriteLine статический, то бишь оперирует некими глобальными данными, используемыми в этом вызове неявно.
Оперирует — да. Зависит — нет. Что бы уж совсем не зависело — можно проглотить исключения.
S>>На побочные эффекты мы съехали вот почему: S>>
declarative programming is a programming paradigm that expresses the logic of a computation without describing its control flow (control flow (or alternatively, flow of control) refers to the order in which the individual statements, instructions, or function calls of an imperative or a declarative program are executed or evaluated.)
V>Я уже показал, что при вычислении компилятором всех зависимостей для императивного подхода мы получаем ровно тот же эффект, что и для ФП. Разница тут лишь в некоей дополнительной статической гарантии, в дополнительных признаках к типам (и сигнатурам), т.е. вот если IO не указано, что ты не можешь прочитать байт из памяти, потому что ссылка на байт идет тоже как IO. Это что-то вроде дополнительного признака, есть же дополнительные признаки типов в С++, например const и volatile.
Опять ты аппелируешь к компилятору
И причем тут IO, если код с ним не может взаимодействовать без бэкдоров?
V>>>Характерно, что я еще помню те времена, когда декларативным считали не функциональный подход S>>Извини, но я с тобой не могу согласиться даже в текущие времена. Поэтому, то что ты помнишь о тех временах, не является для меня аргументом.
V>Аргументы я как раз-таки привел. Ты в ответ постоянно повторяешь "не согласен". Оригинально спор проходит, однако...
Ты в качестве аргументов привел уровень языка, качество преобразований компилятора... А тему, как это связано с определением декларативности, не раскрыл.
S>>Я не считаю что компиляторы каким-то образом влияют на то, что называется декларативным подходом. Потому множественное упоминание компиляторов на мое мнение не повлияло.
V>Давай уже по буквам разбирать то самое нововведение к определению декларативного подхода, которое я постоянно критикую.
То что ты критикуешь, к сожалению, к определению декларативного подхода никак не относится. V>Итак, почему ФП отнесли к декларативному (мой корявый перевод):
Ты тут уже сделал кучу заблуждений. Не всякий код на ФП декларативен, как не всякий код на ИП императивен. С чего ты сразу всё ФП подписал к декларативному-то? V>
V>Хотя функциональные языки, как правило, производят впечатление спецификаций (указаний)"как"
Всё. Больше в этой цитате обсуждать нечего.
V>Итак, де-фако это пояснение, почему ФП пытаются приписать декларативному, не выдерживает критики.
Де-факто это не пояснение "почему", де-факто это свойства, которые вытекают из детерминированности и чистоты. Местами эти оптимизации можно применять и к ИП коду, но только пока сайд-эффекты не перепутываются. V>Саму критику уже привел. Прошу спорить по-существу, если я ошибся в рассуждениях.
Еще раз, ты критикуешь следствия декларативности, ссылаясь на то что компиляторы могут делать те же трюки с императивным кодом. А о том что они это могут делать только в ограничениях влияния сайд-эффектов, ты как-то внимание не акцентируешь.
V>Предупреждаю сразу, что такие эфемерности как "взгляд на вещи" я обсуждать не собираюсь, сорри. Во-первых этими материями можно спекулировать до бесконечности, во-вторых, нет ни одной полностью "чистой" в ФП-смысле программы, которая бы делала хоть что-то полезное, кроме собственной компиллируемости. Это проза жизни из которой мы исходим. Повторять как работает ленивость в Хаскеле не надо, спасибо, все и так понимают.
Нет, не все, но повторять уже задолбало. V>Так же как понимают и то, что вычисление оператора if, например, обязательно императивно даже в полностью чистых ф-иях, без IO.
даже SELECT в SQL будет выполнен императивно. Даже матчинг регекса будет выполнен имеративно. Однако, какое это отношение имеет к декларативности SELECT-а и регекса?
V>Императивно — это значит аргументы вычисляются во времени в строго известном порядке, заданном спецификацией языка. Именно поэтому эту "чистую" ф-ию if можно безопасно применять в IO-контексте, т.к. детерминировано ее поведение с т.з. последовательности ожидаемых побочных эффектов при вычислении операндов ф-ии if.
Никаких побочных эффектов при вычислении if нет, т.к. ничего кроме вычисления условия в нем не происходит. Если настаиваешь на обратном — попрошу продемонстрировать побочные эффекты от вычисления if.
S>>Понимаешь, даже если код на хаскеле вместо компилятора хаскеля будет кем-то преобразован в дремучий императив на C++, а потом C++ его будет компилировать в коды, то исходный код на хаскеле будет все равно декларативен (конечно, если не будет использовать бэкдоры).
V>Я не вижу, чем он будет более декларативен, чем аналогичный код на C++. Покажи, где декларативность. Чуть больше аннотаций к типам/сигнатурам в плане признака их чистоты?
Какой "покажи", если мы даже с printf разобраться не можем? А теперь и с if-ом
S>>Мне чихать, на то, кто компилит, как оптимизирует и распараллеливает. Пока мы говорим о парадигме, в которой записан код, это все значения не имеет.
V>Обычная такая функциональная парадигма, где надо писать с той же подробностью, а иногда и более подробно, чем в ООП. Всегда надо писать в терминах "как".
Подробно != "как". Хотя тут можно и путать даже на бытовом уровне. Вопрос "как ты любишь кофе" провоцирует ответы как декларативные, так и императивные. Причем, декларативный ответ может содержать больше подробностей, чем императивный.
V>Имя, сестра, имя... Что же так слабо-то, а?
Бэкингем
А кроме шуток — я не знаю как с тобой изъясняться, если у тебя хаскелевский if обладает побочными эффектами
S>>А ты опять заходишь с противоположного конца. Говоришь что компилируется все в один и тот же код, потому пофигу как написано.
V>Нет, я привел вполне конкретную критику вполне конкретного популярного определения. Не приписывай мне лишнего.
Ты покритиковал спекуляции на тему оптимизаций в конце страницы о декларативности.
S>>Ты опять ушел куда-то на фронт. До потоков мы так и не дойдем, если не поймем что даже в одном потоке вызовы переставлять нельзя по причине побочных эффектов. ФП тут хорошо не тем, что оно позволяет явно выстроить последовательность без ";". А тем, что чистое ФП не оперирует побочными эффектами.
V>Тебе то что? Не ты же вызовы переставляешь, а компилятор. Выходи до боли знакомое кино, которое тыщу раз видел от функциональщиков: то они призывают компилятор в свидетели, что ему, оказывается, можно порядки вызовов менять как угодно, то когда говорю, что в императивном языке компилятор может делать тоже самое, т.к. способен довольно глубоко просмотреть все зависимости и увидеть степень их "локальности" — то ай, стоп, не надо обсуждать компилятор... Сорри, это несерьезно.
Это ты призываешь компилятор в свидетели императивности ФП. Меня не подписывай. Свойства компилятора ФП это следствие декларативности. Из того что компилятор или процессор может переставить инструкции еще не значит что исходный код декларативен. Если для тебя и SELECT императивен, то надо завязывать с этим трепом.
V>Меня на самом деле интересует лишь кол-во описываемых подробностей в программе, а не то, каким образом компилятор будет колдовать над этим кодом в процессе его оптимизации. Вот что тебе с того, что компилятор способен там что-то менять в твоей программе без твоего ведома? Как это тебе помогает или мешает? Делая тоже самое для С++ компилятор не делает мне ни холодно ни жарко до тех пор, пока заданная мною семантика сохраняется. (Доп. быстродействие, конечно бонус, но оно пока не доступно функциональным языкам, несмотря на все эти обещанные вещи)
Теперь количество подробностей. В определении декларативности ты видел что-то о количестве подробностей?
Мне по большому счету пофигу на перестановки. Но ведь ты к ним аппелируешь, а не я!!!
S>>Т.е. если ты возьмешь ИП и скомпозируешь его функции дабы избежать";", то все равно ты будешь зависеть от порядка вычисления аргументов. В чистом ФП — нет.
V>Не я буду зависеть, а компилятор. А мне-то что? А компиятор тоже не особо ко мне прислушается... Вот ты в упор не понимаешь, что тебе пишут. компилятор как раз тоже сможет вычислять в произвольном порядке до тех пор пока способен установить отсутствие неявных зависимостей м/у аргументами.
Я выделил ключевое. Сможет до тех пор. Я не пойму, какие выводы можно делать из возможности смены порядка, даже если декларативности может быть недостаточно для возможности изменения порядка (в рамках конкретной модели вычислений).
V>Кароч давай ты сделаешь паузу и подумаешь, что же есть побочный эффект, для начала. Вот есть пара вычисляемых выражений-аргументов ф-ии. Предположим, что эта пара не пишет ничего во "внешний мир" в процессе своих вычислений. Так вот, возвращаясь к началу поста относительно побочных эффектов: если эти выражения имеют пересекающиеся зависимости, которые модифицируются в процессе вычисления, то порядок вычисления аргументов важен, если же не имеют — не важен. Точка. Вот почему определение побочных эффектов Синклера всяко грамотнее рассуждений о "внешнем мире", бо последнее нечетко и неграмотно.
Я не очень формально понимаю что такое пересекающиеся зависимости. А вот внешний мир по отношению к выражению — это понятнее. Прежде чем ставить точку, убедись что твое выражение не только не пишет во внешний мир, но и не читает из него.
S>>Забудь ты про компиляторы. main у хаскеля описывает свой результат. main в C++ описывает последовательность действий с побочными эффектами (кроме тривиального случая int main() { return 0;}). Разница в этом.
V>Поправочка, main у Хаскеля описывает КАК ИМЕННО вычислить результат, что бы там кто ни говорил. И это описание в Хаскеле идет с ничуть не меньшими подробностями чем в каком-нить другом языке с уборкой мусора (не обязательно С++).
main у Хаскеля описывает ЧТО ИМЕННО является ее результатом. Как именно он будет вычислен — я бы не взялся утверждать. Число и уровень подробностей значения не имеет.
V>Если честно, я прекрасно понимаю т.з. оппонентов, твою например.
Если так, то ты отлично делаешь вид что совершенно не понимаешь.
V>Я просто надеялся выбить ответные аргументы, вместо слышимых по этому вопросу только лишь "не согласен, это другая т.з." и т.д. Бо противоречие в нынешних определениях налицо. А противоречие это возникло не на пустом месте, так всегда бывает, когда взятое изначально слово в кач-ве термина для обозначения похожих происходящих вещей потом пытается быть пересомтренным. И тогда вместо аксиоматичного понимания сути термина возникают поправки, толкования, объяснения и прочее чтобы показать, почему это некое знакомое слово используется в незнакомом качестве. По мне вся эта возня с насильственной мутацией терминов искуственна и притянута за уши, лучше было бы придумать другой термин, например для обсуждаемого подходит "прозрачность" или что-то в этом духе.
Извини, я совершенно не понимаю, о чем ты думаешь, когда утверждаешь что if в Хаскеле имеет побочные эффекты. Приходится сомневаться в адекватности понимания тобой терминов, которые ты употребляешь, явлений, которые ты описываешь. Когда ты утвреждаешь что споришь с определением, ты говоришь о компиляторах, перстановках, многопоточности, оптимизациях, императивности вычислителей и т.п. Обо всем, но не о способе выражения логики вычислений, относительно которого сформулировано определение. Ты споришь с собой, какими-то предрассудками, но не с определением.
Прежде чем выбивать ответные аргументы, позволь для начала вернуть тебя в плоскость обсуждаемого вопроса.