Re[5]: Ввод-вывод и чистые функции
От: novitk США  
Дата: 28.01.17 14:28
Оценка:
Здравствуйте, AlexRK, Вы писали:

NL>>Но тогда скажем функция `map` в D чистая или нет?

ARK>Понятия не имею, возможно есть два варианта этой функции.

Похоже они там просто не додумали.
http://stackoverflow.com/questions/5812186/pure-functional-programming-in-d

Unfortunately the interaction between generic code and pure (as well as const and immutable) is rather poor. There have been several proposals to fix this, but none have been accepted yet.
\std.algorithm is written to be as generic as possible, so it can't require that its lambda functions and the ranges it accepts be pure. Furthermore, the type system features that were added in D2 are generally the most buggy features in the language, because more basic things have been prioritized ahead of fixing the relevant issues. Right now, pure is basically not usable except for trivial cases like std.math.

Re[4]: Ввод-вывод и чистые функции
От: alex_public  
Дата: 28.01.17 14:43
Оценка:
Здравствуйте, Nick Linker, Вы писали:

NL>Но тогда скажем функция `map` в D чистая или нет? Как D мне запретит туда передать лямбду `println(_)`? А если запрещает, как мне тогда всё же передать `prinln()`?


Никто не запрещает, в том то и вся прелесть (в сравнение с Хаскелем). В тоже время у тебя в языке есть все механизмы для введения подобного запрета при желание (делается в одну короткую строчку). Т.е. язык даёт тебя полную свободу и плюс все необходимые инструменты для построения любого варианта.

Это всё следствия более общего вопроса в построение языка: мультипарадигменный он или нет. Современные удобные языки легко позволяют писать и в ООП стиле и ФП стиле и даже закопаться в МП. А можно смешать это всё в одном проекте и всё равно всё будет удобно. Именно поэтому у языка D (сильно мультипарадигменного) есть хоть какие-то шансы на большой успех (там уже больше от "политики" зависит), а у того же однопарадигменного Хаскеля таких шансов не было от рождения.

Это естественно речь о языках общего назначения. Для всяких всяческих DSL'ей однопарадигменность может быть вполне удобна.
Re[6]: Ввод-вывод и чистые функции
От: alex_public  
Дата: 28.01.17 15:01
Оценка:
Здравствуйте, novitk, Вы писали:

N>Похоже они там просто не додумали.

N>http://stackoverflow.com/questions/5812186/pure-functional-programming-in-d
N>

N>Unfortunately the interaction between generic code and pure (as well as const and immutable) is rather poor. There have been several proposals to fix this, but none have been accepted yet.
N>\std.algorithm is written to be as generic as possible, so it can't require that its lambda functions and the ranges it accepts be pure. Furthermore, the type system features that were added in D2 are generally the most buggy features in the language, because more basic things have been prioritized ahead of fixing the relevant issues. Right now, pure is basically not usable except for trivial cases like std.math.


Ерунда тут написана. Да, вся стандартная библиотека языка построена вокруг метапрограммирования (даже в большей степени чем STL в C++). Но при этом работа с атрибутами типов (в том числе и pure) легко доступна из этого самого МП — не требуются никакие доработки, уже всё отлично работает. Т.е. нет вообще никакой проблемы в написание обобщённой map с требованием на pure.

Другое дело (и это справедливо отмечено в заданном на SO вопросе), что реализации алгоритмов из стандартной библиотеки в данный момент ни сами не отмечены как pure, ни требуют этого от передаваемых в них функций. Правильно это или нет — это другой вопрос, зависящий на мой взгляд от того, какого больше стиля придерживается усреднённый программист на D. Но в любом случае у желающего есть все возможности сделать любой вариант. Ну и да, наверное в идеале в будущем иметь в стандартной библиотеке все возможные реализации. )
Re[6]: Ввод-вывод и чистые функции
От: AlexRK  
Дата: 28.01.17 15:08
Оценка:
Здравствуйте, novitk, Вы писали:

