Oberon space
General Category => Общий раздел => Тема начата: vlad от Февраль 27, 2011, 03:19:08 am
-
Обсуждение как-то затерялось в общем потоке, поэтому решил выделить в отдельную тему.
Итак, из того, что было сказано, я понял, что смысл разделения процедура функция сводится к (поправьте):
1. Функция не имеет побочных эффектов.
2. Процедура не возвращает значения (или косвенно возвращает через OUT-аргументы).
По поводу пункта 1 у меня никаких возражений нет - да, хочется контролировать побочные эффекты. И такое разделение иметь полезно, пока мы имеем некий компромиссный ЯП (не хаскель ;)
По поводу пункта 2 - вообще непонятно зачем такое ограничение. Пусть возвращает нормальный результат. Зачем кому-то нужны OUT-параметры?
Далее по реализации. Если брать за базу оберон, то какие изменения нужны в языке, чтобы обеспечить пункт 1? Если ничего нельзя сделать - тогда извините, но такое разделение совсем не нужно и плодит лишние сущности.
Конкретно хочется услышать ответ на вопрос: если мы запрещаем из функции обращение ко всем "внешним" сущностям и ограничиваем аргументы простыми типами (даже не процедурными) - то что полезного можно получить из таких функций.
-
Конкретно хочется услышать ответ на вопрос: если мы запрещаем из функции обращение ко всем "внешним" сущностям и ограничиваем аргументы простыми типами (даже не процедурными) - то что полезного можно получить из таких функций.
Не "запрещаем", а "разрешаем только для чтения". Эти "внешние" сущности вполне могут выступать в качестве первичных данных, наряду с параметрами функции.
-
Конкретно хочется услышать ответ на вопрос: если мы запрещаем из функции обращение ко всем "внешним" сущностям и ограничиваем аргументы простыми типами (даже не процедурными) - то что полезного можно получить из таких функций.
Не "запрещаем", а "разрешаем только для чтения". Эти "внешние" сущности вполне могут выступать в качестве первичных данных, наряду с параметрами функции.
Поясните пожалуйста. Что значит для чтения? Вызывать другие функции очевидно можно? А процедуры?
-
Поясните пожалуйста. Что значит для чтения? Вызывать другие функции очевидно можно? А процедуры?
"Разрешены только для чтения" - это значит они могут быть использованы в качестве операнда в выражении, но им самим ничего нельзя присваивать.
Внутри описания функции могут быть вызовы других функций. Вызовы процедур в теле функции запрещены (правило 3), так как эти процедуры могут изменить глобальное состояние программы.
-
Поясните пожалуйста. Что значит для чтения? Вызывать другие функции очевидно можно? А процедуры?
"Разрешены только для чтения" - это значит они могут быть использованы в качестве операнда в выражении, но им самим ничего нельзя присваивать.
Внутри описания функции могут быть вызовы других функций. Вызовы процедур в теле функции запрещены (правило 3), так как эти процедуры могут изменить глобальное состояние программы.
Ага. Т.е., у нас остаются только глобальные переменные на чтение и другие функции. Правильно? И чего полезного такие функции могут посчитать?
P.S. Пока это очень похоже на плюсовый const, за исключением доступа к внешним сущностям.
-
И чего полезного такие функции могут посчитать?
Вторичные данные. То есть те данные, которыми мы не располагали до вызова функции.
Вопросики какие-то детские пошли :D
-
Ну, т.е. в лог например такая функция уже ничего не запишет.
-
Писать в лог всё-же лучше в том блоке, в котором содержится вызов процедуры. IMHO.
-
Писать в лог всё-же лучше в том блоке, в котором содержится вызов процедуры. IMHO.
+1
А то вчера функция была чистой, сегодня она должна что-то в лог писать, завтра ей понадобится из этого лога читать и менять результаты расчётов...
Что-то не то с этой функцией, неправильно как-то всё это...
Если нужно проверить работу функции -- так юнит-тесты для этого придуманы...
-
Писать в лог всё-же лучше в том блоке, в котором содержится вызов процедуры. IMHO.
Sorry, опечатался... :-\\ Вызов функции конечно, а не процедуры.
Ну, Geniepro правильно меня понял. :)
-
В этом плане у Хаскелла подход прост и прямолинеен:
Нужны функции, имеющие доступ к вводу/выводу и прочим прелестям побочных эффектов? Да нет проблем!
Но! Такая функция должна быть помечена как грязная, то есть имеющая побочные эффекты, и использовать её можно только в таких же грязных функциях. С проверкой компилятором, естественно.
Тогда функции, не помеченные как грязные, стопудово будут чистыми, и при возможности могут быть оптимизированы (ну там один раз посчитают, а потом много раз это посчитанное значение используют -- экономия времени, хотя и ценою памяти).
Upd. В некоем абстрактном языке можно считать, что функции -- всегда чисты, а процедуры имеют побочные эффекты. Тогда в процедурах можно вызывать функции, а вот в функциях вызывать процедуры нельзя.
Более того, вся работа с изменяемой памятью -- присваивания там всякие -- автоматически помечается как процедурная.
-
В хаскеле таки чистые функции могут писать в лог посредством монады Writer. От этого они менее чистыми не становятся :-)
-
Писать в лог всё-же лучше в том блоке, в котором содержится вызов процедуры. IMHO.
Проблема в том, что это не всегда возможно... Но все же что мы имеем...1. Пусть разделение на Ф и П продиктовано вами чисто из побуждения избавиться от побочного эффекта - произойдет ли это даже если ваши предложения будут реализованы ЯП? 2. Пусть Вы вводите это разделение просто для того, чтобы разделить "Чистые" и "Грязные" действия- насколько предложенная Вами форма адекватна цели... и вообще насколько это реализуемо на практике в компилляторах (т.е. проверка чистоты на низком уровне для проекта произвольной сложности). всегда ли она возможна?
-
2. Пусть Вы вводите это разделение просто для того, чтобы разделить "Чистые" и "Грязные" действия- насколько предложенная Вами форма адекватна цели... и вообще насколько это реализуемо на практике в компилляторах (т.е. проверка чистоты на низком уровне для проекта произвольной сложности). всегда ли она возможна?
Однако трансляторы Хаскелла показывают, что это вполне возможно и реализуемо.
-
Эта проверка вообще делается не на уровне компилятора, а посредством системы типов. Система типов естественно нужна сильнее нежели в обероне, или даже Аде. Ну и естественно побочные эффекты должны быть возможны только через стандартную библиотеку (где уже все это типизировано как надо).
Либо поддержку этой штуки (разделение на чистое и не чистое) закладывать непосредственно в язык, т.e. вместо общего решения получим частное, тогда да, поддержка со стороны компилятора нужна.
-
2. Пусть Вы вводите это разделение просто для того, чтобы разделить "Чистые" и "Грязные" действия- насколько предложенная Вами форма адекватна цели... и вообще насколько это реализуемо на практике в компилляторах (т.е. проверка чистоты на низком уровне для проекта произвольной сложности). всегда ли она возможна?
Однако трансляторы Хаскелла показывают, что это вполне возможно и реализуемо.
Я говорю про проекты ПОЛНОСТЬЮ реализованные на ЯП. Есть ли примеры создания на хаскеле очень сложных систем (БД, ОС) - без сторонних костылей (модулей написанных ДЛЯ ЭТОЙ задачи но на сторонних языках)? Пример, Вирт показал, что с помощью Оберона МОЖНО построить ОС.
-
Эта проверка вообще делается не на уровне компилятора, а посредством системы типов. Система типов естественно нужна сильнее нежели в обероне, или даже Аде. Ну и естественно побочные эффекты должны быть возможны только через стандартную библиотеку (где уже все это типизировано как надо).
Что вы имеете ввиду- RTTI? Но тип то всего лишь схема по которой создается реальный обьект (или связывается внешний обьект) у нас не меняется... меняется под воздействием факторов (обычно внешних по программе) сам обьект.
-
Есть ли примеры создания на хаскеле очень сложных систем (БД, ОС) - без сторонних костылей (модулей написанных ДЛЯ ЭТОЙ задачи но на сторонних языках)? Пример, Вирт показал, что с помощью Оберона МОЖНО построить ОС.
Очень сложные системы не делаются только на одном языке.
Виртовскую систему вряд ли можно назвать очень сложной системой, и то без вставок машинного кода даже Вирт в Обероне не обошёлся. Это не костыль разве?
На Хаскелле тоже делали операционки, House, например. http://en.wikipedia.org/wiki/House_(operating_system)
http://ogi.altocumulus.org/~hallgren/ICFP2005/
Исходников не видел, так что не могу сказать, что там кроме Хаскелла использовалось.
Был ещё пример, но щас так не попадается на глаза. Там микроядро ОС было написано на Хаскелле, но бут-загрузчик на ассемблере.
-
2. Пусть Вы вводите это разделение просто для того, чтобы разделить "Чистые" и "Грязные" действия- насколько предложенная Вами форма адекватна цели... и вообще насколько это реализуемо на практике в компилляторах (т.е. проверка чистоты на низком уровне для проекта произвольной сложности). всегда ли она возможна?
Однако трансляторы Хаскелла показывают, что это вполне возможно и реализуемо.
Я говорю про проекты ПОЛНОСТЬЮ реализованные на ЯП. Есть ли примеры создания на хаскеле очень сложных систем (БД, ОС) - без сторонних костылей (модулей написанных ДЛЯ ЭТОЙ задачи но на сторонних языках)? Пример, Вирт показал, что с помощью Оберона МОЖНО построить ОС.
Да. См. например http://en.wikipedia.org/wiki/House_(operating_system)
Есть распределенная система контроля версий Darcs. Есть веб-фреймворки и так далее.
Софта на хаскеле писано больше чем на обероне, и он реально используется.
Кстати, Оберон-система была не полностью на Обероне – там был и асм тоже.
-
Что вы имеете ввиду- RTTI? Но тип то всего лишь схема по которой создается реальный обьект (или связывается внешний обьект) у нас не меняется... меняется под воздействием факторов (обычно внешних по программе) сам обьект.
Нет. RTTI тут никаким боком (ибо RTTI это не система типов, а всего лишь информация о типах в рантайме).
-
Что вы имеете ввиду- RTTI? Но тип то всего лишь схема по которой создается реальный обьект (или связывается внешний обьект) у нас не меняется... меняется под воздействием факторов (обычно внешних по программе) сам обьект.
Нет. RTTI тут никаким боком (ибо RTTI это не система типов, а всего лишь информация о типах в рантайме).
Тогда что ? (я говорил про использование этой информации).
-
Все проверки на этапе компиляции. При чем тут rtti?
-
Эта проверка вообще делается не на уровне компилятора, а посредством системы типов....
Алексей я прицепился к этой части фразы... - не понял о чем идет речь-и сделал предположение что оно может гипотетчески означать.. давайте не будем уподобляться Илье.. если хотим что бы обсуждение имело хоть какой то смысл...
-
Ну, собственно, в Хаскелле контроль за побочными эффектами возложен именно на систему типов, с минимальной поддержкой со стороны компилятора: компилятор позволяет создать грязное значение, но не позволяет вытащить из него данные в чистый мир (что в IO попало, то там и пропало).
Ну а для тех, кто уж совсем не может без того, что бы не выстрелить себе в ногу из верёвки, всё-таки предусмотрели функцию unsafePerformIO, нарушающую эту защиту.
-
Алексей я прицепился к этой части фразы... - не понял о чем идет речь-и сделал предположение что оно может гипотетчески означать.. давайте не будем уподобляться Илье.. если хотим что бы обсуждение имело хоть какой то смысл...
Конечно. Если вдруг опять начну уподобляться, бейте меня по носу.
-
Разъясню для тех кто хаскелл в глаза не видел как оно там устроено (надеюсь знающие меня поправят, наверняка я где-то ошибусь):
В хаскеле по умолчанию нет побочных эффектов. Т.e. совсем нет. Все не изменно и так далее. Однако, очевидно что так жить нельзя :-) Поэтому в стандартной библиотеке есть множество функций позволяющих создавать изменяемые значения и менять их, лазить по памяти и что-то там ещё. Соответственно правило – из такой функции можно вызвать чистую функцию, из чистой функции вызвать такую функцию нельзя.
Теперь о том, как это правило реализуется: в хаскеле система типов, грубо говоря позволяет вешать тип на тип. То есть например функция у нас возвращает тип "A", мы можем написать функцию которая будет возвращать тип "B A". Причем если конструкторы типа B не экспортируются в модуле где определен B, то у тебя нет никакой возможности из значения типа "B A" получить нечто типа "A". При этом модуль где вводится тип B может иметь функцию преобразующая значение любого типа A (C,D,E… без разницы), в значение типа "B A".
Тип функций через которые возможны побочные эффекты имеют тип IO, конструкторы этого типа программисту не доступны. В хаскеле нет по сути statement'ов, соответственно там есть только выражения. Т.e. вызвать функцию с побочным эффектом и проигнорировать её тип не выйдет, её тип будет влиять на тип функции её вызвавшую. (всем очевидно, что в выражении a+b+c+d*z – типы переменных влияют на результат). Соответственно функция вызвавшая функцию с типом "IO что-то-там" также становится функцией типа "IO что-то-там' ".
Вот и всё. И никакой черной магии и поддержки со стороны компилятора конкретно этого. Просто система типов + отсутствие побочных эффектов в ЯЗЫКЕ (они в стандартной либе). Ну а автоматический вывод типов делает все это юзабельным (иначе потонули бы в ручной декларации типов). А монадный синтаксис делает это еще и читабельным.
Механизм общий, через него можно очень многое делать. Собственно управление побочными эффектами (IO) лишь малая толика того, что делают посредством этой системы типов.
-
Остаётся только добавить, что нет каких-то принципиальных ограничений на размеры систем, которые можно создать, используя такую систему типов.
Где-то может быть больше кода в области IO, где-то меньше. Это уже зависит от задачи и программистов-архитекторов...
-
Очень сложные системы не делаются только на одном языке.
Виртовскую систему вряд ли можно назвать очень сложной системой, и то без вставок машинного кода даже Вирт в Обероне не обошёлся. Это не костыль разве?
На Хаскелле тоже делали операционки, House, например. http://en.wikipedia.org/wiki/House_(operating_system)
http://ogi.altocumulus.org/~hallgren/ICFP2005/
Исходников не видел, так что не могу сказать, что там кроме Хаскелла использовалось.
Был ещё пример, но щас так не попадается на глаза. Там микроядро ОС было написано на Хаскелле, но бут-загрузчик на ассемблере.
Зависит от того что реализовано на нем (стороннем языке)-если элементарные операции по взаимодействию с железом - то (на мой взглят это приемлемо). Если диспетчер управления ресурсами - нет.
-
Ну, собственно, в Хаскелле контроль за побочными эффектами возложен именно на систему типов, с минимальной поддержкой со стороны компилятора: компилятор позволяет создать грязное значение, но не позволяет вытащить из него данные в чистый мир (что в IO попало, то там и пропало).
Ну а для тех, кто уж совсем не может без того, что бы не выстрелить себе в ногу из верёвки, всё-таки предусмотрели функцию unsafePerformIO, нарушающую эту защиту.
Причем тут Хаскелль -это судя по вашему описанию менеджер типов, что то на подобие менеджера кучи - кусок исполняемого кода который шлепается автоматически к программе. Вопрос - Решает введение его проблему или нет?
-
И чего полезного такие функции могут посчитать?
Вторичные данные. То есть те данные, которыми мы не располагали до вызова функции.
Вопросики какие-то детские пошли :D
Вопросик немного шире :) Данные в немаленьких системах не лежат настолько открыто, чтобы функции могли "прочитать" все что нужно. Данные инкапсулированы и скрыты за абстракциями. Т.е., разделение на процедуры/функции должно распространятся и на методы (связанные процедуры/функции). Такое уже есть в C++ (const методы), поэтому я хорошо представляю, что это такое. Вы не можете заранее (в абстрактном интерфейсе) определить будет ли метод функцией (const), потому что вы ничего не можете предполагать о реализации этого метода. В С++ эта проблема нивелируется наличием явного приведения к не-const и наличием mutable-данных. Поэтому в С++ наличие const у методов носит сугубо логический характер. Помечая метод const вы позволяете его вызов для const объекта. Не более того. Т.е., вызывая const метод вы не имеете никакой гарантий, что не будет сайд эффектов.
Следствие же вашего предложение будет таким, что функции вообще ничего полезного выдать не смогут и расширяться тоже не будут. Ну факториал посчитают, да. Массив переколбасят по какому-то жесткому алгоритму (без использования абстракций). А вот в лог уже не запишут. Зачем такая штука (в таком ограниченном виде) в языке - не представляю.
-
Причем тут Хаскелль -это судя по вашему описанию менеджер типов, что то на подобие менеджера кучи - кусок исполняемого кода который шлепается автоматически к программе. Вопрос - Решает введение его проблему или нет?
У Хаскеля статическая типизация. При статической типизации соответствие типов проверяются на этапе компиляции. Контроль побочных эффектов в хаскеле сведен к проверке типов так как описал я. Гм… Что-нибудь не ясно?
-
Причем тут Хаскелль -это судя по вашему описанию менеджер типов, что то на подобие менеджера кучи - кусок исполняемого кода который шлепается автоматически к программе. Вопрос - Решает введение его проблему или нет?
У Хаскеля статическая типизация. При статической типизации соответствие типов проверяются на этапе компиляции. Контроль побочных эффектов в хаскеле сведен к проверке типов так как описал я. Гм… Что-нибудь не ясно?
Ладно, господа давайте , подождем реакции Игоря-мне лично не очень понятно что он имел ввиду... на эту мысль наводят его определения....функций и процедур. В этой каше боюсь что мы просто будем не понимать друг друга. а когда договоримся окажется, что Игорем имелось ввиду нечто другое...
Предлагаю обменяться мнениями по сообщению Vlada.
-
По поводу пункта 1 у меня никаких возражений нет - да, хочется контролировать побочные эффекты. И такое разделение иметь полезно, пока мы имеем некий компромиссный ЯП (не хаскель ;)
По поводу пункта 2 - вообще непонятно зачем такое ограничение. Пусть возвращает нормальный результат. Зачем кому-то нужны OUT-параметры?
По поводу 1. Тоже как не странно :) Как я понял речь идет именно о разделении чистый -грязный (об устранении побочного эффекта речь не идет). Но зачем Ф и П -может хватит модификатора PURE в заголовке? Это по внешнему виду. Возникает вопрос как обеспечить это ?
По поводу 2. Cогласен.
-
По поводу 1. Тоже как не странно :) Как я понял речь идет именно о разделении чистый -грязный (об устранении побочного эффекта речь не идет). Но зачем Ф и П -может хватит модификатора PURE в заголовке? Это по внешнему виду. Возникает вопрос как обеспечить это ?
Посмотрите как это сделано в D : http://verypositive.com/files/d2.pdf
В статье найдите раздел "Функциональное программирование".
-
По поводу 1. Тоже как не странно :) Как я понял речь идет именно о разделении чистый -грязный (об устранении побочного эффекта речь не идет). Но зачем Ф и П -может хватит модификатора PURE в заголовке? Это по внешнему виду. Возникает вопрос как обеспечить это ?
Посмотрите как это сделано в D : http://verypositive.com/files/d2.pdf
В статье найдите раздел "Функциональное программирование".
Vlad- Вы про это говорили? В этой статье речь идет о формальном контороле на этапе компиляции отсутствия в тексте реализации глобальных сущностей (не передаваемых через интерфейс), Если используются внешние функции внутри реализации то возможность компиляции кода определяется сигнатурой вызова этой функции (если она помечена как чистая компиляция идет успешно). Вас такое решение устроит? :)
-
Вас такое решение устроит? :)
Простейший гемор - вы определяете набор совершенно чистых функций = которые прекрасно компилируются = но делаете из них DLL - и компилятор перестает считать их таковыми (Хотя они ими ОСТАЛИСЬ) ;)
-
не перестает, если у нас сохранился интерфейс к этим функциям.
-
не перестает, если у нас сохранился интерфейс к этим функциям.
То есть вы предлагаете реализовать это в виде скрытого параметра?
-
Vlad- Вы про это говорили? В этой статье речь идет о формальном контороле на этапе компиляции отсутствия в тексте реализации глобальных сущностей (не передаваемых через интерфейс), Если используются внешние функции внутри реализации то возможность компиляции кода определяется сигнатурой вызова этой функции (если она помечена как чистая компиляция идет успешно). Вас такое решение устроит? :)
Устроит, как только я пойму как будет работать такое:
struct X
{
virtual void do() = 0;
};
void f(X &x) // pure или не pure?
{
x.do();
}
Еще раз хочу заметить: по моему убеждению мы не можем пометить X::do как pure, потому что мы не знаем заранее - сможет ли ее наследник реализовать как pure.
Почти тоже самое в другой формулировке (без ООП):
void f(F prediacte); // f может быть pure только если F - тоже pure
Что делать, если нам нужно вызвать f, а на руках у нас не-pure predicate?
-
не перестает, если у нас сохранился интерфейс к этим функциям.
То есть вы предлагаете реализовать это в виде скрытого параметра?
Я так понимаю - просто в имени DLL-функции будет зашифровано pure она или нет. Как сейчас шифруются типы параметров для С++ функций.
-
не перестает, если у нас сохранился интерфейс к этим функциям.
То есть вы предлагаете реализовать это в виде скрытого параметра?
Во-первых в dll хранятся только имена функций, про параметры (скрытые или нет) там ничего нет.
Во-вторых в виде скрытого параметра если передавать, то у нас контроль опять будет в рантайме, а нам нужно по возможности в компайл-тайме.
Так что все будет да, в простейшем случае зашифровано в имени функции.
-
Vlad- Вы про это говорили? В этой статье речь идет о формальном контороле на этапе компиляции отсутствия в тексте реализации глобальных сущностей (не передаваемых через интерфейс), Если используются внешние функции внутри реализации то возможность компиляции кода определяется сигнатурой вызова этой функции (если она помечена как чистая компиляция идет успешно). Вас такое решение устроит? :)
Устроит, как только я пойму как будет работать такое:
struct X
{
virtual void do() = 0;
};
void f(X &x) // pure или не pure?
{
x.do();
}
Еще раз хочу заметить: по моему убеждению мы не можем пометить X::do как pure, потому что мы не знаем заранее - сможет ли ее наследник реализовать как pure.
Почти тоже самое в другой формулировке (без ООП):
void f(F prediacte); // f может быть pure только если F - тоже pure
Что делать, если нам нужно вызвать f, а на руках у нас не-pure predicate?
1. Не чистая - просто потому что она (Do) обьявлена без модификатора
2.Просто f не обьявлять как чистую
-
То есть полиморфизм плюсовый действительно накрывается медным тазиком- но и без него ведь люди живут ;)
-
Vlad- Вы про это говорили? В этой статье речь идет о формальном контороле на этапе компиляции отсутствия в тексте реализации глобальных сущностей (не передаваемых через интерфейс), Если используются внешние функции внутри реализации то возможность компиляции кода определяется сигнатурой вызова этой функции (если она помечена как чистая компиляция идет успешно). Вас такое решение устроит? :)
Устроит, как только я пойму как будет работать такое:
struct X
{
virtual void do() = 0;
};
void f(X &x) // pure или не pure?
{
x.do();
}
Еще раз хочу заметить: по моему убеждению мы не можем пометить X::do как pure, потому что мы не знаем заранее - сможет ли ее наследник реализовать как pure.
Почти тоже самое в другой формулировке (без ООП):
void f(F prediacte); // f может быть pure только если F - тоже pure
Что делать, если нам нужно вызвать f, а на руках у нас не-pure predicate?
1. Не чистая - просто потому что она (Do) обьявлена без модификатора
Если я f() объявлю как pure, то что будет:
1. Не скомпилится (вызов x.do() - не-pure)
2. Ошибка в рантайме, если конкретная реализация x.do является не-pure
Если 1 - то это то, о чем я говорил в самом начале (мало для чего можно использовать такие pure функции).
Если 2 - то мне такое принципиально не нравится
2.Просто f не обьявлять как чистую
Тогда приходим к тому, что любой обобщенный (библиотечный) код у нас будет не-pure. Т.е. использование pure сведется к каким-то мелким локальным вещам.
-
Еще раз хочу заметить: по моему убеждению мы не можем пометить X::do как pure, потому что мы не знаем заранее - сможет ли ее наследник реализовать как pure.
А что нам мешает ТРЕБОВАТЬ от наследника PURE реализации?
-
Еще раз хочу заметить: по моему убеждению мы не можем пометить X::do как pure, потому что мы не знаем заранее - сможет ли ее наследник реализовать как pure.
А что нам мешает ТРЕБОВАТЬ от наследника PURE реализации?
Ну вот смотрите, я определил интерфейс X с "pure do()" и написал классную pure функцию:
void f(X &x) pure
{
x.do(); // pure
}
Теперь я вас прошу реализовать мне x::do. Как вы будете ее реализовывать, если вам для этого нужно прочитать файл? Вы придете ко мне и скажете, чтобы я убрал pure из f и из X::do? А если я работаю в другой конторе, а вы лишь используете мой классный расширяемый фрэймворк?
-
Еще раз хочу заметить: по моему убеждению мы не можем пометить X::do как pure, потому что мы не знаем заранее - сможет ли ее наследник реализовать как pure.
А что нам мешает ТРЕБОВАТЬ от наследника PURE реализации?
Ну вот смотрите, я определил интерфейс X с "pure do()" и написал классную pure функцию:
void f(X &x) pure
{
x.do(); // pure
}
Теперь я вас прошу реализовать мне x::do. Как вы будете ее реализовывать, если вам для этого нужно прочитать файл? Вы придете ко мне и скажете, чтобы я убрал pure из f и из X::do? А если я работаю в другой конторе, а вы лишь используете мой классный расширяемый фрэймворк?
Значит ваш фреймворк не является классным - вы на этапе проектирования его заложили чистоту в действие по своей сути грязное... И потом - Vlad- я не знаю ни одного идеального проектного решения ни языка на все случаи жизни, и у меня нет оснований считать что они существуют. А у Вас?
-
Значит ваш фреймворк не является классным
Ну вот я об этом и говорил. В таком виде - бесполезная штука. Не могу я помечать в интерфейсе функцию pure без риска получить плохую расширяемость. Соответственно, не могу использовать абстрактные аргументы в pure-функциях. Соответственно, использование pure функций ограничивается локальными штуками типа вычисления факториала - неюзабельно :)
-
Ну вот я об этом и говорил. В таком виде - бесполезная штука. Не могу я помечать в интерфейсе функцию pure без риска получить плохую расширяемость. Соответственно, не могу использовать абстрактные аргументы в pure-функциях. Соответственно, использование pure функций ограничивается локальными штуками типа вычисления факториала - неюзабельно :)
А что вы хотите ? На одно место сесть и конфетку съесть - и так все время ? - не реализуемо (ИМХО) ;)
-
Но поднимается интересный вопрос - если система чистоты в хаскеле устроена подобным образом (?) то и ограничения у него теже.... Что скажут по этому поводу Хаскеловоды?
-
А Хаскель не ООП-язык, поэтому у него подобных проблем нет :-)
-
А Хаскель не ООП-язык, поэтому у него подобных проблем нет :-)
А как же сложные задачи и фрамеворки ;) ?
-
Ну вот я об этом и говорил. В таком виде - бесполезная штука. Не могу я помечать в интерфейсе функцию pure без риска получить плохую расширяемость. Соответственно, не могу использовать абстрактные аргументы в pure-функциях. Соответственно, использование pure функций ограничивается локальными штуками типа вычисления факториала - неюзабельно :)
А что вы хотите ? На одно место сесть и конфетку съесть - и так все время ? - не реализуемо (ИМХО) ;)
Конкретно чего я хочу от pure-функций (или аналогов): спокойно запускать их параллельно без риска получить известные проблемы. Спокойно - это значит, что компилятор все проконтролирует на этапе компиляции.
Все остальные выстрелы в ногу - мне не очень интересны, потому что я уже научился их избегать даже в С++ :) А вот безопасная многопоточность - покоя не дает.
-
А кстати, давайте уже уйдем (на время) от абстрактных foo да boo, и перейдем к конкретным примерам. Скажем попробуем написать (на уровне спецификаций) какой-нибудь мегафреймворк. Так сказать, будем плясать от практики. Выбирайте предметную область :-)
-
А Хаскель не ООП-язык, поэтому у него подобных проблем нет :-)
А как же сложные задачи и фрамеворки ;) ?
А зачем для них ООП? :-) ООП провалился же ;-)
-
Ну вот я об этом и говорил. В таком виде - бесполезная штука. Не могу я помечать в интерфейсе функцию pure без риска получить плохую расширяемость. Соответственно, не могу использовать абстрактные аргументы в pure-функциях. Соответственно, использование pure функций ограничивается локальными штуками типа вычисления факториала - неюзабельно :)
Если серьезно по этому поводу - Положим вы проектируете корабль , поясните зачем вам предусматривать трансформацию его в поезд метро? (на случай войны? ;))
-
Ну вот я об этом и говорил. В таком виде - бесполезная штука. Не могу я помечать в интерфейсе функцию pure без риска получить плохую расширяемость. Соответственно, не могу использовать абстрактные аргументы в pure-функциях. Соответственно, использование pure функций ограничивается локальными штуками типа вычисления факториала - неюзабельно :)
Если серьезно по этому поводу - Положим вы проектируете корабль , поясните зачем вам предусматривать трансформацию его в поезд метро? (на случай войны? ;))
Аналогия неточна. В случае pure вы скорее декларируете использование только определенного материала. И если в момент декларации корабли строили только из дерева и это был очень даже хороший и очевидный материал, то к 21 веку появились более другие и неочевидные (в 16 веке) альтернативы. Вы конечно можете продолжать строить яхты с помощью такого фрэймворка, но вот с авианосцем - будут проблемы.
-
Посетила мысль в догонку - а если мы по умолчанию сделаем все PURE , а помечать будем IMPURЕ... что у нас получится игого ОберХаскелль ? ;)
-
Аналогия неточна. В случае pure вы скорее декларируете использование только определенного материала. И если в момент декларации корабли строили только из дерева и это был очень даже хороший и очевидный материал, то к 21 веку появились более другие и неочевидные (в 16 веке) альтернативы. Вы конечно можете продолжать строить яхты с помощью такого фрэймворка, но вот с авианосцем - будут проблемы.
Не будьте занудой :) Вы же поняли меня... или хотит-те что бы я занудно на 2 страницы подробно пояснил что я имею ввиду? Если это - то не дождетесь! ;)
-
А кстати, давайте уже уйдем (на время) от абстрактных foo да boo, и перейдем к конкретным примерам. Скажем попробуем написать (на уровне спецификаций) какой-нибудь мегафреймворк. Так сказать, будем плясать от практики. Выбирайте предметную область :-)
Лучше язык - на закуску осталась рантайм безопасное создание переменных (для пользовательских типов)- для этого см. предложения берсеркера... если не заморачиваться синтаксисом ь то останутся деструкторы, и обработчик ошибок при создании экземпляра переменной (конструкторы вроде есть)- ну почти шарпей с паскалеподобным синтаксисом ;) Ой ей ей это почти богохульство... спасает что мы не "Corn"ые - а то уже бы пришел дядька культен - жандарм и оприходовал бы меня в отстойник в пять двадцать пятый раз... :)
-
Ну, собственно, в Хаскелле контроль за побочными эффектами возложен именно на систему типов.
...
Ладно, господа давайте , подождем реакции Игоря-мне лично не очень понятно что он имел ввиду... на эту мысль наводят его определения....функций и процедур.
Может быть я разочарую публику, но честно должен признаться что не компетентен в Хаскеле. Так что здесь пока без комментариев.
Как я понял речь идет именно о разделении чистый -грязный (об устранении побочного эффекта речь не идет). Но зачем Ф и П -может хватит модификатора PURE в заголовке? Это по внешнему виду. Возникает вопрос как обеспечить это ?
Введение модификатора сулит, казалось бы, дополнительную гибкость: хочешь - объявляй чистую функцию, а хочешь - грязную. Но здесь не всё так просто. По большому счёту нужно чтобы не только функции были чистыми, но и выражения. У выражения и у функции схожая цель: вычислить значение. Хотя средства, ну и нотация, могут быть разные.
Представьте себе. Сегодня вот эта функция была у нас чистая, а завтра мы решили её сделать грязной (убрали модификатор PURE и добавили в неё вывод в лог). Но при этом все выражения в которых она была использована в качестве операнда, мгновенно стали грязными. Теперь нам надо отыскать все 120 этих выражений, разбросанных по 30 модулям, и в каждом из этих случаев решить критично это изменение или нет.
Простейший гемор - вы определяете набор совершенно чистых функций = которые прекрасно компилируются = но делаете из них DLL - и компилятор перестает считать их таковыми (Хотя они ими ОСТАЛИСЬ) Wink
А вот тут стоп! Использование DLL - это платформозависимый вопрос. Правила платформы легко могут вступить в противоречие с правилами языка, который мы используем. И вообще, все внешние сущности (например, из DLL) не обязаны подчиняться правилам нашего языка. Уповать на то, что вот эта DLL была написана на нашем языке, в общем случае не приходится.
Данные в немаленьких системах не лежат настолько открыто, чтобы функции могли "прочитать" все что нужно. Данные инкапсулированы и скрыты за абстракциями. Т.е., разделение на процедуры/функции должно распространятся и на методы (связанные процедуры/функции).
Мне кажется более правильным подход к инкапсуляции, принятый в Оберонах, нежели в классическом ООП. В Оберонах любые поля и методы любого объекта, объявленного в каком-либо модуле, доступны из любой точки этого модуля. Так что, исходный посыл, что "данные инкапсулированы и скрыты за абстракциями" получается как бы не верен.
Насчёт того, что методы также должны разделяться на процедуры/функции, согласен с Вами.
Кстати, здесь встаёт интересный вопрос, а разрешить ли методам-функциям (чистым) изменение полей своего объекта? Здесь Вы меня застали врасплох :) Надо бы здесь хорошенько подумать, можно сообща.
Вы не можете заранее (в абстрактном интерфейсе) определить будет ли метод функцией (const), потому что вы ничего не можете предполагать о реализации этого метода.
Да, в С++ не могу ничего утверждать. Ну, а в нашем абстрактном (пока) языке могу. Если метод в абстрактном интерфейсе был объявлен как function, то и все его реализации должны быть функциями. То есть не допускается полиморфизм такого рода, что функция в наследниках превращается в процедуру, и наоборот.
Что касается того, что чистые функции очень маленькие (игрушечные) и потому почти бесполезны, то это не справедливо по отношению к функциям. Функции могут быть исключительно сложны. Например, функция может вычислять оптимальный коэффициент по Калману для стохастической ситемы N-того порядка. Такую функцию ещё и разбивать придётся на вложенные функции. Несколько страниц точно займёт. :D
-
Кстати, здесь встаёт интересный вопрос, а разрешить ли методам-функциям (чистым) изменение полей своего объекта?
Подобные действия со стороны какой-либо функции автоматически означают, что эта функция грязная.
-
Представьте себе. Сегодня вот эта функция была у нас чистая, а завтра мы решили её сделать грязной (убрали модификатор PURE и добавили в неё вывод в лог). Но при этом все выражения в которых она была использована в качестве операнда, мгновенно стали грязными. Теперь нам надо отыскать все 120 этих выражений, разбросанных по 30 модулям, и в каждом из этих случаев решить критично это изменение или нет.
Сложно представить, насколько грязной нужно сделать функцию, чтобы стало критично найти все выражения с такой функцией (в не-pure функциях)...
Данные в немаленьких системах не лежат настолько открыто, чтобы функции могли "прочитать" все что нужно. Данные инкапсулированы и скрыты за абстракциями. Т.е., разделение на процедуры/функции должно распространятся и на методы (связанные процедуры/функции).
Мне кажется более правильным подход к инкапсуляции, принятый в Оберонах, нежели в классическом ООП.
В оберонах тоже есть абстрактные типы данных... Так что эта проблема для оберонов тоже актуальна.
Если метод в абстрактном интерфейсе был объявлен как function, то и все его реализации должны быть функциями. То есть не допускается полиморфизм такого рода, что функция в наследниках превращается в процедуру, и наоборот.
См. моей ответ Dizer. Объявляя функцию интерфейса pure, я рискую сделать фрэймворк неюзабельным, потому что никто не сможет реализовать такую функцию как pure.
Что касается того, что чистые функции очень маленькие (игрушечные) и потому почти бесполезны, то это не справедливо по отношению к функциям. Функции могут быть исключительно сложны. Например, функция может вычислять оптимальный коэффициент по Калману для стохастической ситемы N-того порядка. Такую функцию ещё и разбивать придётся на вложенные функции. Несколько страниц точно займёт. :D
Это все числодробильные штуки. С ними, как я уже говорил, не очень интересно, потому что и так все легко котроллируется: входные данные известны (массивы, простые типы), смотрим чтобы такой модуль ничего лишнего не импортил (а ему и не надо) и все.
-
Насчёт DLL вопрос непонятен. У DLL есть определённый формат описания функций, содержащихся в ней, и там нет упоминаний чисты эти функции или нет, как и вообще описания типов этих функций.
Так что программа на этом гипотетическом языке по-любому должна будет воспользоваться дополнительным интерфейсом, написанным вручную для этой DLL. И вот там уже программисту, описывающему этот интерфейс, нужно думать, как описать функции в этой DLL -- как чистые или как грязные. И если он пометит как чистую функцию, грязную на самом деле, то он сам себе злобный буратина.
Если же понадобится делать что-то типа DLL, но специально для этого языка, то там всё это должно быть прописано --и тип, и чистота. Ну а то, что эта библиотека окажется несовместимой с Win32 DLL, так ни дотнетчики, ни оберонщики этим не заморачиваются...
-
Кстати, здесь встаёт интересный вопрос, а разрешить ли методам-функциям (чистым) изменение полей своего объекта?
Подобные действия со стороны какой-либо функции автоматически означают, что эта функция грязная.
С одной стороны это так. А с другой стороны методы для того и предназначены, чтобы изменять состояние объекта. В классическам ООП поля объектов вроде вообще нельзя изменять напрямую, только через методы. Так вот. Имеет ли смысл рассматривать поля объекта как "продолжение" результата функции? Я склоняюсь к тому, что нет, не стОит. Но полной уверенности в удачности такого решения пока нет.
-
В классическам ООП поля объектов вроде вообще нельзя изменять напрямую, только через методы.
ООП в стиле Эрланга...
-
Это все числодробильные штуки. С ними, как я уже говорил, не очень интересно, потому что и так все легко котроллируется: входные данные известны (массивы, простые типы), смотрим чтобы такой модуль ничего лишнего не импортил (а ему и не надо) и все.
vlad, Вы всё время подчёркиваете ограниченность применения чистых функций. Да, так и есть, их применение ограниченно. Но в этом нет большой беды, ведь процедуры-то никуда не делись, они остались с нами. Пользуйтесь наздоровье :)
Ещё, если мы говорим об универсальном языке программирования, то неуместно говорить "это мне интересно, это - не очень". Хотя в другом контексте в этих заявлениях нет ничего плохого :)
-
У Хаскеля статическая типизация. При статической типизации соответствие типов проверяются на этапе компиляции. Контроль побочных эффектов в хаскеле сведен к проверке типов так как описал я. Гм… Что-нибудь не ясно?
И так господа Хаскеловоды -обьяснитесь - причем тут проверка типов? - на попытку разжевывания вы потратили страницу, или в хаскеле под чистотой понимается нечто другое?
-
С ними, как я уже говорил, не очень интересно, потому что и так все легко котроллируется: входные данные известны (массивы, простые типы), ...
Нужно стремиться к тому, чтобы всё контроллировалось не только легко, но и по возможности автоматически, то есть компилятором.
Идём дальше.
Чистые функции позволяют нам ввести выражения вида: a < b < c. Что равносильно (a < b) & (b < c).
Почему эту привычную математическую нотацию нельзя ввести без требования чистоты функций? Потому что границы диапазона могут вычисляться при помощи функции:
с := 9;
IF MinVal() < b < c THEN ...
Если функция MinVal() грязная, то она может изменить переменную b и c ещё до того, как дело дойдёт до сравнения. В 90 процентах случаев - это не то, что ожидает программист.
На этом моменте долго можно не останавливаться, уже обсуждалось на OberonCore.
-
Можно привести пример и похуже:
IF a < Val() THEN ...
Как насчёт постусловия a < Val()?
При сравнении будет использовано значение переменной a, которое было ДО выполнения функции Val(), или ПОСЛЕ?
-
И так господа Хаскеловоды -обьяснитесь - причем тут проверка типов? - на попытку разжевывания вы потратили страницу, или в хаскеле под чистотой понимается нечто другое?
Любые действия, имеющие побочные эффекты, помечаются как имеющие тип IO, то есть ввод/вывод.
Если тип функции не помечен как IO, функция заведомо чистая. Типы функций контролируются системой типов. Если при проверке типа функции оказывается, что где-то внутри неё используется IO, то и вся функция помечается как имеющая тип IO.
-
И так господа Хаскеловоды -обьяснитесь - причем тут проверка типов? - на попытку разжевывания вы потратили страницу, или в хаскеле под чистотой понимается нечто другое?
Любые действия, имеющие побочные эффекты, помечаются как имеющие тип IO, то есть ввод/вывод.
Если тип функции не помечен как IO, функция заведомо чистая. Типы функций контролируются системой типов. Если при проверке типа функции оказывается, что где-то внутри неё используется IO, то и вся функция помечается как имеющая тип IO.
Господа .... я говор про другое - в предложенном сейчас D методе - речь идет не о ТИПАХ а о ПЕРЕМЕННЫХ - это РАЗНЫЕ сущности , разве нет?
-
Господа .... я говор про другое - в предложенном сейчас D методе - речь идет не о ТИПАХ а о ПЕРЕМЕННЫХ - это РАЗНЫЕ сущности , разве нет?
Уточни плиз, в чем вопрос. Если можно, то по подробней.
-
Господа .... я говор про другое - в предложенном сейчас D методе - речь идет не о ТИПАХ а о ПЕРЕМЕННЫХ - это РАЗНЫЕ сущности , разве нет?
"Место для D", Андрей Александреску:
Почему неизменяемые данные это так здорово? Совместное использование неизменяемых
данных потоками не требует синхронизации, а отсутствие синхронизации - самая быстрая
синхронизация. Хитрость в том, чтобы быть уверенным: «только для чтения» и впрямь озна-
чает «только для чтения», а иначе нельзя дать никаких гарантий. Чтобы поддержать этот
важный аспект параллельного программирования, D предоставляет беспрецедентную под-
держку для смешивания функционального и императивного программирования. Данные со
спецификатором immutable предоставляют сильные статические гарантии — правильно ти-
пизированная программа не может изменять immutable данные. Более того, неизменяемость
транзитивна, и при работе на неизменяемой территории все ссылки тоже будут указывать
на неизменяемые данные. (Почему? Если бы это было не так, то при совместном использо-
вании потоками данных, которые вы считали неизменяемыми, вы непреднамеренно делаете
общими и изменяемые данные, но в этом случае мы возвращаемся к сложным правилам
которых хотели избежать). Целые подграфы связанных объектов могут быть легко «окра-
шены» неизменяемостью. Система типов знает где они и позволяет свободно разделять их
между потоками, более агрессивно оптимизируя доступ к ним и в однопоточном коде.
-
Господа .... я говор про другое - в предложенном сейчас D методе - речь идет не о ТИПАХ а о ПЕРЕМЕННЫХ - это РАЗНЫЕ сущности , разве нет?
"Место для D", Андрей Александреску:
Почему неизменяемые данные это так здорово? Совместное использование неизменяемых
данных потоками не требует синхронизации, а отсутствие синхронизации - самая быстрая
синхронизация. Хитрость в том, чтобы быть уверенным: «только для чтения» и впрямь озна-
чает «только для чтения», а иначе нельзя дать никаких гарантий. Чтобы поддержать этот
важный аспект параллельного программирования, D предоставляет беспрецедентную под-
держку для смешивания функционального и императивного программирования. Данные со
спецификатором immutable предоставляют сильные статические гарантии — правильно ти-
пизированная программа не может изменять immutable данные. Более того, неизменяемость
транзитивна, и при работе на неизменяемой территории все ссылки тоже будут указывать
на неизменяемые данные. (Почему? Если бы это было не так, то при совместном использо-
вании потоками данных, которые вы считали неизменяемыми, вы непреднамеренно делаете
общими и изменяемые данные, но в этом случае мы возвращаемся к сложным правилам
которых хотели избежать). Целые подграфы связанных объектов могут быть легко «окра-
шены» неизменяемостью. Система типов знает где они и позволяет свободно разделять их
между потоками, более агрессивно оптимизируя доступ к ним и в однопоточном коде.
Может не будем уподобляться Илье ...А (или вы хотите свести общение на форуме, к обмену цитатами от балды ?) :( - для этого есть oberoncore...
-
Вот поэтому, я и предложил таки подробно изложить суть вопроса :-)
-
(или вы хотите свести общение на форуме, к обмену цитатами от балды ?) :(
Цитаты от балды???
Вы упомянули подход D (хотя и не уточнили, как Вы его понимаете), спросили "причём здесь типы?" -- вот я и показал, что подход D опирается на типы.
-
(или вы хотите свести общение на форуме, к обмену цитатами от балды ?) :(
Цитаты от балды???
Вы упомянули подход D (хотя и не уточнили, как Вы его понимаете), спросили "причём здесь типы?" -- вот я и показал, что подход D опирается на типы.
Вы не показали.. Вы просто сунули цитату, как обычно делает Илья (не сильно заботясь в тему она или нет, как собаке кость -авось она успокоится). Речь о том - нужно ли нам порождать чистые пользовательские типы - формально -добавлять метку pure в определение типа... ;)
-
В хаскеле нет различий между переменными и функциями, так что вопрос смысла не имеет :-)
-
(или вы хотите свести общение на форуме, к обмену цитатами от балды ?) :(
Цитаты от балды???
Вы упомянули подход D (хотя и не уточнили, как Вы его понимаете), спросили "причём здесь типы?" -- вот я и показал, что подход D опирается на типы.
Вы не показали.. Вы просто сунули цитату, как обычно делает Илья (не сильно заботясь в тему она или нет, как собаке кость -авось она успокоится). Речь о том - нужно ли нам порождать чистые пользовательские типы - формально -добавлять метку pure в определение типа... ;)
Я говорю НАМ, однако (ибо надеюсь, что разговор ведется в контексте темы... если нет - то я выключаюсь из обсуждения)
-
Я говорю НАМ, однако (ибо надеюсь, что разговор ведется в контексте темы... если нет - то я выключаюсь из обсуждения)
... Ибо мне это не нужно, лично я стараюсь воспринимать мир каким он есть - без деления на "чистое" и "грязное" :)
-
Ну, в мире и типов нет, это ж не повод использовать языки без типизации? :-)
-
Ну, в мире и типов нет, это ж не повод использовать языки без типизации? :-)
Я говорю про себя, за "весь" мир пусть говорит Илья- он у нас "профессионал-архитектор" - а что остается простым людям - слушать его и таких как он - либо разбираться самим, если ХОТИМ ПОНЯТЬ СУЩНОСТЬ вопроса...
-
Ну, таки давайте на личности особо акцентированно переходить не будем. Каждый имеет право на ошибку. А Илья довольно часто вполне вменяемо формулирует мысль. В том числе, действительно частенько бывает, повитав в облаках высоких теорий, полезно поковырять немного практики.
Так что давайте таки сформулируем модельную задачу затрагивающую обсуждаемую тему, как я уже предлагал, и попробуем её решить различными способами, возможно на разных языках и псевдокоде. Думаю будет полезно.
2 vlad: ты мне обещал примерчиков :-) Так что милости прошу, так сказать :-)
-
Ну, таки давайте на личности особо акцентированно переходить не будем. Каждый имеет право на ошибку. А Илья довольно часто вполне вменяемо формулирует мысль. В том числе, действительно частенько бывает, повитав в облаках высоких теорий, полезно поковырять немного практики.
Так что давайте таки сформулируем модельную задачу затрагивающую обсуждаемую тему, как я уже предлагал, и попробуем её решить различными способами, возможно на разных языках и псевдокоде. Думаю будет полезно.
2 vlad: ты мне обещал примерчиков :-) Так что милости прошу, так сказать :-)
1. Давайте
2.Зачем,какую, на каком языке
-
Вдогонку, (к чистоте) - а может ату ее, просто заменим проверками типа: IsPURE(SOMETYPE)?
-
1) Когда будут выполняться эти проверки?
2) Какой в них смысл?
Какую задачку – не знаю. Любую реальную, достаточно большую для того, чтобы имело смысл архитектуру разводить. У меня в голове вертятся либо какие-то телекомные задачки, или какой-нибудь гуй. Важно чтобы эту задачу понимали все участвующие в дискуссии.
-
1) Когда будут выполняться эти проверки?
2) Какой в них смысл?
Какую задачку – не знаю. Любую реальную, достаточно большую для того, чтобы имело смысл архитектуру разводить. У меня в голове вертятся либо какие-то телекомные задачки, или какой-нибудь гуй. Важно чтобы эту задачу понимали все участвующие в дискуссии.
1 Во время выполнения
2 В том, что бы на месте определиться с грязью мы работаем али нет (в тех случаях когда это важно) - то есть подразумевается что параметр Pure вычисляетя всегда и неявно для каждого пользовательского типа и функции. (решение а-ля оберон).
Предлагаю для начала спроектировать язык (на основе оберона) и работать в нем.
-
1 Во время выполнения
2 В том, что бы на месте определиться с грязью мы работаем али нет (в тех случаях когда это важно) - то есть подразумевается что параметр Pure вычисляетя всегда и неявно для каждого пользовательского типа и функции. (решение а-ля оберон).[/quite]
На этапе исполнения для нас эта информация практически бесполезна, нам нужна эта информация в момент написания кода и компиляции оного.
Предлагаю для начала спроектировать язык (на основе оберона) и работать в нем.
Так чтобы спроектировать язык, нужно вначале понять для чего и как его проектировать, а мы пока похоже не понимаем. Поэтому неплохо бы вначале побегать по граблям реальной задачи, параллельно проектируя язык и решения оной задачи на нем.
-
Так чтобы спроектировать язык, нужно вначале понять для чего и как его проектировать, а мы пока похоже не понимаем. Поэтому неплохо бы вначале побегать по граблям реальной задачи, параллельно проектируя язык и решения оной задачи на нем.
Это дело пятое десятое... Гораздо более важно, я считаю, для начала определиться чего мы хотим, и насколько сильно.... а остальное производная от этого.
-
Это все числодробильные штуки. С ними, как я уже говорил, не очень интересно, потому что и так все легко котроллируется: входные данные известны (массивы, простые типы), смотрим чтобы такой модуль ничего лишнего не импортил (а ему и не надо) и все.
vlad, Вы всё время подчёркиваете ограниченность применения чистых функций. Да, так и есть, их применение ограниченно. Но в этом нет большой беды, ведь процедуры-то никуда не делись, они остались с нами. Пользуйтесь наздоровье :)
Беды конечно нет, кроме часто упоминаемой оберонщиками "усложнения языка из-за ничего". Просто вполне естественно приоритезировать величину граблей. И с этой точки зрения невозможность "безопасно" писать "a < b < c" или даже просто "a < f()" - да, грабли, но очень маленькие. Например, в С++ порядок вычисления выражения и аргументов функций неопределен. Все об этом знают (или узнают, наступив на грабли) и если этот порядок важен или вызов функции может иметь побочный эффект на другие операнды выражения, то предпринимают соответствующие действия. Предложенный вариант в виде pure функций и различия в синтаксисе вызова pure/не-pure гарантирует отсутствие этих граблей. Это очень хорошо. С одной стороны. С другой - мы уже не можем написать что-то совершенно простое и естественное а-ля: "x + window.width()". Если предположить, что у нас большая часть функций будет pure - с этим можно мирится, больше поводов будет делать функции pure (а это хорошо). Но если у нас pure-функций меньшинство - то я лучше оставлю эти маленькие грабли нерешенными в угоду более ясному коду в большинстве ситуаций.
Ещё, если мы говорим об универсальном языке программирования, то неуместно говорить "это мне интересно, это - не очень". Хотя в другом контексте в этих заявлениях нет ничего плохого :)
А вот пример больших граблей, на которые не хочется наступать в более правильных универсальных языках :) Есть древнючий код (~10 лет) с накопленной за все эти годы спецификой, заплатками и т.д. Код, конечно, гхм... плохой. И не потому, что его писали неумные люди или там ополченцы. Просто он старый. И мне его надо заставить работать в отдельном потоке. Не переписывая на хаскеле :) Условие "не переписывать" исходит не из того, что я такой ленивый, а из того, что я в принципе не могу выковырять из него всей накопленной "специфики" поведения и не сломать какой-то сценарий при переписывании. Вот моя мечта: я помечаю функцию-вход всего этого безобразия как pure (или там thread или еще как) и просто исправляю ошибки компиляции. Исправляю, конечно, не автоматически, но полуавтоматически. Если будет какой-то кусочек, который в принципе несовместим с работой в отдельном потоке - я его перепишу правильно. Но только это будет кусочек, а не вся эта аморфная куча. Компиляция прошла - код гарантировано заработал. Без трудноуловимых багов, специфичных для многопоточности. Только не надо кивать на ортогональные вещи типа тестов, строгих спецификаций и т.д. Это все классно, но такой код все равно был, есть и будет.
-
2 vlad: ты мне обещал примерчиков :-) Так что милости прошу, так сказать :-)
Да трудно придумать такую задачку. Все самое интересное начинается в больших задачах. Пока не знаю, что предложить.
-
2vlad: тебе в этой задаче не нужно чтобы код был чистым, то есть без побочных эффектов, тебе нужно чтобы побочные эффекты были локализованы, инкапсулированы внутри этого кода, или были бы и во вне, но их было бы явно видно. То есть тебе нужно ровно то, о чем я говорил – явное разграничение доступа, которое контролируется компилятором.
-
Т.e. нужно уметь сказать, что вот этот вот код не должен менять что-либо о чем я знаю (список исключений из правила прикладывается), и компилятор должен суметь это проконтроллировать.
-
2vlad: тебе в этой задаче не нужно чтобы код был чистым, то есть без побочных эффектов, тебе нужно чтобы побочные эффекты были локализованы, инкапсулированы внутри этого кода, или были бы и во вне, но их было бы явно видно. То есть тебе нужно ровно то, о чем я говорил – явное разграничение доступа, которое контролируется компилятором.
Да, я понимаю, что обсуждаемое pure - это не совсем та опера. Но близко :) Контроль за доступом к внешним штукам - тоже нужен в каком-то виде.
-
2vlad: тебе в этой задаче не нужно чтобы код был чистым, то есть без побочных эффектов, тебе нужно чтобы побочные эффекты были локализованы, инкапсулированы внутри этого кода, или были бы и во вне, но их было бы явно видно. То есть тебе нужно ровно то, о чем я говорил – явное разграничение доступа, которое контролируется компилятором.
Либо какой- то анализатор кода,еще лучше... задача через чур специфичиская. Кстати , тут пожалуй проверка IsPure самое то?
-
Анализатор кода… Гм. А ведь это идея. Можно написать анализатор какого-нибудь Оберона (это вроде бы должно быть просто), который введет понятие контроля доступа (посредством анотаций, или вообще в виде спец-коментариев/прагм) и попробовать отрефакторить какой-нибудь существующий кусок реального кода например.
-
То есть задача №1: распихивание старого кода (причем такого, который знать не знал про многопоточность) по потокам.
Между прочим, эта же задача – задача вытскивание некой функциональности в отдельную утилиту например.
-
Речь о том - нужно ли нам порождать чистые пользовательские типы - формально -добавлять метку pure в определение типа... ;)
Пока мне кажется, что без этого не обойтись.
Тут вообще надо сначала решить -- а нужно ли разделять подпрограммы на функционально чистые и императивно грязные.
Такое разделение даёт определённые удобства и налагает определённые неудобства.
Так же как оператор GOTO -- можно всё сделать с его помощью, но всё же на каких-то задачах удобнее и безопаснее пользоваться операторами IF, WHILE, FOREACH и т.д.
-
То есть задача №1: распихивание старого кода (причем такого, который знать не знал про многопоточность) по потокам.
Между прочим, эта же задача – задача вытскивание некой функциональности в отдельную утилиту например.
Хотя нет, не та же. Вторая задача много проще.
-
Какую задачку – не знаю. Любую реальную, достаточно большую для того, чтобы имело смысл архитектуру разводить. У меня в голове вертятся либо какие-то телекомные задачки, или какой-нибудь гуй. Важно чтобы эту задачу понимали все участвующие в дискуссии.
Вот на примере GUI-фрэймворка было бы интересно (для меня, по крайней мере).
Сейчас эти задачи решаются в основном в ООП-стиле -- довольно удобен он для этого.
Было бы интересно, какие ещё принципиальные решения могут быть.
Например -- некий GUI-engine предоставляет взаимодействие с пользователем в виде:
Мир (экран, клавиатура, мышь, аудио) => Программа => Мир (экран, клавиатура, мышь, аудио)
Если не вдаваться в низкоуровневые подробности этого GUI-engine, то Программа становится вполне функционально чистой. Насколько это реально удобно, какие могут быть недостатки?
Как можно реализовать этот GUI-engine?
-
1) Когда будут выполняться эти проверки?
1 Во время выполнения
Динамические проверки малополезны.
Всё, что может быть проверено на стадии компиляции, должно быть проверено на стадии компиляции. В этом случае минимизируется цена исправления ошибок.
-
Речь о том - нужно ли нам порождать чистые пользовательские типы - формально -добавлять метку pure в определение типа... ;)
Пока мне кажется, что без этого не обойтись.
Тут вообще надо сначала решить -- а нужно ли разделять подпрограммы на функционально чистые и императивно грязные.
Такое разделение даёт определённые удобства и налагает определённые неудобства.
Так же как оператор GOTO -- можно всё сделать с его помощью, но всё же на каких-то задачах удобнее и безопаснее пользоваться операторами IF, WHILE, FOREACH и т.д.
Подпрограммы всего лишь - отображение на ЯП, свойств моделируемой системы... Если решать его вообще ( то есть с позиции- ЯП может описывать ЛЮБУЮ систему , решать любую задачу) - вопрос филосовский - делить мир на "грязный" и "чистый" или нет...Чистые функциональные языки мне этим и не нравятся...как и тотально объектно =ориентированные... у них перекосы. Тут еще дело в том. что гадить может сам ЯП как своими артефактами так и идущими от железяки
-
Кстати, господа для меня лично польза от конкретно этого обсуждения есть - я ТОЧНО понял, что одно только стремление к чистоте НИКОГДА не заставит меня подсесть на Хаскель :)
-
Кстати, господа для меня лично польза от конкретно этого обсуждения есть - я ТОЧНО понял, что одно только стремление к чистоте НИКОГДА не заставит меня подсесть на Хаскель :)
А что заставит? :)
Лично меня заставил синтаксис... ;D
-
Кстати, господа для меня лично польза от конкретно этого обсуждения есть - я ТОЧНО понял, что одно только стремление к чистоте НИКОГДА не заставит меня подсесть на Хаскель :)
А что заставит? :)
Лично меня заставил синтаксис... ;D
Тем более. :)
-
Мне кажется, что поставленная задача тут чрезмерно усложнена расширительным толкованием понятия "Побочный эффект". Если сузить толкование до обычного (http://ru.wikipedia.org/wiki/%D0%9F%D0%BE%D0%B1%D0%BE%D1%87%D0%BD%D1%8B%D0%B9_%D1%8D%D1%84%D1%84%D0%B5%D0%BA%D1%82_(%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5)), то получение функций и процедур без побочных эффектов станет вполне посильной задачей. Можно будет обойтись (за редкими исключениями) без функций и процедур с побочными эффектами. Правда, для этого потребуются серьезные решения по языку, как это предложено в PureBuilder (https://sites.google.com/site/purebuilder/):
- полный запрет глобальных и статических переменных,
- модификация механизма исключений в функциональном стиле,
- отказ от классического ООП в пользу ООП, реализованного в Обероне и в Обероне-07.
-
Под классическим ООП подразумевается то, что в КП и Обероне-2?
-
Мне кажется, что поставленная задача тут чрезмерно усложнена расширительным толкованием понятия "Побочный эффект". Если сузить толкование до обычного (http://ru.wikipedia.org/wiki/%D0%9F%D0%BE%D0%B1%D0%BE%D1%87%D0%BD%D1%8B%D0%B9_%D1%8D%D1%84%D1%84%D0%B5%D0%BA%D1%82_(%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5)), то получение функций и процедур без побочных эффектов станет вполне посильной задачей. Можно будет обойтись (за редкими исключениями) без функций и процедур с побочными эффектами. Правда, для этого потребуются серьезные решения по языку, как это предложено в PureBuilder (https://sites.google.com/site/purebuilder/):
- полный запрет глобальных и статических переменных,
- модификация механизма исключений в функциональном стиле,
- отказ от классического ООП в пользу ООП, реализованного в Обероне и в Обероне-07.
1. Ну я думаю что все из участвующих в обсужденни знакомы с различными формальными определениями его... лично я участвовал в обсуждении что бы прояснить его сущность...(важнейшая мотивация.)
2. А чем сущность "классического" ООП отличается от Обероновых - в моем представлении это набор концепций, а в вашем?
-
И потом - полный запрет.... для некоторых задач они естественны... А что естественно то не безобразно, как известно
-
Так что давайте таки сформулируем модельную задачу затрагивающую обсуждаемую тему, как я уже предлагал, и попробуем её решить различными способами, возможно на разных языках и псевдокоде. Думаю будет полезно.
2 vlad: ты мне обещал примерчиков :-) Так что милости прошу, так сказать :-)
И когда вы только работаете? :D
-
Под классическим ООП подразумевается то, что в КП и Обероне-2?
Да. Скопировано из мейнстрима.
-
И потом - полный запрет.... для некоторых задач они естественны... А что естественно то не безобразно, как известно
Насколько понимаю, речь идет о глобальных переменных.
Думаю, что в программировании вообще нет ничего естественного. А естественность глобальных переменных и подавно - полная ерунда. В программировании всё искусственное. Когда разработчики недостаточно искусны, появляются такие примитивные и убогие вещи, как глобальные переменные, мудреные правила видимости и прочий винигрет... совершенно безобразный! Глобальные переменные - это отображение хаоса модели задачи в хаос программного кода.
-
Что подразумеваем под глобальными переменными?
Собственно хотелось бы увидеть, как без глобальных переменных получится, ну, скажем написать Hello World.
-
А чем сущность "классического" ООП отличается от Обероновых - в моем представлении это набор концепций, а в вашем?
Про абстракцию, полиморфизм, наследование, инкапсуляцию и прочее говорить не будем - из этих абстрактных идей может следовать какая угодно конкретная реализация.
Классический ООП основан на классах и интерфейсах, содержащих методы (ну и поля). Наиболее яркие примеры: Дельфи, Си++, Ява. Обероновский ООП (кроме Оберона-2 и КП) - на процедурных типах, при том, что процедуры не привязаны к структурным типам данных (записям, объектам, классам, интерфейсам и т.п.). Обероновский ООП имеет не только достоинства, но и недостатки. Но имеет смысл подумать об устранении недостатков, а не о заимствовании классического ООП.
-
Что подразумеваем под глобальными переменными?
Переменная, объявленная снаружи процедуры/функции, и доступная как снаружи, так и внутри нее. См. Википедию (http://ru.wikipedia.org/wiki/%D0%93%D0%BB%D0%BE%D0%B1%D0%B0%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%BF%D0%B5%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%BD%D0%B0%D1%8F#.D0.9B.D0.BE.D0.BA.D0.B0.D0.BB.D1.8C.D0.BD.D1.8B.D0.B5_.D0.B8_.D0.B3.D0.BB.D0.BE.D0.B1.D0.B0.D0.BB.D1.8C.D0.BD.D1.8B.D0.B5_.D0.BF.D0.B5.D1.80.D0.B5.D0.BC.D0.B5.D0.BD.D0.BD.D1.8B.D0.B5._.D0.97.D0.BE.D0.BD.D1.8B_.D0.B2.D0.B8.D0.B4.D0.B8.D0.BC.D0.BE.D1.81.D1.82.D0.B8.).
Собственно хотелось бы увидеть, как без глобальных переменных получится, ну, скажем написать Hello World.
А зачем там вообще какие-то переменные?
-
А зачем там вообще какие-то переменные?
Затем, что hello world что-то таки печатает куда-то, сам этот процесс таки изменяет состояние чего-то, вот это самое что-то это и есть глобальная переменная.
Вот буквально сегодня смотрел исходники функции printf для микроконтроллера который у нас используется -- там без глобальной переменной не обошлось. Причем по фиксированному адресу. :-)
-
Думаю, что в программировании вообще нет ничего естественного. А естественность глобальных переменных и подавно - полная ерунда. В программировании всё искусственное. Когда разработчики недостаточно искусны, появляются такие примитивные и убогие вещи, как глобальные переменные, мудреные правила видимости и прочий винигрет... совершенно безобразный! Глобальные переменные - это отображение хаоса модели задачи в хаос программного кода.
Разумеется да, если смотреть на нее как на набор инструкций для исполнителя. Точно также , как искуственны постулаты Евклида. Также с помощью последних МОЖНО описывать мир, но так-же с помощью них можно делать построения которым, едва ли найдутся интересные (на практике) системы. В этом и порок такого однобокого взгляда.
-
Когда разработчики недостаточно искусны, появляются такие примитивные и убогие вещи, как глобальные переменные, мудреные правила видимости и прочий винигрет... совершенно безобразный!
Ваши слова вызывают у меня оторопь. Зачем же так ненавидеть всё, что не вписывается в Ваше представление о семантическом редакторе?
Ничего личного.
-
А зачем там вообще какие-то переменные?
Затем, что hello world что-то таки печатает куда-то, сам этот процесс таки изменяет состояние чего-то, вот это самое что-то это и есть глобальная переменная.
Вот буквально сегодня смотрел исходники функции printf для микроконтроллера который у нас используется -- там без глобальной переменной не обошлось. Причем по фиксированному адресу. :-)
Отсюда , небольшой шаг, до понимания того, что чистый и грязный зависит от модели системы. Применительно к вашему предложению о создании анализатора, это дает нам осознание того, что нет универсального способа остановки (анализатора), и если нужда заставит делать такую тулзовину... то речь будет идти о свойствах КОНКРЕТНОЙ системы- вывод нех маятся дурью ;) - вполне конкретен, и без всякого прототипирования. По этому и ВАЖНО (для специалистов широкого профиля и управленцев) умение выделять сущности из определений и уметь работать на абстрактном уровне (в противном случае всю группу и проект можно в такое дерьмо опустить, что банка икры баклажанной будет казаться манной небесной).
-
А зачем там вообще какие-то переменные?
Затем, что hello world что-то таки печатает куда-то, сам этот процесс таки изменяет состояние чего-то, вот это самое что-то это и есть глобальная переменная.
Вот буквально сегодня смотрел исходники функции printf для микроконтроллера который у нас используется -- там без глобальной переменной не обошлось. Причем по фиксированному адресу. :-)
Но мы же говорим о новом языке высокого уровня, а не о том, во что он транслируется. Да в ассемблере есть и глобальные переменные, и goto, и побочные эффекты на каждом шагу. И я отношусь к этому совершенно спокойно, потому что транслятор, как правило, не допускает ошибок, в отличие от программиста.
-
А при чем тут трансляция? Это все (тот же prontf) пишется в терминах языка высокого уровня, ни единой строчки асма. От синглетонов (они же глобальные перменные в девичестве) никуда не деться, они есть просто как следствие окружающего нас мира. Другое дело, что они должны использоваться только по делу, и их использование (и создание) должно контролироваться.
-
Пример где наличие оной глобальной переменной в реализации printf'a (или writeln, или чем там печатается Hello World) явно вылезает: делаем двупоточный Hello World, где каждый поток в цикле печатает оный Hello World – в результате на выходе получим замечательную кащу из символов.
-
Всё, что может быть проверено на стадии компиляции, должно быть проверено на стадии компиляции. В этом случае минимизируется цена исправления ошибок.
Правильные слова в целом. Но, как всегда, до того момента, когда цена от реализации начинает перевешивать выгоду от ранних проверок.
Практика показывает, что особый риск, цену поиска и шансы остаться незамеченными имеют как раз простые "низкоуровневые" ошибки, вроде базовых типов и т.п.
Чем высокоуровневее части, тем меньше проблем с динамикой. Вы не ошибётесь с тем, какого типа сообщение Вы посылаете объекту, или какого типа объекты соединяете в единое целое, потому что это - основная семантика, вы о ней думаете.
Я с большим интересом следил за экспериментами Microsoft в области этих верификаций протоколов и т.п., что пробовалось в Sing# и OS Singularity. И при встрече с Владиславом Шершульским дотошно его "потрепал" вопросами, что из этих идей вышло: http://forum.oberoncore.ru/viewtopic.php?f=26&t=2685. Показателен его ответ - "Те средства, которые были введены в языке Sing#, оказались переусложнёнными относительно реальных потребностей".
-
Нужно конкретно предметно смотреть какие именно возможности не пошли и что это были за возможности такие. Иначе имеем ситуацию не много лучше чем "одна бабка сказала".
Потому как в промышленности тот же SPARK например востребован. И в отличае от Sig# он уже в боингах.
-
В тему immutable-data, вспомнил про публикацию Вольфганга Века (второй архитектор ББ):
http://narod.ru/disk/6679411001/Weck-Freezable-Lists.pdf.html
An Abstract Data Type for Freezable List and DAGs
-
Кстати, ошибок на уровне базовых типов, построения циклов и так далее, я за последние годы не помню вообще. А вот ошибки в предметной области, там где сосредоточено внимание, являются основными. И да, ошибка это не обязательно то, что приводит к неверной работе программы, это в том числе и то, что не позволяет быстро прикрутить нужную функциональность без втыкания костылей.
Ах, да. Язык – С++ (в основном).
-
Кстати, ошибок на уровне базовых типов, построения циклов и так далее, я за последние годы не помню вообще.
Касательно циклов - за последние, как результат опыта.
А касательно типов - они прут обычно при переделках кода.
-
Использование классов (особенно шаблонных) дает строгую типазацию и качественные проверки типов на этапе компиляции.
Использование typedef'ов дает гибкость при рефакторинге.
-
Я имею в виду сравнение с языками с дин. типизацией: там простое переименование переменной или изменение подразумеваемого типа параметра может вызвать кучу проблем, которые в статическом языке сразу вылезают на компиляции.
И говорю про то. что вот на этом уровне статические проверки дают самый ощутимый эффект, потому что он - на каждом шагу и для каждой мелкой переменной.
А ощутимость эффекта от статических проверок тем меньше, чем выше уровень семантики мы пытаемся проверить - и тем сложнее это статически проверить.
-
А ощутимость эффекта от статических проверок тем меньше, чем выше уровень семантики мы пытаемся проверить - и тем сложнее это статически проверить.
Возможно, это и так в языках со слабой системой типов. Однако хаскеллеры утверждают, что система типов им как раз помогает при разработке высокуровневой части кода -- типы помогают понять, а то ли они вообще пытаются сделать, по верной ли дороге вообще идут.
-
А ощутимость эффекта от статических проверок тем меньше, чем выше уровень семантики мы пытаемся проверить - и тем сложнее это статически проверить.
Согласен. Поэтому динамические языки существуют и конкурируют со статическими: все равно тесты писать ;)
-
А чем сущность "классического" ООП отличается от Обероновых - в моем представлении это набор концепций, а в вашем?
Классический ООП основан на классах и интерфейсах, содержащих методы (ну и поля). Наиболее яркие примеры: Дельфи, Си++, Ява. Обероновский ООП (кроме Оберона-2 и КП) - на процедурных типах, при том, что процедуры не привязаны к структурным типам данных (записям, объектам, классам, интерфейсам и т.п.). Обероновский ООП имеет не только достоинства, но и недостатки. Но имеет смысл подумать об устранении недостатков, а не о заимствовании классического ООП.
Гхм. ООП в true oberon'e - с нефиговым таким недостатком. По степени возможных граблей может поспорить с жабаскриптом :) Да, и оно точно так же "не работает" с идеей pure функций.
-
Возможно, это и так в языках со слабой системой типов. Однако хаскеллеры утверждают, что система типов им как раз помогает при разработке высокуровневой части кода -- типы помогают понять, а то ли они вообще пытаются сделать, по верной ли дороге вообще идут.
Я читал публикации в журнале ФП и кое-где ещё, понимаю, о чём речь.
Впечатление такое: чтобы задействовать весь этот семантический контроль, слишком многое нужно продумывать сразу и до деталей. Это провоцирует достаточно объёмное (семантически) решение - т.е. полное.
Мне не нравится этот подход, потому что я придерживаюсь другого - итерационное уточнение прототипов, от простейших, минимума, с заглушками и т.п.
И если инструмент заставляет сразу думать о деталях ("угадывать будущее"), то в рамках такого итерационного подхода это - минус. Т.е. компактный инвариант, который нужно выделять на первых порах, окажется недостаточно полным, чтобы задействовать типизацию (т.е. начнёшь её задействовать - потребуется доуточнять сразу то, что доуточнять не следует первое время).
-
Я читал публикации в журнале ФП и кое-где ещё, понимаю, о чём речь.
Впечатление такое: чтобы задействовать весь этот семантический контроль, слишком многое нужно продумывать сразу и до деталей. Это провоцирует достаточно объёмное (семантически) решение - т.е. полное.
Прелесть хаскеля как раз в том, что это не требуется.
Мне не нравится этот подход, потому что я придерживаюсь другого - итерационное уточнение прототипов, от простейших, минимума, с заглушками и т.п.
И если инструмент заставляет сразу думать о деталях ("угадывать будущее"), то в рамках такого итерационного подхода это - минус. Т.е. компактный инвариант, который нужно выделять на первых порах, окажется недостаточно полным, чтобы задействовать типизацию (т.е. начнёшь её задействовать - потребуется доуточнять сразу то, что доуточнять не следует первое время).
Там идет разработка как раз сверху вниз. С постепенным уточнением деталей. На языках типа оберона, явы. ады и так далее, так не получится. До хаскеля я думал что владею техникой построения системы сверху вниз, познакомившись с ним я понял, что все что я делал это жалкая породия на то как это должно быть на самом деле.
-
Гхм. ООП в true oberon'e - с нефиговым таким недостатком. По степени возможных граблей может поспорить с жабаскриптом :) Да, и оно точно так же "не работает" с идеей pure функций.
Во всех нынешних языках ООП страдает какими-нибудь пороками. Не хватает фундаментальности в анализе ООП, а поэтому реализация оказывается такой уродливой. Надо думать (http://forum.oberoncore.ru/viewtopic.php?f=93&t=3297), что делать.
-
Гхм. ООП в true oberon'e - с нефиговым таким недостатком. По степени возможных граблей может поспорить с жабаскриптом :) Да, и оно точно так же "не работает" с идеей pure функций.
Во всех нынешних языках ООП страдает какими-нибудь пороками. Не хватает фундаментальности в анализе ООП, а поэтому реализация оказывается такой уродливой. Надо думать (http://forum.oberoncore.ru/viewtopic.php?f=93&t=3297), что делать.
Гм. А какими пороками страдает ООП в ObjC, Smalltalk'e, StrongTalk'e ну и в erlang'e наконец? Ну и, до кучи, в Eiffel'e.
-
Там идет разработка как раз сверху вниз. С постепенным уточнением деталей. На языках типа оберона, явы. ады и так далее, так не получится. До хаскеля я думал что владею техникой построения системы сверху вниз, познакомившись с ним я понял, что все что я делал это жалкая породия на то как это должно быть на самом деле.
А вот теперь меня заинтриговали - я тоже считаю что владею этой техникой.... ;) в чем разница реализации этой техники на Хаскеле (от Оберона)?
2Geniepro - Учитесь пиарить ЯП!!! :) - Это действительно может быть веской причиной для перехода на Хаскель- если это дейвтвительно так...
-
2Geniepro - Учитесь пиарить ЯП!!! :) - Это действительно может быть веской причиной для перехода на Хаскель- если это дейвтвительно так...
Ненене, я послушный мальчик!
Партия сказала "Avoid success at all costs!" (http://www.reddit.com/r/programming/comments/77z8h/avoid_success_at_all_costs_the_unofficial_slogan/) -- я отвечаю "Ok!"
-
Нужно конкретно предметно смотреть какие именно возможности не пошли и что это были за возможности такие. Иначе имеем ситуацию не много лучше чем "одна бабка сказала".
Потому как в промышленности тот же SPARK например востребован. И в отличае от Sig# он уже в боингах.
Верно, кто знает, не вышло ли у них как с транзакционной памятью -- в Хаскелле супер, а в дотнете провал полный, ибо сплошная мутабельность везде...
-
2Geniepro - Учитесь пиарить ЯП!!! :) - Это действительно может быть веской причиной для перехода на Хаскель- если это дейвтвительно так...
Ненене, я послушный мальчик!
Партия сказала "Avoid success at all costs!" (http://www.reddit.com/r/programming/comments/77z8h/avoid_success_at_all_costs_the_unofficial_slogan/) -- я отвечаю "Ok!"
А... так вы из хэтого принципа рекламировали уродства... хитрый ход, однако, я уж думал что вы убежденный мазохист- и делаете это что бы получить очередной пистон от oberoncor'ных.... :)
-
А... так вы из хэтого принципа рекламировали уродства...
о_О Это какие, интересно? Приведите примеры уродств, а то я что-то не догоняю...
хитрый ход, однако, я уж думал что вы убежденный мазохист- и делаете это что бы получить очередной пистон от oberoncor'ных.... :)
Оберонщики делятся на две категории -- на оберонщиков (Р. Богатырёв, А. Ильин -- вполне вменяемые и адекватные люди) и на блэкбоксёров (которых прокомментировать я могу только матом).
Но ничего, у блекбоксёров руки коротки, здесь им меня не достать... ;D
-
о_О Это какие, интересно? Приведите примеры уродств, а то я что-то не догоняю...
Все просто, как два пальца... - то что не обьеденяет нас , то - разъединяет (а степень и форма выражения последнего зависит от многих вещей - культура, образованность...- они формируют реакцию - то что одному -шедевр, второму -уродство, третий просто не воспринимает , а у четвертого может вызвать ПРАВЕДНЫЙ ГНЕВ ;D )
Оберонщики делятся на две категории -- на оберонщиков (Р. Богатырёв, А. Ильин -- вполне вменяемые и адекватные люди) и на блэкбоксёров (которых прокомментировать я могу только матом).
Но ничего, у блекбоксёров руки коротки, здесь им меня не достать... ;D
Ну ну, земля не столь велика и, вдобавок, достаточно круглая (а правильному фанатику ,как известно,- и море по колено... так что я бы не зарекался). ;)
-
Извините, не хотелось бы обвинять вас в расовой нетерпимости....но если бы они были whiteboxer'ами - вы бы к ним были более терпимы? ;)
-
А вот теперь меня заинтриговали - я тоже считаю что владею этой техникой.... ;) в чем разница реализации этой техники на Хаскеле (от Оберона)?
2Geniepro - Учитесь пиарить ЯП!!! :) - Это действительно может быть веской причиной для перехода на Хаскель- если это дейвтвительно так...
Разниц в том, что в хаскеле у нас типы уточняются постепенно без переписывания оных типов. При этом на каждом этапе мы имеем компилируемую программу. Я тут пока совсем не мастер, и лучше чем Дмитрий Астапов не напишу, поэтому наверно лучше прочесть вот эту статью из журнала Практика ФП: http://fprog.ru/2009/issue1/dmitry-astapov-checkers/ . Меня помнится впечатлило. А потом он продемонстрировал мне эту технику в онлайне решив поставленную мною задачу (для демонстрации был использован etherpad), что впечатлило еще больше.
-
Да, я пробовал в таком стиле писать на Ocaml'e и F#, у меня не получилось. Поэтому, с некоторым сожалением, я оставил Ocaml.
-
Извините, не хотелось бы обвинять вас в расовой нетерпимости....но если бы они были whiteboxer'ами - вы бы к ним были более терпимы? ;)
Если бы они вели себя так же -- то нет, конечно.
-
лучше чем Дмитрий Астапов не напишу, поэтому наверно лучше прочесть вот эту статью из журнала Практика ФП: http://fprog.ru/2009/issue1/dmitry-astapov-checkers/ . Меня помнится впечатлило.
А вот это печально, в статье нечетко выделены сущности с которыми он работает (на мой взгляд) - т.е. через чур много работы для анализа (и синтаксис непривычный, и сущности его (Дмитрия Астапова) анализировать, и соотносить со своим опытом, короче удовольствие еще то :-\\ ).
-
через чур много работы для анализа (и синтаксис непривычный, и сущности его (Дмитрия Астапова) анализировать, и соотносить со своим опытом, короче удовольствие еще то :-\\ ).
Без труда не выловишь и рыбку из пруда... ;D
-
через чур много работы для анализа (и синтаксис непривычный, и сущности его (Дмитрия Астапова) анализировать, и соотносить со своим опытом, короче удовольствие еще то :-\\ ).
Без труда не выловишь и рыбку из пруда... ;D
Согласен, конечно - но тут еще мотивация должна быть на высоте. Просто, когда ЗНАЕШЬ, что в такого рода задачах, ГЛАВНОЕ -умение АБСТРАГИРОВАТЬ и АЛГОРИТМИЗИРОВАТЬ, а от ЯП требуется, чтобы он если не способствовал то не мешал - роль вторичная... То... от впопуляризирующей статьи, хотелось бы -в первую очередь, снижение порога вхождения в "тему".
-
А там он и так снижен до нельзя. Никто не грузит ни монадами ни безточечным стилем, ни классами типов. Единственное что синтаксис чуть не привычен тем кто на сях пишет, с другой стороны это не APL, и он в принципе очень похож на псевдокод абстрактных императивных языков на которых обычно алгоритмы записываются. Так что не вижу проблем.
-
Так что не вижу проблем.
А они есть :)
Как человек, прошедший часть пути по врубанию в Haskell, могу сказать, что эта (хорошая!) статья абсолютно не подходит для первого знакомства с предметом. Для начала надо элементарно разобраться с синтаксисом. Иначе количество непоняток значительно превышает критический порог.
-
Ну давайте пример непоняток :-)
Для первого знакомства я помнится вот эту статью с rsdn использовал: http://rsdn.ru/article/haskell/haskell_part1.xml
Причем именно первую часть и до пункта 6 включительно.
-
Не фига себе "мягкое введение " . ....." В состав Haskell включены также полиморфные типы – типы, которые некоторым образом содержат квантор общности над всеми типами.".... но за то я теперь знаю откуда черпают свой словарный запас на oberoncore... :) Введение хорошее, так вводит. что и снотворного не надо
-
Ну это ж просто обобщенка. Мне после С++ с его шаблонами, это было довольно просто.
-
2GeniePro... , блин - вынужден признать... жесткая позиция оберонцев мне представляется обоснованной. (таки, в некоторой степени).. В моем представлении "черные боксеры" и за меньшее могут вполне, закопать заживо... а после на месте захоронения сплясать ХИП-ХОП всем "племенем". ;D
-
Ну это ж просто обобщенка. Мне после С++ с его шаблонами, это было довольно просто.
Алексей , это комментарий по ходу дела.. ;) и потом, я не говорю что мне сложно...
-
Ну это ж просто обобщенка. Мне после С++ с его шаблонами, это было довольно просто.
Алексей , это комментарий по ходу дела.. ;) и потом, я не говорю что мне сложно...
я говорю, что мне скучно... :-\\
-
2GeniePro... , блин - вынужден признать... жесткая позиция оберонцев мне представляется обоснованной. (таки, в некоторой степени)
Ну а мне не кажется.
ЗЫ. Ну, раз Вас тянет в сон от введения в Хаскелл, значит Вы уже и так всё в ФП знаете и понимаете, рад за Вас. ;D
-
2GeniePro... , блин - вынужден признать... жесткая позиция оберонцев мне представляется обоснованной. (таки, в некоторой степени).. В моем представлении "черные боксеры" и за меньшее могут вполне, закопать заживо... а после на месте захоронения сплясать ХИП-ХОП всем "племенем". ;D
Да, кстати, я, походу, выпал из контекста.
В чём там заключается "жесткая позиция оберонцев" и чем именно она обоснована? А то они много чего говорят, но как дойдёт до обоснования, так сразу в ответ: "Свои "обоснуи" оставьте при себе." (http://forum.oberoncore.ru/viewtopic.php?f=27&t=1106&p=17685&hilit=%D0%A1%D0%B2%D0%BE%D0%B8+%D0%BE%D0%B1%D0%BE%D1%81%D0%BD%D1%83%D0%B8+%D0%BE%D1%81%D1%82%D0%B0%D0%B2%D1%8C%D1%82%D0%B5+%D1%81%D0%B5%D0%B1%D0%B5#p17685)
-
"ЗЫ. Ну, раз Вас тянет в сон от введения в Хаскелл, значит Вы уже и так всё в ФП знаете и понимаете, рад за Вас. ;D"
Спасибо за лестную оценку ;) ..., но скажу честно НЕТ (не понимаю), но мои мысли просто разбиваются о монументальную фундаментальность определений. И есть подозрение, что просто мой тип ума недостаточно полиморфен, утешает только мысль, что это подозрение содержит квантор общности над всеми типами, некоторым образом...
-
Сам автор языка Саймон Пейтон Джонс говорит следующее:
"Чтобы писать поистине функциональные, а не императивные программы, действительно необходимо в некоторой степени перестроить мозги. И не слегка. Это очень существенная перестройка."
"Он [Haskell] сложный."
"У Haskell особый подход к программированию. Если он вам незнаком, то изучить его с нуля довольно трудно."
Из этого и надо исходить. А всякие высказывания типа "не вижу проблем" только дизориентируют и вредят делу.
-
...Из этого и надо исходить. А всякие высказывания типа "не вижу проблем" только дизориентируют и вредят делу.
Похоже на правду, только - я говорил, главным образом, про то, что - наличие ЯВНЫХ плюсов снижает барьер и стимулирует любознательность.... В особенности, когда ЗНАЕШЬ, что свои проблемы можно решить без введения как новых сущностей, так и перестройки сознания.... То есть нужны основания и веские основания... Например, я ТОЧНО знаю что уровень владения абстрактными понятиями НЕОБХОДИМЫМИ для программирования на Хаскеле = превышает тот , который имеют наши студенты (математики) на 1 курсе (тогда как программирование на том же ББ можно давать им и на 1 курсе), на эту хрень накладываются еще абстракции задачи. Короче, на ФИГА ЭТО НУЖНО, КОМУ, ПОЧЕМУ...с вариантами ответа -мазохистам, культистам (от чистой математики), и just for fun ... полностью согласен...
-
Сам автор языка Саймон Пейтон Джонс говорит следующее:
"Чтобы писать поистине функциональные, а не императивные программы, действительно необходимо в некоторой степени перестроить мозги. И не слегка. Это очень существенная перестройка."
"Он [Haskell] сложный."
"У Haskell особый подход к программированию. Если он вам незнаком, то изучить его с нуля довольно трудно."
Из этого и надо исходить. А всякие высказывания типа "не вижу проблем" только дизориентируют и вредят делу.
Почитайте статью "Haskell vs. Ada vs. C++ vs. Awk vs. ... An Experiment in Software Prototyping Productivity" (http://www.google.co.uz/url?sa=t&source=web&cd=4&ved=0CC4QFjAD&url=http%3A%2F%2Fweb.cecs.pdx.edu%2F~apt%2Fcs457_2005%2Fhudak-jones.pdf&ei=OtdwTcyuLouLhQfKj5FL&usg=AFQjCNHF8zEHHymYozkfPEIFyMETzHbR6Q) -- там упоминалось, как студенту ВУЗа понадобилась пара недель для ознакомления с Хаскеллем, после чего он смог написать вполне конкурентоспособное решение для задачи из этого эксперимента.
-
Из этого и надо исходить. А всякие высказывания типа "не вижу проблем" только дизориентируют и вредят делу.
Ой, таки не надо вырывать из контекста, это было сказано конкретно про ту статью. Та статья глубоких познаний не требует абсолютно. Хаскель как язык – простой, используемые парадигмы при построении программ на нем да, довольно сложные. Причем, в отличае от иных языков, на нем весьма сложно писать не правильно, т.е. наплевать на эти парадигмы и писать на хаскеле как на фортране просто так не выйдет.
В этом плане Ocaml сильно проще. Но… оно того стоит. По крайней мере меня очень впечатлило как Дмитрий Астапов строил у меня на глазах программу. То есть сам ход решения задачи, приемы мышления.
-
Причем никаких зубодробильных абстракций там небыло. То есть весь процесс от начала до конца мне был понятен. Но мыслить в таком направлении я пока нормально не научился. Это реально построение сверху-вниз, а не снизу вверх.
Как только вы начинаете построение системы с планирования типов данных (структурки там заводите, классы разрисовываете) – это значит, что вы опять строите не сверху вниз, а снизу вверх, точнее строите не с самого низа, а где-то ниже середины. Соответственно да, будет участок где у вас будет как бы строительство сверху вниз, но основная часть все равно будет снизу вверх.
-
Например, я ТОЧНО знаю что уровень владения абстрактными понятиями НЕОБХОДИМЫМИ для программирования на Хаскеле = превышает тот , который имеют наши студенты (математики) на 1 курсе (тогда как программирование на том же ББ можно давать им и на 1 курсе), на эту хрень накладываются еще абстракции задачи.
John O’Donnell, Cordelia Hall and Rex Page
"Discrete Mathematics Using a Computer"
Учебник по дискретной математике, являющийся заодно и учебником по Хаскеллу.
Короче, на ФИГА ЭТО НУЖНО, КОМУ, ПОЧЕМУ...с вариантами ответа -мазохистам, культистам (от чистой математики), и just for fun ... полностью согласен...
Ну хотя бы для того, что бы изучать дискретную математику.
-
Например, я ТОЧНО знаю что уровень владения абстрактными понятиями НЕОБХОДИМЫМИ для программирования на Хаскеле = превышает тот , который имеют наши студенты (математики) на 1 курсе (тогда как программирование на том же ББ можно давать им и на 1 курсе), на эту хрень накладываются еще абстракции задачи.
John O’Donnell, Cordelia Hall and Rex Page
"Discrete Mathematics Using a Computer"
Учебник по дискретной математике, являющийся заодно и учебником по Хаскеллу.
Короче, на ФИГА ЭТО НУЖНО, КОМУ, ПОЧЕМУ...с вариантами ответа -мазохистам, культистам (от чистой математики), и just for fun ... полностью согласен...
НУЖНО, а не МОЖНО
Ну хотя бы для того, что бы изучать дискретную математику.
-
John O’Donnell, Cordelia Hall and Rex Page
"Discrete Mathematics Using a Computer"
Учебник по дискретной математике, являющийся заодно и учебником по Хаскеллу.
Спасибо, нашел и скачал :)
А агитировать меня не требуется, я, типа, уже давно ...
-
Не, я не понял, у нас таки шо, форум плавно превращается из обероновского в хаскелевский? :-)
Уже три адепта + другие постепенно совращаются.
-
Так практически сразу можно было заводить ветку по ФП и Haskell, в частности.
-
Не, я не понял, у нас таки шо, форум плавно превращается из обероновского в хаскелевский? :-)
Уже три адепта + другие постепенно совращаются.
А вот черта с два... императивщики просто так не сдаются... :)
-
Дэк этта… Хаскель это ж в том числе и прекрасный императивный язык со строгой системой типов и простым синтаксисом :-)
-
Дэк этта… Хаскель это ж в том числе и прекрасный императивный язык со строгой системой типов и простым синтаксисом :-)
Не понял таки Императивный или Функциональный? c тем что прекрасный соглашусь (на всякий случай, земля то круглая...) :)
-
Дэк этта… Хаскель это ж в том числе и прекрасный императивный язык со строгой системой типов и простым синтаксисом :-)
Не понял таки Императивный или Функциональный?
Ну это зависит от того, как Вы его используете. На Хаскелле можно писать и в чисто функциональном стиле, и в жёстко-императивном (ввод/вывод, параллельные процессы и т.д.).
Просто эти два мира (Функциональный и Императивный) в Хаскелле строго разделены, и если функциональщина без проблем может использоваться в императивной части программы, то императивщина находится в специальной резервации -- в монаде ввода/вывода.
-
Дэк этта… Хаскель это ж в том числе и прекрасный императивный язык со строгой системой типов и простым синтаксисом :-)
Не понял таки Императивный или Функциональный?
Ну это зависит от того, как Вы его используете. На Хаскелле можно писать и в чисто функциональном стиле, и в жёстко-императивном (ввод/вывод, параллельные процессы и т.д.).
Просто эти два мира (Функциональный и Императивный) в Хаскелле строго разделены, и если функциональщина без проблем может использоваться в императивной части программы, то императивщина находится в специальной резервации -- в монаде ввода/вывода.
ЭЭЭ так он смешанный... "Скажите а диссонансы по ночам Вас не мучают"? (П. Кушнир) от сложности. :) Господа, я предлагаю прояснить мне - дурилке картонной разницу в подходах к алгоритмизации задач обычных ЯП и Хаскеля есть разница на том уровне или нет? если есть то в чем? и своими словами. Или разница на уровне ниже-в переложении алгоритма на ЯП (составлении программы)?
-
ЭЭЭ так он смешанный...
Ну что значит "смешанный"?
Любой промышленный язык обречён иметь дело с вводом/выводом информации, так что императивная часть неизбежно будет присутсвовать в любом полноценном языке.
Другое дело, что стандартные языки типа сей смешивают императивную и функциональную части программы. Вот они и есть "смешанные"...
И вот как раз такое разделение программы на чистую и грязную части помогает бороться со сложностью. Так что диссонансы возникают лишь у упёртых императивщиков, дальше оберонов и сей не видящих...
-
ЭЭЭ так он смешанный...
Ну что значит "смешанный"?
Любой промышленный язык обречён иметь дело с вводом/выводом информации, так что императивная часть неизбежно будет присутсвовать в любом полноценном языке.
Другое дело, что стандартные языки типа сей смешивают императивную и функциональную части программы. Вот они и есть "смешанные"...
И вот как раз такое разделение программы на чистую и грязную части помогает бороться со сложностью. Так что диссонансы возникают лишь у упёртых императивщиков, дальше оберонов и сей не видящих...
То что я дурилка картонная - понял...Но вопрос был другой ;)
-
Не, я не понял, у нас таки шо, форум плавно превращается из обероновского в хаскелевский? :-)
Уже три адепта + другие постепенно совращаются.
Вот оно истинное лицо oberon space :D :D - это шайка-лейка активистов-Хаскелистов... пришедшая конвертировать сомневающихся с соседней конфессии... :)
-
Нас раскрыли, чорт... ::)
-
Причем никаких зубодробильных абстракций там небыло. То есть весь процесс от начала до конца мне был понятен. Но мыслить в таком направлении я пока нормально не научился. Это реально построение сверху-вниз, а не снизу вверх.
Как только вы начинаете построение системы с планирования типов данных (структурки там заводите, классы разрисовываете) – это значит, что вы опять строите не сверху вниз, а снизу вверх, точнее строите не с самого низа, а где-то ниже середины. Соответственно да, будет участок где у вас будет как бы строительство сверху вниз, но основная часть все равно будет снизу вверх.
Так мне представляется такой подход естественным и продуктивным.
У нас есть задача и есть базовая машина.
Мы, с одной стороны, идём от задачи - проясняем её, сначала вообще без всякого программирования. Делим на функциональные части, потом на взаимодействующие подсистемы, реализующие эти функции. И стремимся свести как можно скорее к каким-то более типовым подзадачам, унифицированным решениям для этих задач (стремимся прийти от индивидуальной и неповторимой задачи к совершенно типовым подзадачам).
С другой стороны, поднимаем уровень данной нам машины, создавая новые слои, новые "абстрактные машины", в таком направлении, чтобы сойтись с тем нисходящим потоком мысли.
Я, как системщик-инструментальщик обычно практикую такую расстановку акцентов: "ключиком" для проекта является некий уровень в его середине, на котором удаётся уже "убить" частные закидоны задачи и придумать некие простые базовые средства, которые никак с задачей не связаны, но помогают просто её решить (т.е. свести прикладную часть задачи к какого-то рода сборке из кубиков). При создании этих средств не целим на универсальность (пустая трата времени - обобщать от одной задачи), а целим на инвариантность - т.е. средства должны быть такими базовыми и простыми, что, совершенно очевидно, что они будут полезны "направо и налево".
Так достигаются цели расширяемости и масштабируемости системы, и накопления фонда базовых средств и инструментов у коллектива.