Здравствуйте, AlexRK, Вы писали:
ARK>Здравствуйте, samius, Вы писали:
ARK>Ты не можешь без документации по языку судить о чистоте написанных на нем функций. Если можешь, то скажи, является ли чистой вот эта функция: "funktion Main % print Hello World \ @Q". Что это за язык, неважно, ведь ты не будешь руководствоваться документацией при проверке чистоты.
Для неизвестного мне языка — даже пытаться не буду.
S>>Если при этом тип результата функции будет int, а не Task<int> или IO int, то мне кашлять, что написано в документации.
ARK>А, то есть computation должно быть обязательно явно записанным, а неявно выражено оно быть не может? Это твое личное мнение?
Это так для обсуждаемых мной здесь языков. Все что там записано между строк кода морзянкой из пробелов и табуляций — оставлю экспертам в этой области.
S>>Какая цель в этом? Это поможет выполнить оптимизацию или упростить рассуждения о программах?
ARK>В чем "этом"? В изменении трактовки слов? Ну, у создателей хаскеля цель, очевидно, любой ценой натянуть сову на глобус и доказать, что у их языка грязные функции как будто чистые.
Мне это не очевидно. Но судя по тому, что это многих задевает лично — да, их хохма удалась на славу.
S>>Хорошо, твоя чистота называет функции хаскеля грязными. Но это не отменяет рассуждения и возможности оптимизации хаскеля в терминах обычной чистоты.
ARK>В том-то и дело, что отменяет. Грязные функции в хаскеле не приобретают никаких свойств чистых только от того, что их назвали таковыми. Они по-прежнему не являются ссылочно прозрачными, их невозможно выкинуть или переупорядочить. Это типичная грязь.
Можно узнать, о каких именно грязных функциях речь? putStr, например, о которой мы говорили — чистая.
S>>А что дает твой вариант кроме разоблачения хаскеля? Может быть он позволяет лучше заниматься оптимизацией в C++?
ARK>По моему мнению, он позволяет упростить рассуждение о тексте программы. Грязные функции обладают своими особенностями, которые надо учитывать. В хаскеле можно легко обосраться, вызвав IO за пределами do-нотации и получив в итоге вызовы в случайном порядке.
Это полная чушь. do-нотация это синтаксический сахар, рассахаренный код — это цепочка вызовов IO вне do-нотации. Переупорядочить их не дает именно IO, а не do-нотация.
S>>Но называя int действием ты ничего не достигаешь в плане возможностей оптимизации и уж точно ухудшаешь понимание программы.
ARK>Так и в хаскеле — называя IO "действием", мы ничего не достигаем в плане оптимизации и не улучшаем понимание программы.
Обобщение тут неуместно. ARK>В языке D есть pure функции и обычные — всегда видно, с чем имеешь дело, однако при всем при этом грязные функции за чистые не выдаются.
Напомню, у тебя отдельное понимание чистой функции, ничего общего общепринятым определением чистоты не имеющее.
ARK>>>Каким образом из википедийного определения читателю становится ясно, что evaluation в разных языках означает совершенно разные вещи и что чистота напрямую зависит от этого? S>>Да блин, почему они разные-то? Evaluation в С++ возвращает int и гадит в мир. В хаскле evaulation main вместо int возвращает композицию действий. Это одинаковые evaluation. Разница не в evaluation, а в организации кода.
ARK>Я понял, что для тебя камнем преткновения является синтаксическая метка. Но допустить ее неявное присутствие ты почему-то не можешь. Хотя создатель языка имеет полное право заложить любую семантику и описать ее с помощью любого синтаксиса. В том числе и неявного.
Имеет. А я имею право устраниться от обсуждения чистоты функций в языке с любой семантикой и любым синтаксисом, в том числе неявного.
S>>>>У меня суждения вполне однозначны с точностью до заранее заданного перечня сайдэффектов. Заметь, терминами evaluate/invoke я не жонглирую и оперирую лишь обозримыми сайдэффектами (зафиксированными заранее). ARK>>>Ну вот есть обозримый сайд-эффект: печать "Hello, World". У тебя есть исполняемый файл, который печатает это предложение. У тебя есть код программы, который содержит в себе визуально видимое наименование системной функции печати с параметром "Hello, World". Что говорит твое суждение относительно чистоты данной программы, если: a) документация по языку говорит тебе, что все функции языка возвращают computation; S>>Откуда это взялось? нет, не все функции языка возвращают computation и чисты только по этому.
ARK>Это взялось из семантики языка. Создатель определил семантику именно так — ВСЕ функции языка возвращают computation, при этом никаких синтаксических меток для этого нет. ARK>Что говорит твое суждение, чиста программа или нет?
О каком языке речь? О сфероконическом?
ARK>>>б) документация по языку говорит тебе, что все функции языка "выполняются напрямую"? S>>Так они напрямую и выполняются. Но если в сигнатуре функции написано что она должна вернуть структуру данных, выполнение ее приведет к возврату структуры данных (либо ошибке). С пониманием этого есть проблемы?
ARK>Без документации по языку мы не знаем, что записывается в сигнатуре функции. И что вообще означает сигнатура функции. В сигнатуре может быть голый int, но компилятор будет создавать "computation" для каждой функции (аналогия — см. checked/unchecked exception).
Вот когда C++ будет создавать computation для каждой функции, вернемся к этому вопросу.
S>>main в C++ возвращает int. main в Haskell возвращает IO a. int и IO a здесь структуры данных.
ARK>ОК, функция возвращает структуру данных QWERTY. Что говорит твое суждение, эта функция чистая или нет?
Я не сужу о чистоте по типу результата. Функция возвращающая int вполне может быть чиста, как и функция, возвращающая IO a, может быть грязной.
Re[65]: Мнение: объектно-ориентированное программирование — катастрофа на трилли
S>>И эта функция чиста.
M>Если она чиста, почему она приводит к сайд-эффектам?
Вызов такой main не приводит к сайд эффектам.
S>>Т.е. то, что ты подверг сомнению этим примером — не мои слова, а уровень своего восприятия моих слов.
M>Нет никакого уровня восприятия слов, кроме одного:
M>
M>Она будет чиста, если не будет до возврата действия производить сайд-эффекты.
M>Это строго эквивалентно следующему:
M>
M>Хаскель из кожи вон лезет, чтобы притвориться, что он чистый, а внешнего мира не существует.
Имеешь право так считать. У меня другое мнение.
Re[72]: Мнение: объектно-ориентированное программирование — катастрофа на трилли
Здравствуйте, samius, Вы писали:
ARK>>Ты не можешь без документации по языку судить о чистоте написанных на нем функций. Если можешь, то скажи, является ли чистой вот эта функция: "funktion Main % print Hello World \ @Q". Что это за язык, неважно, ведь ты не будешь руководствоваться документацией при проверке чистоты. S>Для неизвестного мне языка — даже пытаться не буду.
Отчего же? Значит, документация по языку таки нужна для суждения о чистоте написанных на нем функций?
S>>>Если при этом тип результата функции будет int, а не Task<int> или IO int, то мне кашлять, что написано в документации. ARK>>А, то есть computation должно быть обязательно явно записанным, а неявно выражено оно быть не может? Это твое личное мнение? S>Это так для обсуждаемых мной здесь языков. Все что там записано между строк кода морзянкой из пробелов и табуляций — оставлю экспертам в этой области.
Так все-таки: может ли _в принципе_ семантика быть выраженной неявно? Я создаю форк С++ под названием C++PURE и заявляю, что в нем семантика computation выражена неявно. И, стало быть, все его функции автоматически становятся чистыми. Верно?
S>>>Хорошо, твоя чистота называет функции хаскеля грязными. Но это не отменяет рассуждения и возможности оптимизации хаскеля в терминах обычной чистоты. ARK>>В том-то и дело, что отменяет. Грязные функции в хаскеле не приобретают никаких свойств чистых только от того, что их назвали таковыми. Они по-прежнему не являются ссылочно прозрачными, их невозможно выкинуть или переупорядочить. Это типичная грязь. S>Можно узнать, о каких именно грязных функциях речь? putStr, например, о которой мы говорили — чистая.
putStr невозможно заменить на значение, нельзя выкинуть при оптимизации, нельзя спекулятивно вычислить, нельзя поменять местами с другой putStr. Это типичная грязная функция.
putStr "чистая" только в случае вольной интерпретации термина "evaluation" ("считать computation результатом evaluation"). Эта интерпретация из определения чистоты НЕ следует, она записана в документации хаскеля. При стандартной интерпретации — без каких-либо дополнительных сущностей а-ля "внешний вычислитель" — putStr чистой не является.
S>>>А что дает твой вариант кроме разоблачения хаскеля? Может быть он позволяет лучше заниматься оптимизацией в C++? ARK>>По моему мнению, он позволяет упростить рассуждение о тексте программы. Грязные функции обладают своими особенностями, которые надо учитывать. В хаскеле можно легко обосраться, вызвав IO за пределами do-нотации и получив в итоге вызовы в случайном порядке. S>Это полная чушь. do-нотация это синтаксический сахар, рассахаренный код — это цепочка вызовов IO вне do-нотации. Переупорядочить их не дает именно IO, а не do-нотация.
Да, вот здесь я неправ. Побег из IO возможен разве что через unsafe.
ARK>>В языке D есть pure функции и обычные — всегда видно, с чем имеешь дело, однако при всем при этом грязные функции за чистые не выдаются. S>Напомню, у тебя отдельное понимание чистой функции, ничего общего общепринятым определением чистоты не имеющее.
Нет, во всем разговоре я руководствуюсь только тем определением, которое в википедии. Так вот, в D есть разделение на чистые и нечистые функции, которое дает не меньше информации о побочных эффектах, чем хаскелевый IO.
ARK>>Я понял, что для тебя камнем преткновения является синтаксическая метка. Но допустить ее неявное присутствие ты почему-то не можешь. Хотя создатель языка имеет полное право заложить любую семантику и описать ее с помощью любого синтаксиса. В том числе и неявного. S>Имеет. А я имею право устраниться от обсуждения чистоты функций в языке с любой семантикой и любым синтаксисом, в том числе неявного.
Имеешь. Но определение чистоты не привязано ни к какому языку, оно универсально и должно быть применимо к чему угодно. В том числе и к языкам с неявным "computation".
S>>>>>У меня суждения вполне однозначны с точностью до заранее заданного перечня сайдэффектов. Заметь, терминами evaluate/invoke я не жонглирую и оперирую лишь обозримыми сайдэффектами (зафиксированными заранее). ARK>>>>Ну вот есть обозримый сайд-эффект: печать "Hello, World". У тебя есть исполняемый файл, который печатает это предложение. У тебя есть код программы, который содержит в себе визуально видимое наименование системной функции печати с параметром "Hello, World". Что говорит твое суждение относительно чистоты данной программы, если: a) документация по языку говорит тебе, что все функции языка возвращают computation; S>>>Откуда это взялось? нет, не все функции языка возвращают computation и чисты только по этому. ARK>>Это взялось из семантики языка. Создатель определил семантику именно так — ВСЕ функции языка возвращают computation, при этом никаких синтаксических меток для этого нет. ARK>>Что говорит твое суждение, чиста программа или нет? S>О каком языке речь? О сфероконическом?
Да, о сфероконическом. Скажи, пожалуйста, что говорит твое суждение, чиста ли программа в описанном мной случае или нет?
Надеюсь, твое суждение не ограничено строго двумя языками — хаскелем и С++?
S>>>main в C++ возвращает int. main в Haskell возвращает IO a. int и IO a здесь структуры данных. ARK>>ОК, функция возвращает структуру данных QWERTY. Что говорит твое суждение, эта функция чистая или нет? S>Я не сужу о чистоте по типу результата. Функция возвращающая int вполне может быть чиста, как и функция, возвращающая IO a, может быть грязной.
То есть по сигнатуре функции в хаскеле нельзя сказать, является ли функция чистой?
Тогда почему ты считаешь, что putStr — чистая функция? Так написано в документации хаскеля?
Re[65]: Мнение: объектно-ориентированное программирование — катастрофа на трилли
M> S>И эта функция чиста. M> Если она чиста, почему она приводит к сайд-эффектам?
Ты наверное что-то путаешь, абсолютизируя понятие чистоты. Говорят о чистоте именно _функций_. Эта _функция_ чиста и к сайд-эффектам не приводит. Однако, эта функция возвращает выражение, которое будет изменять внешний с т.з. _функций_ мир.
Здравствуйте, AlexRK, Вы писали:
ARK>Здравствуйте, samius, Вы писали:
S>>Для неизвестного мне языка — даже пытаться не буду.
ARK>Отчего же? Значит, документация по языку таки нужна для суждения о чистоте написанных на нем функций?
Представления о языке — нужны. Документация, которую ты предлагаешь — нет. От такой надо держаться подальше.
S>>Это так для обсуждаемых мной здесь языков. Все что там записано между строк кода морзянкой из пробелов и табуляций — оставлю экспертам в этой области.
ARK>Так все-таки: может ли _в принципе_ семантика быть выраженной неявно? Я создаю форк С++ под названием C++PURE и заявляю, что в нем семантика computation выражена неявно. И, стало быть, все его функции автоматически становятся чистыми. Верно?
Нет, не верно. Одних заявлений о семантике недостаточно для чистоты функций.
S>>Можно узнать, о каких именно грязных функциях речь? putStr, например, о которой мы говорили — чистая.
ARK>putStr невозможно заменить на значение, нельзя выкинуть при оптимизации, нельзя спекулятивно вычислить, нельзя поменять местами с другой putStr. Это типичная грязная функция.
Ничего из перечисленного не имеет отношения к putStr и определению чистоты. С какого перепугу она стала грязной?
ARK>putStr "чистая" только в случае вольной интерпретации термина "evaluation" ("считать computation результатом evaluation"). Эта интерпретация из определения чистоты НЕ следует, она записана в документации хаскеля. При стандартной интерпретации — без каких-либо дополнительных сущностей а-ля "внешний вычислитель" — putStr чистой не является.
Ты все-таки посмотри на сигнатуру функции. Не нужно считать ее результат computation_ом, если он и есть computation. Это такая же правда, как и то, что результат main из C++ имеет тип int.
S>>Напомню, у тебя отдельное понимание чистой функции, ничего общего общепринятым определением чистоты не имеющее.
ARK>Нет, во всем разговоре я руководствуюсь только тем определением, которое в википедии.
Так покажи что есть нечистого в putStr согласно определению из википедии. ARK>Так вот, в D есть разделение на чистые и нечистые функции, которое дает не меньше информации о побочных эффектах, чем хаскелевый IO.
Хаскелевый IO не дает информации о побочных эффектах. Ведь можно продемонстрировать функцию putStr2, которая при той же сигнатуре IO a будет генерировать computation без побочных эффектов. Смысл IO лишь в упорядочивании действий, как у точки с запятой в C++.
ARK>Имеешь. Но определение чистоты не привязано ни к какому языку, оно универсально и должно быть применимо к чему угодно. В том числе и к языкам с неявным "computation".
Хорошо, должно. Но я не достаточно хорошо представляю, что такое неявный "computation", что бы судить о чистоте языка с заявлениями автора об этом.
S>>О каком языке речь? О сфероконическом?
ARK>Да, о сфероконическом. Скажи, пожалуйста, что говорит твое суждение, чиста ли программа в описанном мной случае или нет? ARK>Надеюсь, твое суждение не ограничено строго двумя языками — хаскелем и С++?
Я в достаточной мере владею несколькими языками, о чистоте которых могу рассуждать. Но не совсем четко представляю, что такое computation без семантических меток и какая там модель вычислений. Потому — нет, судить не могу и не хочу.
S>>Я не сужу о чистоте по типу результата. Функция возвращающая int вполне может быть чиста, как и функция, возвращающая IO a, может быть грязной.
ARK>То есть по сигнатуре функции в хаскеле нельзя сказать, является ли функция чистой?
Конечно, одна лишь сигнатура не дает оснований для заявлений о чистоте. ARK>Тогда почему ты считаешь, что putStr — чистая функция? Так написано в документации хаскеля?
Потому, что она выполняется на стадии выполнения main, когда computation всей программы еще не построен, ему еще не передано управление. Никакого смысла там что-то пачкать нет. Потому, что реализация putStr вызывает другую IO функцию, создающую вычисление. И кроме создания вычисления на этапе выполнения putStr больше ничего не происходит. Ничего вне контекста IO, который будет создан лишь для того, что бы передать его вычислению-результату main.
В момент выполнения функции putStr у нас нет ни мира, ни IO экземпляра. Можно испачкать putStr? Конечно, достаточно перед return насрать в консоль. И тогда сайд эффект проявит себя еще до передачи управления computation-у. Оно это кому надо? Ради чего?
Ну и разумеется, в исходниках видно, что кроме построения computation-а в putStr ничего не происходит.
Re[73]: Мнение: объектно-ориентированное программирование — катастрофа на трилли
Здравствуйте, AlexRK, Вы писали: ARK>Так все-таки: может ли _в принципе_ семантика быть выраженной неявно? Я создаю форк С++ под названием C++PURE и заявляю, что в нем семантика computation выражена неявно. И, стало быть, все его функции автоматически становятся чистыми. Верно?
Отож. Правда, на эту работу уйдёт несколько лет, т.к. придётся очень сильно перепахать спецификацию языка, и
1. Не факт, что существующие программы на С++ продолжать компилироваться компилятором, написанным по этой новой спецификации, и
2. Не факт, что семантика существующих компилирующихся программ будет сохранена.
На всякий случай поясню очевидное: если у нас теперь любая int-функция возвращает не int, а computation, то вот такая программа:
int a()
{
printf("Hello,");
return 42;
}
int b()
{
printf(" world!);
}
int main()
{
auto varA = a();
auto varB = b();
return (rand() > 50) ? varA : varB;
}
Выведет только половину фразы. Почему это так — понятно? Почему недостаточно просто "переобозвать" функции чистыми — понятно?
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[65]: Мнение: объектно-ориентированное программирование — катастрофа на трилли
Здравствуйте, Mamut, Вы писали: M>Если она чиста, почему она приводит к сайд-эффектам?
Вы смотрите не туда.
Для упрощения восприятия давайте себе представим генерацию SQL-стейтментов на языке типа C#.
У нас может быть весьма-весьма сложная программа, которая занимается компоновкой SQL-батча.
Всякие условия, ветвления, циклы, ООП, прочая сложность. Но вся эта программа всего лишь порождает набор insert, update, и delete стейтментов.
Сколько бы раз мы её ни запускали, никаких изменений в базе происходить не будет. Она вообще может подключения к базе не иметь.
А вот потом, когда программа отработала, мы получаем готовый батч, который скармливаем в SQL Server, и уже он внезапно изменяет состояние базы.
Ясно, что это гораздо выгоднее, чем в каждом месте, где мы хотели сделать return from g in goods select g.Name, g.Price where g.VendorID = vendorId, сразу писать var r = db.ExecuteQuery("select g.Name, g.Price from goods g where g.VendorID = @vendorId", vendorId).
Во-первых, у нас могут быть "тупиковые" ветки, которые будут выброшены в процессе построения батча на основе условий, которые обнаружатся "в будущем".
Во-вторых, удерживать транзакцию открытой — плохо; поэтому перемежать обращения к базе с выполнением дорогостоящей client-side логики — дорого.
Ну, и в-третьих, у нас появляется феноменальная возможность выполнять регрессионное тестирование: вместо мучительных сравнений состояний базы, мы просто сравниваем тексты батчей "до" и "после".
Примерно так же поступает Хаскел с "внешним миром".
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[74]: Мнение: объектно-ориентированное программирование — катастрофа на трилли
Здравствуйте, samius, Вы писали:
ARK>>Отчего же? Значит, документация по языку таки нужна для суждения о чистоте написанных на нем функций? S>Представления о языке — нужны.
Нужны для чего именно? По-моему, для работы вряд ли может быть достаточно "представления", без глубокого понимания, которое может дать только документация по языку.
S>Документация, которую ты предлагаешь — нет. От такой надо держаться подальше.
Я предлагаю спецификацию языка и описание стандартной библиотеки. Это то место, которое содержит информацию, которую невозможно или затруднительно извлечь из кода.
ARK>>putStr невозможно заменить на значение, нельзя выкинуть при оптимизации, нельзя спекулятивно вычислить, нельзя поменять местами с другой putStr. Это типичная грязная функция. S>Ничего из перечисленного не имеет отношения к putStr и определению чистоты. С какого перепугу она стала грязной?
Перечисленное — это не определение чистоты, это следствие чистоты. Ничего из этого сделать с putStr нельзя, посему она не имеет никаких преимуществ чистых функций.
S>Так покажи что есть нечистого в putStr согласно определению из википедии.
Согласно определению в википедии, функция является грязной, если ее "evaluation" вызывает "performing IO". Я считаю, что "evaluation" функции "putStr" вызывает "performing IO", поэтому она грязная.
Ты трактуешь слово "evaluation" как создание computation. Но это жонглирование терминами. Потому что ты не можешь отличить "прямое evaluation" и "создание computation". На C# я могу создать computation и вызвать его, когда хочу. В хаскеле у меня нет выбора — ты можешь говорить, что создаешь computation, но нет разницы с тем, чтобы назвать это просто грязной функцией.
Вот программа:
import System.IO
import System.IO.Unsafe
test :: [Char]
test = unsafePerformIO $ do
putStrLn "CCC"
return "BBB"
main = do
putStrLn "AAA"
content <- getLine
putStrLn test
content <- getLine
putStrLn content
Вывод:
GHCi, version 8.6.5
AAA
33
CCC
BBB
2
=> 2
Так вот, если бы СНАЧАЛА на экран вывелось бы "CCC", которое идет через unsafePerformIO, то я бы согласился, что есть "промежуточный этап" — создание computation:
1) в момент создания computation выполняется unsafePerformIO и на экран выводится "CCC";
2) ЗАТЕМ внешний вычислитель выполняет созданный computation, и на экране появляется "AAA".
Но это не так. Создание computation — это фикция.
ARK>>То есть по сигнатуре функции в хаскеле нельзя сказать, является ли функция чистой? S>Конечно, одна лишь сигнатура не дает оснований для заявлений о чистоте.
Хорошо, зафиксируем этот момент.
ARK>>Тогда почему ты считаешь, что putStr — чистая функция? Так написано в документации хаскеля? S>Потому, что она выполняется на стадии выполнения main, когда computation всей программы еще не построен, ему еще не передано управление. Никакого смысла там что-то пачкать нет. Потому, что реализация putStr вызывает другую IO функцию, создающую вычисление. И кроме создания вычисления на этапе выполнения putStr больше ничего не происходит. Ничего вне контекста IO, который будет создан лишь для того, что бы передать его вычислению-результату main. S>Ну и разумеется, в исходниках видно, что кроме построения computation-а в putStr ничего не происходит.
Погоди. Стало быть, ты не можешь судить о чистоте функции иным образом, кроме как посмотрев в исходники или документацию по языку (от которой "надо держаться подальше" (с))? Так?
Тогда такой вопрос: каким образом, глядя в исходники, ты понимаешь, что функция putStr чиста? Она не вызывает никаких "грязных" функций, не так ли?
Re[74]: Мнение: объектно-ориентированное программирование — катастрофа на трилли
Здравствуйте, Sinclair, Вы писали:
ARK>>Так все-таки: может ли _в принципе_ семантика быть выраженной неявно? Я создаю форк С++ под названием C++PURE и заявляю, что в нем семантика computation выражена неявно. И, стало быть, все его функции автоматически становятся чистыми. Верно? S>Отож.
Странно, а samius говорит, что нет.
S>На всякий случай поясню очевидное: если у нас теперь любая int-функция возвращает не int, а computation, то вот такая программа: S>
int a()
S>{
S> printf("Hello,");
S> return 42;
S>}
S>int b()
S>{
S> printf(" world!);
S>}
S>int main()
S>{
S> auto varA = a();
S> auto varB = b();
S> return (rand() > 50) ? varA : varB;
S>}
S>Выведет только половину фразы. Почему это так — понятно? Почему недостаточно просто "переобозвать" функции чистыми — понятно?
Нет, не понятно по обоим пунктам.
Получившийся код эквивалентен следующему (псевдокод):
int main(IO io) -> (IO, int)
{
auto (varA, io1) = a(io);
auto (varB, io2) = b(io1);
return (io2, (rand() > 50) ? varA : varB);
}
Понятно, почему будет выведена фраза целиком? Понятно, почему _достаточно_ "переобозвать" функции чистыми?
Re[66]: Мнение: объектно-ориентированное программирование — катастрофа на трилли
·>Ты наверное что-то путаешь, абсолютизируя понятие чистоты. Говорят о чистоте именно _функций_. Эта _функция_ чиста и к сайд-эффектам не приводит. Однако, эта функция возвращает выражение, которое будет изменять внешний с т.з. _функций_ мир.
Я про это и говорю: Хаскель из кожи вон лезет, чтобы притвориться, что он чистый, а внешнего мира не существует.
Функция чистая, сайд эффектов нет, а в итоге сайд эффекты проявляются. Потому что если сильно зажмурить глаза, назвать внешний мир экшнами и притвориться, что наш язык не имеет к этим экшнам никакого отношения, то можно назвать язык чистым. Ведь это не функции меняют мир, как мы могли подумать, а некий магический внешний экзекьютор.
M>·>Ты наверное что-то путаешь, абсолютизируя понятие чистоты. Говорят о чистоте именно _функций_. Эта _функция_ чиста и к сайд-эффектам не приводит. Однако, эта функция возвращает выражение, которое будет изменять внешний с т.з. _функций_ мир. M>Я про это и говорю: Хаскель из кожи вон лезет, чтобы притвориться, что он чистый, а внешнего мира не существует.
Это только в твоём воображении.
M>Функция чистая, сайд эффектов нет, а в итоге сайд эффекты проявляются.
Ты говоришь как будто это что-то плохое.
M>Потому что если сильно зажмурить глаза, назвать внешний мир экшнами и притвориться, что наш язык не имеет к этим экшнам никакого отношения, то можно назвать язык чистым. Ведь это не функции меняют мир, как мы могли подумать, а некий магический внешний экзекьютор.
Язык называют чистым, т.к. по спеке там функции — чистые, просто терминология такая. Ты же обобщаешь чистоту как некую самоцель и она должна быть вообще везде. Это бред.
Чистота функций это же не самоцель, а такое свойство функций, которое позволяет ими манипулировать определённым образом с сохранением определённых гарантий.
M>Так любой язык является чисто функциональным.
Не является.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Если мы скомпилируем эту функцию и запустим получившуюся программу, мы будем наблюдать сайд-эффект. Хаскелисты при этом утверждают, что Хаскель не виноват. Есть какой-то внешний экзекьютор, который, конечно, к Хаскелю не имеет отношения, но без которого Хаскель не существует, как язык, который и занимается выполнением этих экшнов. Но тогда любая программа — чистый ФП. Потому никаких сайд эффектов не происходит ровно до момента запуска программы сторонним экзекьютором.
Здравствуйте, samius, Вы писали:
S>Это подход (один из), позволяющий писать абсолютно чистые программы. И я не могу запретить называть его мастурбацией, если так нравится. S>Надеюсь, разобрались с отрицанием существования чистых программ.
Абсолютно чистая — это без IO ? Или под этим подразумевается "чуточку грязная" ?
Re[67]: Мнение: объектно-ориентированное программирование — катастрофа на трилли
M>Я про это и говорю: Хаскель из кожи вон лезет, чтобы притвориться, что он чистый, а внешнего мира не существует.
и да и нет.
M>Функция чистая, сайд эффектов нет, а в итоге сайд эффекты проявляются. Потому что если сильно зажмурить глаза, назвать внешний мир экшнами и притвориться, что наш язык не имеет к этим экшнам никакого отношения, то можно назвать язык чистым. Ведь это не функции меняют мир, как мы могли подумать, а некий магический внешний экзекьютор.
в хаскеле не экшинами внешний мир меняется, там чистая функция на вход принимает RealWorl и на выходе возвращает новый инстанс RealWorl как бы модифицированный ею относительно входного. ментальная модель именно такая.
далее придуманы разные штуки (монады, do-нотация) для упрощения работы таким образом.
вообщем-то интересный трюк чтоб сохранить чистость функций.
Re[75]: Мнение: объектно-ориентированное программирование — катастрофа на трилли
Здравствуйте, AlexRK, Вы писали: ARK>Странно, а samius говорит, что нет.
Он более строг к формулировке утверждения "функция чиста".
S>>На всякий случай поясню очевидное: если у нас теперь любая int-функция возвращает не int, а computation, то вот такая программа: S>>
int a()
S>>{
S>> printf("Hello,");
S>> return 42;
S>>}
S>>int b()
S>>{
S>> printf(" world!);
S>>}
S>>int main()
S>>{
S>> auto varA = a();
S>> auto varB = b();
S>> return (rand() > 50) ? varA : varB;
S>>}
S>>Выведет только половину фразы. Почему это так — понятно? Почему недостаточно просто "переобозвать" функции чистыми — понятно?
ARK>Нет, не понятно по обоим пунктам.
Спрашивайте, что именно непонятно.
ARK>Получившийся код эквивалентен следующему (псевдокод): ARK>
ARK>Понятно, почему будет выведена фраза целиком?
Понятно. ARK>Понятно, почему _достаточно_ "переобозвать" функции чистыми?
В том-то и дело, что если бы функции возвращали вычисление, то вся фраза бы не выводилась. У нас была бы возможность вычислить только то из вычислений, которое нам нужно.
Ваша программа не позволяет скомпоновать вычисления сколь-нибудь другим способом, чем указанный порядок исполнения.
Поэтому подобное изменение спецификации С++ бессмысленно. А хаскелл тем временем вводит практически полезное определение чистоты функций.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[67]: Мнение: объектно-ориентированное программирование — катастрофа на трилли
Здравствуйте, Mamut, Вы писали:
M>Если мы скомпилируем эту функцию и запустим получившуюся программу, мы будем наблюдать сайд-эффект. Хаскелисты при этом утверждают, что Хаскель не виноват. Есть какой-то внешний экзекьютор, который, конечно, к Хаскелю не имеет отношения, но без которого Хаскель не существует, как язык, который и занимается выполнением этих экшнов. Но тогда любая программа — чистый ФП. Потому никаких сайд эффектов не происходит ровно до момента запуска программы сторонним экзекьютором.
Не совсем. Хаскел — это попытка официально разделить программы на "чистую" и "грязную" части, чтобы можно было безопасно рассуждать хотя бы об одной из этих частей.
Ну, вот продолжая нашу аналогию с SQL — понятно, что не всякая программа может построить полный батч "с нуля", не заглядывая в БД.
Но мы можем построить её так, что все точки взаимодействия с СУБД явно выделены, и вместо каши с перемешанными вызовами db.ExecuteXXX, внешних веб сервисов, и тяжёлых вычислительных задач, мы имеем явную цепочку readFromDb-Compute->readFromDb->Compute->WriteToDB.
Это по-прежнему предоставляет полезные гарантии по сравнению с лапшой. В частности, что джуниор не сможет вставить внезапное чтение или запись в середину очередного Compute и, например, поставить СУБД раком из-за дедлока.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[76]: Мнение: объектно-ориентированное программирование — катастрофа на трилли
ARK>>Понятно, почему _достаточно_ "переобозвать" функции чистыми? S>В том-то и дело, что если бы функции возвращали вычисление, то вся фраза бы не выводилась. У нас была бы возможность вычислить только то из вычислений, которое нам нужно.
Почему же, именно что при возврате вычислений все равно выводится фраза целиком. Ведь вызовы a и b имеют теперь зависимость друг от друга через IO.
S>Ваша программа не позволяет скомпоновать вычисления сколь-нибудь другим способом, чем указанный порядок исполнения.
Верно. Как и в хаскеле для всех функций с IO.
S>Поэтому подобное изменение спецификации С++ бессмысленно.
Подобное изменение спецификации С++ приведет к тому, что _формально_ все функции будут считаться чистыми. Что, на мой взгляд, есть лютый бред, обесценивающий все понятие чистоты функций.
S>А хаскелл тем временем вводит практически полезное определение чистоты функций.
Разница с хаскелем состоит только в том, что в хаскеле еще есть и "действительно чистые" функции, для которых возможны все полезные оптимизации и рассуждения. Вопрос состоит в том, зачем "онанировать вприсядку" (с), называя грязные функции чистыми, когда можно просто явно выделить чистые функции, как в D.
Re[68]: Мнение: объектно-ориентированное программирование — катастрофа на трилли
Здравствуйте, Sinclair, Вы писали:
S>Ну, вот продолжая нашу аналогию с SQL — понятно, что не всякая программа может построить полный батч "с нуля", не заглядывая в БД. S>Но мы можем построить её так, что все точки взаимодействия с СУБД явно выделены, и вместо каши с перемешанными вызовами db.ExecuteXXX, внешних веб сервисов, и тяжёлых вычислительных задач, мы имеем явную цепочку readFromDb-Compute->readFromDb->Compute->WriteToDB.
Для этого не обязательно делать то самое вприсядку, достаточно ввести понятие "pure function" (или наоборот — "io function"). Часть функций чистая, часть грязная. Все ОК.
Re[75]: Мнение: объектно-ориентированное программирование — катастрофа на трилли
Здравствуйте, AlexRK, Вы писали:
ARK>Здравствуйте, samius, Вы писали:
S>>Представления о языке — нужны.
ARK>Нужны для чего именно? По-моему, для работы вряд ли может быть достаточно "представления", без глубокого понимания, которое может дать только документация по языку.
Ты прав, документация нужна.
S>>Документация, которую ты предлагаешь — нет. От такой надо держаться подальше.
ARK>Я предлагаю спецификацию языка и описание стандартной библиотеки. Это то место, которое содержит информацию, которую невозможно или затруднительно извлечь из кода.
Первое твое предложение было таким: давайте ка заявим что там вместо int неявные computation. Такая документация заведомо противоречит другой документации того же языка и модели вычислений. Значит, одна из них будет врать.
ARK>>>putStr невозможно заменить на значение, нельзя выкинуть при оптимизации, нельзя спекулятивно вычислить, нельзя поменять местами с другой putStr. Это типичная грязная функция. S>>Ничего из перечисленного не имеет отношения к putStr и определению чистоты. С какого перепугу она стала грязной?
ARK>Перечисленное — это не определение чистоты, это следствие чистоты. Ничего из этого сделать с putStr нельзя, посему она не имеет никаких преимуществ чистых функций.
Здесь ты говоришь не о putStr, а о том, что она возвращает.
S>>Так покажи что есть нечистого в putStr согласно определению из википедии.
ARK>Согласно определению в википедии, функция является грязной, если ее "evaluation" вызывает "performing IO". Я считаю, что "evaluation" функции "putStr" вызывает "performing IO", поэтому она грязная.
Чуть ниже....
ARK>Ты трактуешь слово "evaluation" как создание computation. Но это жонглирование терминами. Потому что ты не можешь отличить "прямое evaluation" и "создание computation". На C# я могу создать computation и вызвать его, когда хочу. В хаскеле у меня нет выбора — ты можешь говорить, что создаешь computation, но нет разницы с тем, чтобы назвать это просто грязной функцией.
ARK>Вот программа: ARK>
ARK>Так вот, если бы СНАЧАЛА на экран вывелось бы "CCC", которое идет через unsafePerformIO, то я бы согласился, что есть "промежуточный этап" — создание computation: ARK>1) в момент создания computation выполняется unsafePerformIO и на экран выводится "CCC"; ARK>2) ЗАТЕМ внешний вычислитель выполняет созданный computation, и на экране появляется "AAA".
ARK>Но это не так. Создание computation — это фикция.
Вот здесь я должен сказать тебе спасибо. Даже не так, а СПАСИБО! Без иронии и сарказма. Твой пример кода заставил меня обратиться к документации и переосмыслить свое понимание. Ну а до этого толкнул штангу, в связи с чем должен принести извинения перед участниками за попытки (местами успешные) ввести в заблуждение. Относительно причин чистоты putStr.
Action в том виде, в котором я представлял реализацию putStr на C#, обладает фатальным недостатком. Он не может быть построен перед выполнением main, т.к. то значение строки, которое он должен вывести в консоль, может быть получено в результате работы программы. Оно не известно до начала проигрывания главного computation, точнее, не всегда известно.
Причины формальной чистоты putStr заключаются в частичном применении. Т.е. принимая строку в качестве единственного своего аргумента, она возвращает грязную функцию IO(), которая возьмет world1 и вернет world2, который уже со строкой в консоли.
Action никуда не делся. Я ошибался в месте и времени его формирования. Конечно, он формируется внутри цепочки action-ов main, а не заранее.
ARK>>>То есть по сигнатуре функции в хаскеле нельзя сказать, является ли функция чистой? S>>Конечно, одна лишь сигнатура не дает оснований для заявлений о чистоте.
ARK>Хорошо, зафиксируем этот момент.
ARK>>>Тогда почему ты считаешь, что putStr — чистая функция? Так написано в документации хаскеля? S>>Потому, что она выполняется на стадии выполнения main, когда computation всей программы еще не построен, ему еще не передано управление. Никакого смысла там что-то пачкать нет. Потому, что реализация putStr вызывает другую IO функцию, создающую вычисление. И кроме создания вычисления на этапе выполнения putStr больше ничего не происходит. Ничего вне контекста IO, который будет создан лишь для того, что бы передать его вычислению-результату main.
Сорри, это бред ^^^^^^
S>>Ну и разумеется, в исходниках видно, что кроме построения computation-а в putStr ничего не происходит.
ARK>Погоди. Стало быть, ты не можешь судить о чистоте функции иным образом, кроме как посмотрев в исходники или документацию по языку (от которой "надо держаться подальше" (с))? Так?
Судить могу, но как показывает опыт, не вполне адекватно. Заключение мое верно, но не его обоснование.
ARK>Тогда такой вопрос: каким образом, глядя в исходники, ты понимаешь, что функция putStr чиста? Она не вызывает никаких "грязных" функций, не так ли?
Не вызывает, хотя и создает грязный action, чернее мазута.