N>Похоже они там просто не додумали.


Не знаю, что там можно додумать. Тут либо оставить всё как есть (просто помечать функции как чистые), либо пихать в каждый вызов какую-то шнягу, запрещающую считать вызов ссылочно прозрачным.
Re[7]: Ввод-вывод и чистые функции
От: AlexRK  
Дата: 28.01.17 15:13
Оценка:
Здравствуйте, alex_public, Вы писали:

_>Другое дело (и это справедливо отмечено в заданном на SO вопросе), что реализации алгоритмов из стандартной библиотеки в данный момент ни сами не отмечены как pure, ни требуют этого от передаваемых в них функций.


Изначальный вопрос
Автор: Nick Linker
Дата: 28.01.17
как раз и был именно об этом.

_>Правильно это или нет — это другой вопрос, зависящий на мой взгляд от того, какого больше стиля придерживается усреднённый программист на D. Но в любом случае у желающего есть все возможности сделать любой вариант. Ну и да, наверное в идеале в будущем иметь в стандартной библиотеке все возможные реализации. )


В этой ветке как раз и мусолится вариант, что хорошо бы иметь функцию, подходящую "ко всему" — хоть к пуре, хоть к унпуре коду. Только вот лично мне пока не вполне ясно, как это можно (и можно ли) сделать просто (а не нагородив адской хрени а-ля Хаскель).
Re[8]: Ввод-вывод и чистые функции
От: alex_public  
Дата: 28.01.17 15:46
Оценка:
Здравствуйте, AlexRK, Вы писали:

_>>Правильно это или нет — это другой вопрос, зависящий на мой взгляд от того, какого больше стиля придерживается усреднённый программист на D. Но в любом случае у желающего есть все возможности сделать любой вариант. Ну и да, наверное в идеале в будущем иметь в стандартной библиотеке все возможные реализации. )

ARK>В этой ветке как раз и мусолится вариант, что хорошо бы иметь функцию, подходящую "ко всему" — хоть к пуре, хоть к унпуре коду. Только вот лично мне пока не вполне ясно, как это можно (и можно ли) сделать просто (а не нагородив адской хрени а-ля Хаскель).

В Хаскеле адская хрень исключительно потому, что там формально просто нет "не чистых" функций. ))) Это так сказать "язык с высокими принципами", а потому обречённый на маргинальное существование.

А в D как раз этим проблем нет: стандартный библиотечный map спокойно проглотит функцию и с модификатором pure и без него. Как ты и хочешь.

Другое дело, если ты хочешь какую-то отдельную реализацию для map с pure. Такое тоже элементарно делается в D (там же всё на МП). Более того, подобный код очень распространён в стандартной библиотеке, только не для pure, а для другого: во многих стандартных алгоритмах можно увидеть несколько разных реализации, а выбор нужной ветки происходит в зависимости от типа доступа к обрабатываем данным (например только последовательный доступ (подходит для всех случаев, но медленный) или же есть возможность произвольного(тогда алгоритм эффективнее)). Однако для pure мне пока не приходит в голову какая может быть от этого польза. В принципе гарантированная чистота функции даёт две известные дополнительные возможности при её использование: ленивость и мемоизация. Однако скажем для того же map эти возможности вряд ли применимы на практике, так что по идее код map не должен отличаться для чистых и не чистых функций.

Ну и плюс для особых фанатов строгости можно в две строчки определить свой my_map, который будет работать в точности как стандартный, но при этом иметь ограничение на чистоту передаваемой функции (т.е. компилятор будет ругаться, если передашь в my_map не чистую функцию).
Re[9]: Ввод-вывод и чистые функции
От: AlexRK  
Дата: 28.01.17 15:58
Оценка:
Здравствуйте, alex_public, Вы писали:

_>А в D как раз этим проблем нет: стандартный библиотечный map спокойно проглотит функцию и с модификатором pure и без него. Как ты и хочешь.


Если я верно понимаю, то это всего лишь значит, что map там грязный. Понятно, что грязная функция что угодно проглотит.

