Здравствуйте, AVC, Вы писали:
AVC>Часом, не книга двух "русских парней" Вайнера и Пинсона "С++ изнутри"? AVC>(В оригинале Wiener, Pinson "The C++ Workbook".) AVC>Там как раз одна глава была посвящена этому "экологическому моделированию" (океан, хищники, жертвы).
Может автор перепечатал главу, но я точно помню что автор был русский.
Здравствуйте, GlebZ, Вы писали:
AVC>>Часом, не книга двух "русских парней" Вайнера и Пинсона "С++ изнутри"? AVC>>(В оригинале Wiener, Pinson "The C++ Workbook".) AVC>>Там как раз одна глава была посвящена этому "экологическому моделированию" (океан, хищники, жертвы). GZ>Может автор перепечатал главу, но я точно помню что автор был русский.
Ну, не суть важно.
Главное — учебный пример и правда неплохой.
Но существует одно качество, которое нельзя купить, — это надежность. Цена надежности — погоня за крайней простотой. Это цена, которую очень богатому труднее всего заплатить.
Здравствуйте, Курилка, Вы писали:
К>Хотел поделиться статьёй, где автор рассматривает (на примере Haskell), почему же путь "обычных" программеров в функциональное программирование несколько сложен. Ответ, наверное, довольно заметно пересекается с тем, что тут уже довольно много говорил VladD2: функциональщики, как правило, довольно сильно отходят от тех материй, которые занимают умы императивщиков, и занимаются всякими монадами и прочими "хитрыми" вещами. В результате чего для какого-нибудь сишника учебник по хаскелю или мл получается очень сложным, т.к. строится с точки зрения человека, мыслящего уже категориями хаскеля или мл.
У меня есть сомнение в основной предпосылке (что императивщикам плохо дается именно ФП).
По крайней мере, хотелось бы уточнить, что именно в ФП плохо дается императивщикам.
Насколько я понимаю, собственно ФП основывается на принципе "референциальной прозрачности" ("прозрачности по ссылкам").
В учебниках ФП этот принцип подается в виде "подстановочной" вычислительной модели (substitution model), в противоположность трассировке (прокрутке?) для "обычного" императивного программирования.
Как, ИМХО, справедливо указывают авторы известных учебников (Абельсон и Сассман, Бауэр и Гооз, и т.д.) подстановочная модель проще.
Можно было бы предположить, что какая-то трудность заключается в невозможности использовать привычную конструкцию цикла (из-за ее несовместимости с принципом "прозрачности по ссылкам").
Но, ИМХО, первое же знакомство с хвостовой рекурсией устраняет эту трудность.
Значит, дело не в самом базовом принципе.
А в чем? Может быть, в следствиях?
Из принципа "прозрачности по ссылкам" прямоо вытекает ряд приятных следствий: возможность (автоматического) распараллеливания программ и использования "ленивых" вычислений.
Может быть, их трудно понять?
Кто-нибудь конкретно считает, что это трудно?
Единственным минусом как основного принципа, так и этих следствий может быть некоторая усложненность системы программирования и рантайма по сравнению с простыми ИЯ, вроде Си или Оберона. Возможно, программисту становится несколько труднее предсказать, во что "выльется" его код.
Кого-то это отпугнет (например, меня, т.к. я пишу по "голому железу", и мне надо выжимать из процессора максимум), а кого-то и нет.
Вопрос становится все запутаннее.
Может быть, дело в каких-то иных следствиях? И есть ли они?
Да, какие-то есть.
Заглянем в раздел 3.1.2. ("Преимущества присваивания") книги Абельсона и Сассмана.
Там достаточно ясно сказано, что и (внимание!) у присваивания (т.е. у конструкции не совместимой с ФП) есть свои преимущества.
На простом примере демонстрируется, что чистое ФП плохо совместимо с модульностью и ООП.
Без присваиваний, оказывается, это не дается.
Не надо только говорить, что объекты реализуются в ФЯ с помощью "окружения" (closure = enclosuring enviroment).
Суть в том, что требуется присваивание, а substitution model замещается существенно более сложной (и в принципе не функциональной) enviroment model.
Т.е. в чистом виде ФП применимо в сравнительно узкой области, а за ее пределами разговоры о "простоте подстановочной модели" — это разговоры в пользу бедных.
Вот и приходится все время подменять тему обсуждения: вместо ФП мы уже говорим о ФЯ, а вместо ФЯ — о "отдельных функциональных конструкциях" в императивных языках, а заодно приписываем какую-то "функциональность" конструкциям, с ФП (прозрачностью по ссылкам) не связанным: паттерн-матчингу, разным видам типизации, делегатам и т.д.
Короче, как это все странно выглядит.
И сдается мне, дело не в тупых императивщиках, а в "консерватории" (т.е. в ФП) что-то не так.
Конечно, все высказанное — это субъективный взгляд на тему топика.
Хотелось бы выслушать людей, сведущих в ФП гораздо более меня.
Но только не на уровне трагических вздохов о снижении среднего уровня мастерства, а на уровне принципиальных вопросов.
Но существует одно качество, которое нельзя купить, — это надежность. Цена надежности — погоня за крайней простотой. Это цена, которую очень богатому труднее всего заплатить.
Это ж надо было так все с головы на ноги перевернуть.
AVC>На простом примере демонстрируется, что чистое ФП плохо совместимо с модульностью и ООП.
А модульность-то с какого бока с "чистым ФП" не совместима? С каких пор для нее присваивание нужно?
AVC>Без присваиваний, оказывается, это не дается.
AVC>Т.е. в чистом виде ФП применимо в сравнительно узкой области, а за ее пределами разговоры о "простоте подстановочной модели" — это разговоры в пользу бедных.
О как, нет ООП, значит, и не годится. Сурово.
AVC>Вот и приходится все время подменять тему обсуждения: вместо ФП мы уже говорим о ФЯ, а вместо ФЯ — о "отдельных функциональных конструкциях" в императивных языках, а заодно приписываем какую-то "функциональность" конструкциям, с ФП (прозрачностью по ссылкам) не связанным: паттерн-матчингу, разным видам типизации, делегатам и т.д. AVC>Короче, как это все странно выглядит. AVC>И сдается мне, дело не в тупых императивщиках, а в "консерватории" (т.е. в ФП) что-то не так.
То есть отсутсвие ООП в чистых ФЯ мешает императивным программистам понимать ФП; в том числе и O'Caml со Scheme, в которых и присваивание и ООП есть?
Логично.
*Шепотом*
Даже в Haskell есть на самом деле присваивание и даже ООП.
прежде чем понять рекурсию, необходимо понять рекурсию.
Здравствуйте, граммофон, Вы писали:
Г>Это ж надо было так все с головы на ноги перевернуть.
Переверни обратно.
И с этой удобной позиции объясни, почему ФП плохо дается императивщикам.
AVC>>На простом примере демонстрируется, что чистое ФП плохо совместимо с модульностью и ООП. Г>А модульность-то с какого бока с "чистым ФП" не совместима? С каких пор для нее присваивание нужно?
Напомню, что речь шла о примере из 3.1.2 The Benefits of Introducing Assignment.
"Модульность" я здесь использую в смысле coupling/cohesion, information hiding etc.
AVC>>Без присваиваний, оказывается, это не дается. AVC>>Т.е. в чистом виде ФП применимо в сравнительно узкой области, а за ее пределами разговоры о "простоте подстановочной модели" — это разговоры в пользу бедных.
Г>О как, нет ООП, значит, и не годится. Сурово.
Мне и правда следовало бы сказать не "ООП", а "объекты" (главное, что они обладают состоянием).
Г>То есть отсутсвие ООП в чистых ФЯ мешает императивным программистам понимать ФП; в том числе и O'Caml со Scheme, в которых и присваивание и ООП есть? Г>Логично.
Не так.
Мне (как тупому императивщику) непонятно, что такое ФП с присваиваниями.
Но существует одно качество, которое нельзя купить, — это надежность. Цена надежности — погоня за крайней простотой. Это цена, которую очень богатому труднее всего заплатить.
Здравствуйте, AVC, Вы писали:
AVC>Переверни обратно. AVC>И с этой удобной позиции объясни, почему ФП плохо дается императивщикам.
Да там выше объяснили уже. Потому же, почему на иностранный язык всегда сложнее учить, чем "родной". В общем случае, потому что новые идеи всегда хуже даются чем старые и уже усвоенные.
В психологии это называется ригидность. С возрастом только усугубляется.
Справиться с этим можно только если заранее сознательно стараться держать open mind.
Если не держать, то одинаково сложно будет учить что Haskell, что Oberon (который вообще что-то никто выучить "не может").
Отсутствие пособий, объясняющих на "популярном" уровне тоже, конечно играет роль, но, как мне кажется, гораздо меньшую.
И уж точно такой причиной не является якобы неприспособленность ФП для программирования.
AVC>"Модульность" я здесь использую в смысле coupling/cohesion, information hiding etc.
Да нет проблем, это как раз даже в Haskell идет все в комплекте. См., например, как там ATD реализуются через ограничение экспорта в отдельных модулях.
Про параметризуемые модули и функторы в ML упоминать наверное и смысла нет.
AVC>Не так. AVC>Мне (как тупому императивщику) непонятно, что такое ФП с присваиваниями.
Абсолютно то же самое, что и ФП с вводом-выводом. Совершенно одного порядка вещи.
прежде чем понять рекурсию, необходимо понять рекурсию.
Здравствуйте, граммофон, Вы писали:
Г>Да там выше объяснили уже. Потому же, почему на иностранный язык всегда сложнее учить, чем "родной". В общем случае, потому что новые идеи всегда хуже даются чем старые и уже усвоенные. Г>В психологии это называется ригидность. С возрастом только усугубляется. Г>Справиться с этим можно только если заранее сознательно стараться держать open mind.
Это, скорее, моральная проповедь (с содержанием которой я согласен), а не разбор конкретных трудностей усвоения ФП императивщиками.
Г>Если не держать, то одинаково сложно будет учить что Haskell, что Oberon (который вообще что-то никто выучить "не может").
Кто-нибудь жаловался на сложность Оберона?
Мол, Марья Ивановна, честное слово, учил-учил, учил-учил, ну никак не могу выучить этот проклятый Оберон!
Мой личный опыт говорит, что Оберон очень простой язык (я даже не могу сказать, что "учил" его; свободно писать на нем начал сразу; справедливости ради, то же можно сказать и про Scheme), а Оберон-система основана на нескольких простых принципах, немногим более сложных, чем язык.
А вот про Хаскель говорят иное. (Правда, кто освоил, хвалит, что тоже важно.)
Интересно, что в Оксфорде языки программирования изучают в такой последовательности: (1) Хаскель, (2) Оберон, (3) все остальное.
AVC>>"Модульность" я здесь использую в смысле coupling/cohesion, information hiding etc.
Г>Да нет проблем, это как раз даже в Haskell идет все в комплекте. См., например, как там ATD реализуются через ограничение экспорта в отдельных модулях. Г>Про параметризуемые модули и функторы в ML упоминать наверное и смысла нет.
Вопрос: откуда они параметризуются?
Если извне, то модульность ли это?
Меня вот что интересует.
В "обыкновенном" императивном программировании (в ООП особенно) именно побочные эффекты зачастую являются источником значительной гибкости.
Возможно, это связано с косвенностью (вызовов).
Мы обращаемся к переменной (не в математическом смысле) — это может быть процедурная переменная или указатель на объект.
Короче, я не стану распространяться на тему ООП (и косвенности, как способа решать те или иные проблемы ПО). Все это, скорее всего, ты лучше меня знаешь.
Главное, что это мощное средство управления "настройками" ПО. Чтобы модифицировать (например, подстроить под конкретного заказчика) поведение/вид программы достаточно поменять совсем чуть-чуть.
Я сильно подозреваю, что такой гибкости мы добиваемся именно за счет "нефункциональности" наших программ.
AVC>>Мне (как тупому императивщику) непонятно, что такое ФП с присваиваниями. Г>Абсолютно то же самое, что и ФП с вводом-выводом. Совершенно одного порядка вещи.
Если это то же самое, то переформулирую вопрос: что такое ФП с вводом-выводом?
Я вот слышал, что ввод-вывод по своей природе императивен.
Но существует одно качество, которое нельзя купить, — это надежность. Цена надежности — погоня за крайней простотой. Это цена, которую очень богатому труднее всего заплатить.
Здравствуйте, AVC, Вы писали:
AVC>Если это то же самое, то переформулирую вопрос: что такое ФП с вводом-выводом? AVC>Я вот слышал, что ввод-вывод по своей природе императивен.
Да ничего там особенного с ним нет. С ленивыми языками проблемы, это да, но далеко не все ФЯ ленивые.
Ввод-вывод не столько императивен, сколько детерминирован, важно, чтобы порядок операций сохранялся. Поэтому проблемы только в тех языках, которые этот порядок меняют.
Здравствуйте, Quintanar, Вы писали:
AVC>>Я вот слышал, что ввод-вывод по своей природе императивен.
Q>Да ничего там особенного с ним нет. С ленивыми языками проблемы, это да, но далеко не все ФЯ ленивые.
Действительно, не все ФЯ ленивые.
Но, IMHO, важно то, что "лень" основана на "функциональности" aka "референциальной прозрачности".
Если есть проблемы с ленивыми языками, то именно потому, что есть проблемы с ФП как таковым.
Q>Ввод-вывод не столько императивен, сколько детерминирован, важно, чтобы порядок операций сохранялся. Поэтому проблемы только в тех языках, которые этот порядок меняют.
Если важен порядок операций, то это не ФП.
Ведь ФП перспективно для распараллеливания программ именно потому, что порядок вычислений не важен, что опять-таки основано на "прозрачности по ссылкам".
У меня нет цели "доказать", что ФП — это "плохо".
Просто на мой взгляд, отвечая на тему топика, все "ломанулись" по легкому пути: стали морализировать.
Я же делаю робкую попытку понять, что в самом ФП трудно дается императивщикам.
Но существует одно качество, которое нельзя купить, — это надежность. Цена надежности — погоня за крайней простотой. Это цена, которую очень богатому труднее всего заплатить.
Здравствуйте, AVC, Вы писали:
AVC>У меня нет цели "доказать", что ФП — это "плохо". AVC>Просто на мой взгляд, отвечая на тему топика, все "ломанулись" по легкому пути: стали морализировать. AVC>Я же делаю робкую попытку понять, что в самом ФП трудно дается императивщикам.
ИМХО виной всему — привычка. Привычка смотреть на программу, как на последовательность инструкций, меняющих значения переменных. Такой подход в ФП работает плохо, если вообще работает. В итоге программист с приличным опытом оказывается в положении человека, которому нужно научится ходить заново, причём используя другие группы мышц. Вместо циклов и состояний — рекурсия и чистые первоклассные функции.
Я думаю, это как с человеческими языками. Вот знает кто-то русский. Приезжает в Болгарию или Сербию и более-менее легко осваивает чужой (но родственный) язык, почти с ходу способен общаться. А приехав в Китай, обнаруживает, что чужие (и не родственные) языки даются не так легко.
Похоже я тоже скатываюсь в "морализирование" . Честно говоря, не знаю, что в ФП для императивщиков является самым трудным. Ау, императивщики!
Есть SICP для изучения LISP'а. Есть, скажем, YAHT для Хаскелла. Очень редко встретишь конкретные вопросы по ним в rsdn.declarative, чтобы выдать статистику по трудностям. Вроде всем, кто серьезно взялся изучать ФЯ и имеет более-менее приличный багаж в ИЯ эти курсы вполне по силам. А флейм типа: "А на хрен нужна фича X языка Y!? Это полный отстой, мы в своём ИЯ Z это не использовали и приклеить это в нашем Z некуда и незачем (с дальнейшим убедительны доказательством, что в Z фича X — пятое колесо)" — такой флейм трудностей в изучении ФЯ действительно не выявляет и, вообще, особого смысла не имеет.
Здравствуйте, deniok, Вы писали:
D> Честно говоря, не знаю, что в ФП для императивщиков является самым трудным. Ау, императивщики!
Ломка мышления. Как ты правильно сказал начинают работать совсем другие мышцы.
С чем бы это сравнить. Допустим гребля на каноэ и езда не велосипеде.
Как ? Тут нет весел ? И работать надо ногами ? Вы наверное шутите.. Ах, оно еще в базовом варианте и плавать не умеет, а необходимо делать изврат в виде водного велосипеда ??
И так далее... Кто-то ломает мышление. Кто-то нет.
Такие дела (с)
Здравствуйте, deniok, Вы писали:
D>Вместо циклов и состояний — рекурсия и чистые первоклассные функции.
Если использование хвостовой рекурсии вместо циклов не вызывает проблем (по крайней мере, в Scheme), то использование чистых функций вместо состояний — вызывает.
По первому впечатлению, это приводит к перекосам в структуре программы.
Вот отрывок из вышеупомянутого раздела SICP (3.1.2):
Разумеется, ту же последовательность случайных чисел мы могли бы получить без
использования присваивания, просто напрямую вызывая rand-update. Однако это
означало бы, что всякая часть программы, которая использует случайные числа, должна
явно запоминать текущее значение x, чтобы передать его как аргумент rand-update.
Чтобы понять, насколько это было бы неприятно, рассмотрим использование случай-
ных чисел для реализации т. н. моделирования методом Монте-Карло (Monte Carlo
simulation).
Дальше разбирается, почему это было бы плохо.
В голову непосвященного, вроде меня, закрадывается крамольная мысль, что ФП не очень дружит с инкапсуляцией.
Но существует одно качество, которое нельзя купить, — это надежность. Цена надежности — погоня за крайней простотой. Это цена, которую очень богатому труднее всего заплатить.
Здравствуйте, AVC, Вы писали:
AVC>Дальше разбирается, почему это было бы плохо. AVC>В голову непосвященного, вроде меня, закрадывается крамольная мысль, что ФП не очень дружит с инкапсуляцией.
Инкапсуляцией чего? Состояния? Нет в чистом ФП состояний. Нечего и инкапсулировать. LISP — не чистое ФП. Там состояния вводятся и оператор присваивания тоже.
Я мог бы описать, скажем, как работает монада состояния в Хаскелле, решающая в общем виде ту же проблему, что и введение присваивания локальным переменным для сокрытия состояния в SICP, но чисто функциональным способом. Но я думаю, что
(1) это только запутает тебя, потому что это строится на довольно сложной эквилибристике с монадическим типом (в след. номере RSDN Magazine Влад обещал перевод второй части GIH, там это будет, хотя этот раздел 9.3, хм..., скажем так: редкая птица долетит до его серидины )
(2) это в 99% случаев совершенно не нужно, поскольку чистое ФП решает подобные задачи архитектурно по-другому. В Хаскелле грязные ботинки снимают в IO-прихожей, зато в остальном доме чисто.
А вот инкапсуляция функциональности в ФП очень даже присутствует. В функциях
Здравствуйте, deniok, Вы писали:
D>скажем так: редкая птица долетит...
А потом все еще делают такие озабоченные лица и начинают разводить руками и спрашивать друг у друга: с чего это вдруг императивщикам трудно дается ФП?!
— Вот Вы знаете?
— Нет!
— А Вы?
— Понятия не имею!!
— Императивщики? Боже, кто это?!
D>(2) это в 99% случаев совершенно не нужно, поскольку чистое ФП решает подобные задачи архитектурно по-другому. В Хаскелле грязные ботинки снимают в IO-прихожей, зато в остальном доме чисто.
Факт, архитектурно по-другому.
А как?
И потом, злые языки говорят, что монады (IO, списки и т.п.) — скрытый императив; но он, дескать, любит, чтобы его называли чистым ФП.
Вот и разберись...
Но существует одно качество, которое нельзя купить, — это надежность. Цена надежности — погоня за крайней простотой. Это цена, которую очень богатому труднее всего заплатить.
Здравствуйте, AVC, Вы писали:
Г>> Про параметризуемые модули и функторы в ML упоминать наверное и смысла нет. A> Вопрос: откуда они параметризуются? A> Если извне, то модульность ли это?
Примерно оттуда же, откуда параметризуются generic packages в Аде. Но Вы же не станете утверждать, что в Аде нет модульности?
A> В "обыкновенном" императивном программировании (в ООП особенно) именно A> побочные эффекты зачастую являются источником значительной гибкости.
Оператор GOTO тоже даёт значительную гибкость, вот только Вы от него почему-то отказались вслед за Виртом и Хоаром...
Так почему бы не сделать следующий шаг и не отказаться от побочных эффектов? Ну хотя бы минимизировать их использование только до ввода/вывода...
Здравствуйте, AVC, Вы писали:
AVC>- Вот Вы знаете? AVC>- Нет! AVC>- А Вы? AVC>- Понятия не имею!! AVC>- Императивщики? Боже, кто это?! AVC>
Не, не так:
— Как сделать состояние?
— Есть способ, но это никому не нужно!
— Ну покажи!
— ... (показывает, используя монадическую артиллерию)
— Блин, как сложно. Плохой язык.
В соседней ветке хороший пример с goto. Представь — сделали императивный язык без него. Набегает народ: а как выходить из вложенных циклов? Ну описываешь им известные техники, в конце говоришь но можно и сэмулировать goto, правда сложно. О, покажи! Показываешь. Реакция с гордостью за свой язык: "Фу, как сложно, а у нас это goto прямо в языке есть! И писать ничего не надо."
AVC>Факт, архитектурно по-другому. AVC>А как?
В какой задаче?
Например, в Монте-Карло, с неспецифицированным генератором случайных чисел, как в SICP?
Передаёшь в
randoms :: RandomGen g => g -> [a]
этот генератор, и пользуешься получившимся бесконечным ленивым списком случайных чисел в свое удовольствие. Как устроен randoms можно посмотреть в System.Random
randoms g = (\(x,g') -> x : randoms g') (random g)
Здесь
random :: RandomGen g => g -> (a, g)
возвращает пару из случайной величины типа a и нового генератора.
Блин! Кажется, я понял одну из причин обсуждаемых трудностей! Понять как всё устроено и работает внутри — значит опускаться всё ниже и ниже по уровням абстракции. Для императивного мира — это путь, в конце которого биты, байты, регистры, ассемблер. Но для чистого функционального мира это вовсе не так! В конце этого пути в ФП лежат базовые комбинаторы, или лямбда-исчисление.
Здравствуйте, AVC, Вы писали:
AVC>И потом, злые языки говорят, что монады (IO, списки и т.п.) — скрытый императив; но он, дескать, любит, чтобы его называли чистым ФП.
Ничего скрытого. Монады позволяют моделировать императивную модель вычислений. Оставаясь при этом чистым ФП. Можно на компьютере во всех деталях смоделировать работу гидравлического пресса. От этого компьютер не станет гидравлическим прессом.
Есть одна монада (IO), которая отвечает за работу с окружающим миром. Работа с окружающим миром сделана в Хаскелле через монаду именно из-за того, что монады способны чисто функционально описывать императивную модель вычислений. Были и другие предложения для IO, но в Хаскелле был выбран такой способ.
Привет delphiнам!
Г>>> Про параметризуемые модули и функторы в ML упоминать наверное и смысла нет. A>> Вопрос: откуда они параметризуются? A>> Если извне, то модульность ли это? G>Примерно оттуда же, откуда параметризуются generic packages в Аде. Но Вы же не станете утверждать, что в Аде нет модульности?
Конечно, не стану.
Но для меня важно, что модуль может иметь собственные переменные (и собственнически инкапсулировать их), а в ФП это невозможно (?).
До меня потихоньку доходит, что мы, императивщики, не так уж рвемся расставаться с побочными эффектами.
A>> В "обыкновенном" императивном программировании (в ООП особенно) именно A>> побочные эффекты зачастую являются источником значительной гибкости.
G>Оператор GOTO тоже даёт значительную гибкость, вот только Вы от него почему-то отказались вслед за Виртом и Хоаром... G>Так почему бы не сделать следующий шаг и не отказаться от побочных эффектов? Ну хотя бы минимизировать их использование только до ввода/вывода...
У самих, между прочим, тоже рыльце в пушку: монады-то не только для ввода/вывода...
А если серьезно, то как обойтись без goto мы знаем. Да и теорема Боэма-Джакопини есть.
А вот как обойтись вообще без побочных эффектов (ввод/вывод не в счет) — мы просто не знаем...
Но существует одно качество, которое нельзя купить, — это надежность. Цена надежности — погоня за крайней простотой. Это цена, которую очень богатому труднее всего заплатить.
AVC>У самих, между прочим, тоже рыльце в пушку: монады-то не только для ввода/вывода...
Да монады — это обычный класс типа; интерфейс и не более того. Правда весьма полезный. Нет там никакого волшебства и железячных хаков. Ввод-вывод, ясный пень, должен общаться с внешним миром, но выбор монадического интерфейса для него — просто дизайнерское решение (одно из рассматривавшихся в своё время). Для чистого и ленивого языка — то что доктор прописал.
AVC>А вот как обойтись вообще без побочных эффектов (ввод/вывод не в счет) — мы просто не знаем...
Ну так постарайся привести минимальную задачку, где тебе кажется, что без этого нельзя. Конечно, если приложение читает биты из регистров одной железки и пишет их в регистры другой, то тут функциональный подход — не лучшее решение. Но если у него (приложения) есть отличная от тривиальной логика, то её можно описать как императивно, так и чисто функционально. Впрочем и тривиальную тоже можно:
Здравствуйте, deniok, Вы писали:
D>Ну так постарайся привести минимальную задачку, где тебе кажется, что без этого нельзя. Конечно, если приложение читает биты из регистров одной железки и пишет их в регистры другой, то тут функциональный подход — не лучшее решение. Но если у него (приложения) есть отличная от тривиальной логика, то её можно описать как императивно, так и чисто функционально. Впрочем и тривиальную тоже можно:
Допустим, к примеру, что я хочу подменить фабричный объект или фабричную процедуру, ответственные за создание объектов определенного типа.
Пусть, для определенности, это будет фабричная процедура, реализованная через инсталляцию процедурной переменной, что-то вроде:
MODULE M;
TYPE
Object* = POINTER TO RECORD ... END;
ConcreteObject = POINTER TO RECORD (Object) ... END;
FabrProc* = PROCEDURE () : Object;
...
VAR
fabrique*: FabrProc;
...
PROCEDURE DefaultFabrique () : Object;
VAR p: ConcreteObject;
BEGIN
NEW(p);
... (* инициализация *)
RETURN p
END DefaultFabrique;
BEGIN
fabrique := DefaultFabrique
END M.
Код a-la Oberon, но это совершенно неважно. Речь идет об обычном "порождающем" паттерне.
Главное, объекты какого-то типа создаются через фабричную процедуру.
Мы хотим ее поменять (прямо или косвенно переприсвоив значение fabrique), чтобы обращение к fabrique из произвольных мест программы приводило к созданию объектов иного конкретного типа, отличного от типа по умолчанию.
Как это делается в ФП?
Но существует одно качество, которое нельзя купить, — это надежность. Цена надежности — погоня за крайней простотой. Это цена, которую очень богатому труднее всего заплатить.