_>Другое дело, если ты хочешь какую-то отдельную реализацию для map с pure. Такое тоже элементарно делается в D (там же всё на МП).


Нехорошо получится, иметь две почти одинаковые функции. Как-то не комильфо. Чисто эстетически убого. Хотя с практической точки зрения может и хорошо.

_>Более того, подобный код очень распространён в стандартной библиотеке, только не для pure, а для другого: во многих стандартных алгоритмах можно увидеть несколько разных реализации, а выбор нужной ветки происходит в зависимости от типа доступа к обрабатываем данным (например только последовательный доступ (подходит для всех случаев, но медленный) или же есть возможность произвольного(тогда алгоритм эффективнее)).


Это все же другое, это особенности реализации функции. А для pure/unpure нам нужно две разных функции.

_>Однако для pure мне пока не приходит в голову какая может быть от этого польза. В принципе гарантированная чистота функции даёт две известные дополнительные возможности при её использование: ленивость и мемоизация. Однако скажем для того же map эти возможности вряд ли применимы на практике, так что по идее код map не должен отличаться для чистых и не чистых функций.


ИМХО, самое главное свойство — ссылочная прозрачность. Возможность заменить функцию от известных аргументов уже вычисленным значением. Чтобы сделать это с map, нам нужно два ограничения: сам map не должен содержать ввода-вывода (то бишь быть pure), плюс передаваемая в него функция тоже должна быть pure.

Таким образом, получаем два мапа — один чистый, один грязный. Кривовато...
Re[10]: Ввод-вывод и чистые функции
От: alex_public  
Дата: 29.01.17 14:39
Оценка:
Здравствуйте, AlexRK, Вы писали:

_>>А в D как раз этим проблем нет: стандартный библиотечный map спокойно проглотит функцию и с модификатором pure и без него. Как ты и хочешь.

ARK>Если я верно понимаю, то это всего лишь значит, что map там грязный. Понятно, что грязная функция что угодно проглотит.

И да и нет.

Она грязная с точки зрения отсутствия соответствующих атрибутов. Но сама то по построению очевидно чистая. Так что соответственно если передать в неё чистые аргументы, то и вся конструкция окажется чистой (опять же по построению, а не атрибутам типа).

_>>Более того, подобный код очень распространён в стандартной библиотеке, только не для pure, а для другого: во многих стандартных алгоритмах можно увидеть несколько разных реализации, а выбор нужной ветки происходит в зависимости от типа доступа к обрабатываем данным (например только последовательный доступ (подходит для всех случаев, но медленный) или же есть возможность произвольного(тогда алгоритм эффективнее)).

ARK>Это все же другое, это особенности реализации функции. А для pure/unpure нам нужно две разных функции.

Просто в D в силу развитого МП и наличия статической интроспекции частенько вместо использования перегрузки функции по типу аргумента применяется обобщённый аргумент, а где-то внутри тела функции размещено ветвление (отрабатывающее во время компиляции) на базе анализа типов аргументов.

ARK>Таким образом, получаем два мапа — один чистый, один грязный. Кривовато...


Ну как бы а какие ещё варианты? ) В других языках и такого нет. )))

Вообще я бы сделал одно исправление в механике работы D в этом смысле. Сейчас (во всяком случае на тот момент, когда я игрался с D — может за пару последних лет что-то и поменялось) атрибут pure устанавливается программистов и потом проверяется компилятором (если функция не удовлетворяет нужным условиям, то получаем ошибку компиляции). А бы предложил сделать наоборот: чтобы компилятор сам проверял все функции на предмет чистоты и в случае удовлетворения требований сам проставлял бы этот атрибут.

Если сделать такое изменение, то можно и расставить требование на pure во многих местах библиотеки. Потому что при таком раскладе оно не будет напрягать классических "императивных" программистов, которые не в курсе ни про какие pure и не собираются их использовать в своём коде.
Re[3]: Ввод-вывод и чистые функции
От: VladD2 Российская Империя www.nemerle.org
Дата: 29.01.17 22:52
Оценка:
Здравствуйте, Слава, Вы писали:

С>Тогда можно задать вопрос, а существуют ли хорошие и современные языки для программ, занимающихся в основном вводом-выводом.


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

Я вам один секрет открою. У функциональных языков нет никаких проблем с вводом выводом. Проблемы есть у ленивых языков. По жизни таких не так много. Хаскель и пара экспериментальных. Проблемы у них проистекают из того, что у них:
1. Порядок вычислений не проистекает из расположения выражений в коде.
2. Выполнение отложенное и может просто не производиться, если результат не нужен.

Если ФЯ является энергичным, то побочные эффекты в функциях работают так же как и в императивном языке. scala, Nemerle, F#, Ocaml и куча других языков не имеют никаких проблем с побочными эффектами.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[11]: Ввод-вывод и чистые функции
От: AlexRK  
Дата: 30.01.17 08:09
Оценка:
Здравствуйте, alex_public, Вы писали:

_>Она грязная с точки зрения отсутствия соответствующих атрибутов. Но сама то по построению очевидно чистая. Так что соответственно если передать в неё чистые аргументы, то и вся конструкция окажется чистой (опять же по построению, а не атрибутам типа).


Верно. Но мы таким образом теряем возможность рассуждать о свойствах программы, глядя в ее код. Видим где-то в середине шаблонного кода вызов map, но чистый он или нет — понять нельзя. Собственно, откуда мы вообще знаем, что map "чистый по построению"? Только посмотрев в исходники (а если их нет?). И если завтра Брайту взбредет в голову сунуть в map чтение файла, мы этого никак не заметим и компилятор нам ничего не скажет. Вот в этом проблема "чистоты по построению". Хотя эта проблема может выглядеть надуманной, мне она кажется весьма важной.

ARK>>Таким образом, получаем два мапа — один чистый, один грязный. Кривовато...

_>Ну как бы а какие ещё варианты? ) В других языках и такого нет. )))

Ну, вон в том же Хаскеле есть другой вариант — когда всё вокруг как будто чистое, но побочный эффект каким-то образом упаковывается в передаваемое внутрь значение и чистая функция как бы и ни при чем — ее эффект приплюсовывается поверх побочного эффекта и потом вся эта хрень выполняется грязным рантаймом (если я правильно понимаю идеологию). Но вот не уверен, что вся эта овчинка стоит выделки.

_>Вообще я бы сделал одно исправление в механике работы D в этом смысле. Сейчас (во всяком случае на тот момент, когда я игрался с D — может за пару последних лет что-то и поменялось) атрибут pure устанавливается программистов и потом проверяется компилятором (если функция не удовлетворяет нужным условиям, то получаем ошибку компиляции). А бы предложил сделать наоборот: чтобы компилятор сам проверял все функции на предмет чистоты и в случае удовлетворения требований сам проставлял бы этот атрибут.


Под "проставлял" имеется в виду не в смысле физически менял код, а просто учитывал это при оптимизациях? Ну, такое давно везде есть, по-моему. И, собственно, теряется главное преимущество явных пометок — возможность рассуждать о коде (о чем я писал выше).

_>Если сделать такое изменение, то можно и расставить требование на pure во многих местах библиотеки. Потому что при таком раскладе оно не будет напрягать классических "императивных" программистов, которые не в курсе ни про какие pure и не собираются их использовать в своём коде.


Вот тут не очень понял. Если pure уже проставлено, то чего с ним еще можно сделать? Или имеется в виду, что модификатор "pure" может быть при необходимости отменен компилятором, если он видит возможность нечистого вызова? Тогда опять же с такого модификатора нет особого толка, если он не дает гарантий...

UPD. А, кажется понял. Вы имеете в виду, что pure будет гарантировать именно ту самую "чистоту по построению", но не чистоту самого вызова. В принципе да, это неплохо.



В общем, по большому счету есть немного вариантов:
1) "железобетонное" pure — приходим к необходимости дублировать некоторые функции в чистом и грязном виде;
2) "мягкое" pure — необходимо учитывать весь контекст вызова, чтобы точно знать, pure оно или нет;
3) оверинженернутый подход а-ля Хаскель — приводит к распространению по коду "лифтингов";
4) вообще никакого контроля а-ля C/C++.

Криво — всё.

Лично мне из всех зол пока почему-то больше нравится вариант 1. Хотя, после некоторых размышлений, вариант 2 может быть даже и лучше.
Отредактировано 30.01.2017 8:21 AlexRK . Предыдущая версия .
Re[12]: Ввод-вывод и чистые функции
От: alex_public  
Дата: 30.01.17 14:55
Оценка:
Здравствуйте, AlexRK, Вы писали:

_>>Она грязная с точки зрения отсутствия соответствующих атрибутов. Но сама то по построению очевидно чистая. Так что соответственно если передать в неё чистые аргументы, то и вся конструкция окажется чистой (опять же по построению, а не атрибутам типа).

ARK>Верно. Но мы таким образом теряем возможность рассуждать о свойствах программы, глядя в ее код. Видим где-то в середине шаблонного кода вызов map, но чистый он или нет — понять нельзя. Собственно, откуда мы вообще знаем, что map "чистый по построению"? Только посмотрев в исходники (а если их нет?). И если завтра Брайту взбредет в голову сунуть в map чтение файла, мы этого никак не заметим и компилятор нам ничего не скажет. Вот в этом проблема "чистоты по построению". Хотя эта проблема может выглядеть надуманной, мне она кажется весьма важной.

Не, я согласен что явная аннотация важна. Я просто подчеркнул, что "грязнота" стандартного библиотечного map'а как раз и заключается только в отсутствие этой самой аннотации.

ARK>Ну, вон в том же Хаскеле есть другой вариант — когда всё вокруг как будто чистое, но побочный эффект каким-то образом упаковывается в передаваемое внутрь значение и чистая функция как бы и ни при чем — ее эффект приплюсовывается поверх побочного эффекта и потом вся эта хрень выполняется грязным рантаймом (если я правильно понимаю идеологию). Но вот не уверен, что вся эта овчинка стоит выделки.


Хаскель имеет право на существование исключительно как некий экспериментальный язык, на котором можно изучать различные новые идей в данной области.

_>>Вообще я бы сделал одно исправление в механике работы D в этом смысле. Сейчас (во всяком случае на тот момент, когда я игрался с D — может за пару последних лет что-то и поменялось) атрибут pure устанавливается программистов и потом проверяется компилятором (если функция не удовлетворяет нужным условиям, то получаем ошибку компиляции). А бы предложил сделать наоборот: чтобы компилятор сам проверял все функции на предмет чистоты и в случае удовлетворения требований сам проставлял бы этот атрибут.

ARK>Под "проставлял" имеется в виду не в смысле физически менял код, а просто учитывал это при оптимизациях? Ну, такое давно везде есть, по-моему. И, собственно, теряется главное преимущество явных пометок — возможность рассуждать о коде (о чем я писал выше).

Менял не код, а прототип функции (pure — это же атрибут типа). Который потом учитывается другими функциями (принимающими данную как параметр и т.п.).

_>>Если сделать такое изменение, то можно и расставить требование на pure во многих местах библиотеки. Потому что при таком раскладе оно не будет напрягать классических "императивных" программистов, которые не в курсе ни про какие pure и не собираются их использовать в своём коде.

ARK>Вот тут не очень понял. Если pure уже проставлено, то чего с ним еще можно сделать? Или имеется в виду, что модификатор "pure" может быть при необходимости отменен компилятором, если он видит возможность нечистого вызова? Тогда опять же с такого модификатора нет особого толка, если он не дает гарантий...

Нет, идея в том чтобы атрибут pure был в прототипе не только тех функций, где это проставил программист, но и у тех, которые просто удовлетворяют этому условию (но программист поленился поставить). Поясняю почему это важно:

Допустим у нас есть библиотечная функция X(F f), принимающая некую пользовательскую функцию. Идеологически f обязательно должна быть чистой, но в нашей стандартной библиотеке это требование не стоит (по историческим и политическим причинам, типа как сейчас в библиотеке D) и X принимает любые функции. Чем прикладные программисты активно пользуются, передавая в X свои функции f произвольного вида (и чистые и не чистые, но в любом случае все без атрибута pure, т.к. всем пофиг на него).

Теперь если мы при нынешней работе компилятора изменим прототип X так, что он будет требовать только pure F, то это сломает вообще весь прикладной код всех программистов, включая абсолютно корректный.

А если бы компилятор работал так, как описал, то введение такого требования для X сломало бы только код тех программистов, которые передавали в X функции с наличием побочных эффектов (т.е. по сути сломался бы как раз некорректный изначально код).

ARK>В общем, по большому счету есть немного вариантов:

ARK>1) "железобетонное" pure — приходим к необходимости дублировать некоторые функции в чистом и грязном виде;
ARK>2) "мягкое" pure — необходимо учитывать весь контекст вызова, чтобы точно знать, pure оно или нет;
ARK>3) оверинженернутый подход а-ля Хаскель — приводит к распространению по коду "лифтингов";
ARK>4) вообще никакого контроля а-ля C/C++.
ARK>Криво — всё.
ARK>Лично мне из всех зол пока почему-то больше нравится вариант 1. Хотя, после некоторых размышлений, вариант 2 может быть даже и лучше.

Я пока что особо серьёзно не раздумывал об этой проблеме. Но в одном я уверен точно: подобное решение должно быть опциональным (например как в D), а не навязываемым.
Re[13]: Ввод-вывод и чистые функции
От: novitk США  
Дата: 30.01.17 16:00
Оценка:
Здравствуйте, alex_public, Вы писали:

_>Не, я согласен что явная аннотация важна. Я просто подчеркнул, что "грязнота" стандартного библиотечного map'а как раз и заключается только в отсутствие этой самой аннотации.


А зачем ты это подчеркнул? В чем принципиальная важность? Если map грязный, то все что его использует тоже грязно, а это 99% кода, за исключением какой-то изолированной математики. И два map-a это не решение проблемы, потому что потом нужно два fold-а и вообще всего в std.algorithm или как оно там называется, и в результате ты получаешь тот же Хаскель с другой стороны.
Re[13]: Ввод-вывод и чистые функции
От: AlexRK  
Дата: 30.01.17 16:24
Оценка:
Здравствуйте, alex_public, Вы писали:

_>Нет, идея в том чтобы атрибут pure был в прототипе не только тех функций, где это проставил программист, но и у тех, которые просто удовлетворяют этому условию (но программист поленился поставить). Поясняю почему это важно:


А, теперь понятно. Такие функции автоматом пролезают в pure-места даже без соответствующей пометки. То бишь это разновидность моего пункта 1, только без требования расставлять везде модификатор "pure". В принципе звучит разумно. Хотя недостатки остаются — необходимость иметь по два варианта каждой функции, которая может быть вызвана как в pure, так и unpure контексте.
Re[12]: Ввод-вывод и чистые функции
От: Слава  
Дата: 30.01.17 16:54
Оценка:
Здравствуйте, AlexRK, Вы писали:

ARK>В общем, по большому счету есть немного вариантов:

ARK>1) "железобетонное" pure — приходим к необходимости дублировать некоторые функции в чистом и грязном виде;
ARK>2) "мягкое" pure — необходимо учитывать весь контекст вызова, чтобы точно знать, pure оно или нет;
ARK>3) оверинженернутый подход а-ля Хаскель — приводит к распространению по коду "лифтингов";
ARK>4) вообще никакого контроля а-ля C/C++.

5) Навешивать на функции пред- и пост- условия, наподобие, как это сделано в Ada Spark. Они дают более широкие гарантии, не только "чистота/не чистота".
Re[13]: Ввод-вывод и чистые функции
От: AlexRK  
Дата: 30.01.17 16:59
Оценка:
Здравствуйте, Слава, Вы писали:

С>Здравствуйте, AlexRK, Вы писали:


ARK>>В общем, по большому счету есть немного вариантов:

ARK>>1) "железобетонное" pure — приходим к необходимости дублировать некоторые функции в чистом и грязном виде;
ARK>>2) "мягкое" pure — необходимо учитывать весь контекст вызова, чтобы точно знать, pure оно или нет;
ARK>>3) оверинженернутый подход а-ля Хаскель — приводит к распространению по коду "лифтингов";
ARK>>4) вообще никакого контроля а-ля C/C++.

С>5) Навешивать на функции пред- и пост- условия, наподобие, как это сделано в Ada Spark. Они дают более широкие гарантии, не только "чистота/не чистота".


Это эквивалентно пункту 1.
Re[14]: Ввод-вывод и чистые функции
От: alex_public  
Дата: 30.01.17 20:48
Оценка:
Здравствуйте, novitk, Вы писали:

_>>Не, я согласен что явная аннотация важна. Я просто подчеркнул, что "грязнота" стандартного библиотечного map'а как раз и заключается только в отсутствие этой самой аннотации.

N>А зачем ты это подчеркнул? В чем принципиальная важность? Если map грязный, то все что его использует тоже грязно, а это 99% кода, за исключением какой-то изолированной математики.

С чего бы это? Как раз map в 99% кода используют как чистую функцию (просто потому что для грязных императивных целей есть гораздо более удобный foreach). Только вот:

1. Это никак формально не гарантируется компилятором (а вот в D это добавили)
2. Факт данной чистоты никак потом на практике не используется (в том числе и в D, причём скорее вследствие отсутствия соответствующих навыков у прикладных программистов).

N>И два map-a это не решение проблемы, потому что потом нужно два fold-а и вообще всего в std.algorithm или как оно там называется,


Ну как бы вообще говоря решение. Только совсем не изящное.

N>и в результате ты получаешь тот же Хаскель с другой стороны.


В том то и дело что нет. У Хаскеля тоже развито только одно направление. Просто оно противоположное классическим императивным языкам. А вот языка с развитыми обоими направлениями что-то не видно пока. В D заложена потенциальная возможность этого. Но на практике (в библиотеках, в прикладном коде) она почти не используется.
Re[15]: Ввод-вывод и чистые функции
От: novitk США  
Дата: 30.01.17 22:23
Оценка:
Здравствуйте, alex_public, Вы писали:

_>Не, я согласен что явная аннотация важна.

_>1. Это никак формально не гарантируется компилятором (а вот в D это добавили)
_>2. Факт данной чистоты никак потом на практике не используется (в том числе и в D, причём скорее вследствие отсутствия соответствующих навыков у прикладных программистов).
От меня ускользает смысл. ТС вроде за аннотацию, ты вроде тоже. 99% в D это обычные грязные функции без аннотации и написать на нем чистую функцию реально нельзя, так как комбинаторы тянут грязь. То есть по факту pure в нем не додумана и не используется.

N>>И два map-a это не решение проблемы, потому что потом нужно два fold-а и вообще всего в std.algorithm или как оно там называется,

_>Ну как бы вообще говоря решение. Только совсем не изящное.
int f(int i) pure {
    return i*i;
}
int h(int i) {
    writeln("Bad");
    return i*i;
}
int g(int function(int) pure func) pure {
    return func(10);
}
void main(string[ ] args)
{
   writeln(g(&f)); //no prob
   writeln(g(&h)); //???
}

main.d(18): Error: function main.g (int function(int) pure func) is not callable using argument types (int function(int i))
Как мне g переделать в грязную? Я надеюсь какой-то лифтинг все же есть и мне не надо переписывать g еще раз.

_>В D заложена потенциальная возможность этого. Но на практике (в библиотеках, в прикладном коде) она почти не используется.

Если функционал не используется, то в нем нет смысла. Пока есть сильное подозрение что авторы этой фичи в D просто не додумкали и/или не разобрались с матаном.
Re[4]: Ввод-вывод и чистые функции
От: D. Mon Великобритания http://thedeemon.livejournal.com
Дата: 31.01.17 07:36
Оценка: 14 (2)
Здравствуйте, Nick Linker, Вы писали:

ARK>>Ну, в языке D есть pure-функции, но при этом никаких лифтингов ни в какие монады там делать не надо.


NL>Но тогда скажем функция `map` в D чистая или нет? Как D мне запретит туда передать лямбду `println(_)`? А если запрещает, как мне тогда всё же передать `prinln()`?


Тут какой-то ерунды наговорили. В D map это не функция, это шаблон функции, генерик. Для шаблонов всегда работает автоматический вывод атрибутов, в том числе чистоты. Если в map передать чистую функцию, получится чистая функция. Если передать грязную — получится грязная.

import std.stdio, std.algorithm;

void myDirtyFun() { // используем map в грязной ф-ии
    auto xs = [1,2,3].map!((x) { write(x, " "); return x*2; }); 
    writeln(xs.sum);    
}

int myPureFun() pure { // используем map в чистой ф-ии
    auto xs = [1,2,3].map!(x => x*2);
    //write("hi"); // если раскомментировать, компилятор ругнется:
    // Error: pure function 'main.myPureFun' cannot call impure function 'std.stdio.write!string.write'
    return xs.sum;
}

void main(string[] argv) {
    myDirtyFun(); // 1 2 3 12
    writeln( myPureFun() ); // 12
}

https://dpaste.dzfl.pl/42460904b633
Re[7]: Ввод-вывод и чистые функции
От: D. Mon Великобритания http://thedeemon.livejournal.com
Дата: 31.01.17 07:39
Оценка:
Здравствуйте, alex_public, Вы писали:

_>Другое дело (и это справедливо отмечено в заданном на SO вопросе), что реализации алгоритмов из стандартной библиотеки в данный момент ни сами не отмечены как pure, ни требуют этого от передаваемых в них функций. Правильно это или нет — это другой вопрос, зависящий на мой взгляд от того, какого больше стиля придерживается усреднённый программист на D. Но в любом случае у желающего есть все возможности сделать любой вариант. Ну и да, наверное в идеале в будущем иметь в стандартной библиотеке все возможные реализации. )


Там уже есть все реализации автоматически. В стандартной библиотеке все на шаблонах, передаешь чистую функцию — получаешь чистую. Компилятор по-прежнему все контролирует, а код засирать не обязательно.
Re[12]: Ввод-вывод и чистые функции
От: D. Mon Великобритания http://thedeemon.livejournal.com
Дата: 31.01.17 07:45
Оценка: 2 (1)
Здравствуйте, AlexRK, Вы писали:

_>>Она грязная с точки зрения отсутствия соответствующих атрибутов. Но сама то по построению очевидно чистая. Так что соответственно если передать в неё чистые аргументы, то и вся конструкция окажется чистой (опять же по построению, а не атрибутам типа).


ARK>Верно. Но мы таким образом теряем возможность рассуждать о свойствах программы, глядя в ее код. Видим где-то в середине шаблонного кода вызов map, но чистый он или нет — понять нельзя. Собственно, откуда мы вообще знаем, что map "чистый по построению"? Только посмотрев в исходники (а если их нет?). И если завтра Брайту взбредет в голову сунуть в map чтение файла, мы этого никак не заметим и компилятор нам ничего не скажет.


Скажет. Если ты свою ф-ю описал как pure и вызываешь чужую вроде map, то компилятор убедится, что та чужая тоже чистая. Если Брайт вставит в map нечистоты, твоя ф-я, которая ее вызывает, не скомпилируется. map и другие ФВП в D не грязные, они с автоматическим выводом чистоты.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.