Оберон-технология: особенности и перспективы |
Тематика обсуждения: Оберон-технология. Особенности, перспективы, практическое применение.
Всего в теме 6256 сообщений
Добавить свое сообщение
Отслеживать это обсуждение Обсуждение из раздела Школа ОБЕРОНА
№ 3456 24-03-2007 16:19 | |
Ответ на »сообщение 3451« (Geniepro)
___________________________
Ответ на »сообщение 3450« (AVC)
ведь тут идёт речь о внедрении модулем B своих сущностей в модуль A, который даже и не подозревает о существовании модуля B!
А когда в ОС вы устанавливаете драйвер, к примеру, монитора, то он - о ужас!! - внедряет "свои сущности" в область ядра операционной системы - а авторы операционной системы даже не подозревали о наличии вашего драйвера для экзотической видеокарты из провинции Шунь-Янь КНР!
наверное, нужно зашивать все реализации драйверов статически в ядро ОС, чтобы не нарушать "referential transparency"?
Вообще-то схема "точка предоставления сервиса даже не подозревает о конкретной реализации сервиса" является ключевой для системного программирования...
№ 3455 24-03-2007 16:12 | |
Ответ на »сообщение 3451« (Geniepro)
___________________________
Ответ на »сообщение 3450« (AVC)
___________________________
Но ведь это же хак! Это пляски с бубном! Это же чистый императив!
Это не хак. Это как раз пример нормальных межмодульных отношений. Статический импорт - это примитив... Для компонентных архитектур используется именно то, что Вы назвали "хаком"...
Интерфейсные модули, используемые пользовательскими приложениями, ничего не знают о своей конкретной реализации, они предоставляют абстрактные объектно-ориентированные разъемы.
Затем пишутся отдельные модули конкретной (в частности, платформенно-зависимой) реализации, которые подключаются по ОО-разъемам к интерфейсным модулям. В результате мы можем перекоммутировать конкретную реализацию не только без перекомпиляции, но даже без перезапуска.
Пусть у нас есть модуль A, предоставляющий какой-то сервис и высокоуровневые интерфейсы к нему, и модуль AImpl - с низкоуровневой платформенно-зависимой реализацией сервисов A.
Естественный и первый позыв - импортировать из A AImpl. Однако в компонентной архитектуре все наоброт - A вообще ничего не знает про AImpl, он только предоставляет разъемы для его подключения. Импорт реверсирован - AImpl импортирует A и подключается к нему по разъемам.
AImpl никем более не импортируется. В нужный момент мы можем его выгрузить, загрузить другую реализацию, которую закоммутировать к A. При этом ни один из клиентов A не заметит подмены.
Стоит опять подумать в "железных" аналогиях. A выступает в роли монтажной платы, на которой коммутируются клиенты сервиса и его реализации.
Т.е. в компонентной архитектуре н
Например, в BlackBox
№ 3454 24-03-2007 16:05 | |
Ответ на »сообщение 3442« (Булат Зиганшин)
___________________________
Ответ на »сообщение 3440« (Руслан Богатырев)
с другой стороны, это и не свойство языка, а компилятора, верно? на основании спецификации типов экспортируемых модулем единиц для любого языка можно создать такую компонентную систему
Не совсем. Один из примеров: для компонентности, как я уже упоминал, нужно автоматическое управление памятью. Для автоматического управления памятью нужна а) поддержка метаинформации о типах б) герметичность системы типов. В языках С-семейства нет ни а) ни б). При этом а) еще можно ввести. Но б)... Никто не может запретить в С/С++ программисту засувать указатель в int-переменную. После чего диспетчер памяти мгновенно сядет в лужу, и пройзойдет фатальный сбой системы... О какой надежности и интегрируемости компонент при таком "дырявом решете" в типизации языка может идти речь?
№ 3453 24-03-2007 11:17 | |
Ответ на »сообщение 3417« (Сергей Перовский)
___________________________
самая крупная странслированная программа, которую я знаю была порядка 300 строк
а может большие программы просто в память не влазили (по исходникам или exe-шнику)?
№ 3452 24-03-2007 11:13 | |
Ответ на »сообщение 3450« (AVC)
___________________________
Вот для таких "трюков" нам и нужны переменные -- для (пере)коммутации "на лету".
Вот почему я подозреваю (возможно, и неправильно; это только подозрение) ФП в недостаточной модульности.
имхо вы смешиваете уровень реализации и уровень порграммистской абстракции. на нижнем уровне функция в ФП языке точно так же может быть представлена указателем, и ничто не мешает поменять этот указатель на лету
вообще, представление о том, что в чистых ФП побочные эффекты невозможны - оно, разумеется, ошибочно. куда ж бех них... :) просто в чистых ФП языках функции с побочными эффектами описываются либо как имеющие лополнительный псведопараметр, либо как continuation и т.д., т.е. исходя из типа функции можно определить - либо она без всех эжтих наворотов и по определению чистая, либо нет
так вот, модули с заменяемой реализацией скорее будут экпортировать процедуры с побочным эффектом, а не чистые функции - хотя бы уж для того, чтобы оптимизатор не скешировал ненароком их результаты :) и потому никаких различий в том, как это можно сделать там и там я не вижу
№ 3451 24-03-2007 10:35 | |
Ответ на »сообщение 3450« (AVC)
___________________________
Но ведь это же хак! Это пляски с бубном! Это же чистый императив!
Это нарушает все нормы чистоты ФП и "referencial transparency" в частности!
И после этого Вы удивляетесь трудностям формальной верификации программ? Ну ещё бы...
имхо, в рамках "чистого" ФП такие трюки невозможны, и никакие монады тут не помогут - ведь тут идёт речь о внедрении модулем B своих сущностей в модуль A, который даже и не подозревает о существовании модуля B! Тут действительно всё завязано на изменении чужого состояния.
Хотя, в том же Хаскелле, можно такое проделать, используя возможности модуля System.IO.Unsafe, например функцию unsafePerformIO. Можно придумать что-то типа: создаём в модуле А набор переменных, которым тут же присваиваем какие-то функции, затем в модуле B перезаписываем эти переменные с помощью нехороших системных хаков - и вуаля!
Но это в принципе может привести ко всякого рода глюкам при оптимизации программы - например, оптимизатор может подставить вместо фиктивных переменных из А те функции, которые им присвоены в этом самом модуле А, и не использовать сами эти переменные. Тогда, сколько не будут модули В и С перезаписывать эти переменные - эффекта это не возымеет - ведь транслятор будет считать, что всё чисто, и эти переменные никому не нужны на самом деле...
№ 3450 24-03-2007 09:36 | |
Ответ на »сообщение 3447« (Geniepro)
___________________________
Ответ на »сообщение 3432« (Илья Ермаков)
___________________________
В Обероне я могу не то что даже реализацию работы с файлами, а реализацию менеджера памяти или загрузчика модулей "подмахнуть" прозрачно на лету без перезапуска программы, так что весь работающий код даже не заметит подмены... Таковы возможности модульных архитектур.
извините, я не понял, как это Вы сможете перезагрузить модуль без выгрузки других модулей, его использующих?
А уж перезагрузка менеджера памяти или загрузчика модуле без остановки и выгрузки всех других модулей - разве такое возможно???
Остановка же всех модулей и их выгрузка с последующей загрузкой - это и есть перезагрузка программы!
Вот оставить бы Вас на денек в таком удивлении! ;)
Но совесть не позволяет.
Насколько я понял, Илья имеет в виду следующее.
Допустим, у нас есть модуль A, в котором определены процедурные переменные или указатели на объекты, отвечающие за определенную функциональность.
В случае необходимости использовать эту функциональность, этот модуль A импортируется другими модулями.
Теперь пусть у нас будет модуль B, реализующий эту функциональность. Модуль B импортирует модуль A, но сам не импортируется другими модулями. В процессе загрузки модуля B (вызываемой косвенно, а не через секцию IMPORT) выполняется его блок инициализации, инсталлирующий свои процедуры и/или объекты в "гнезда" модуля A.
Допустим, в каких-то обстоятельствах нам не нравится "стратегия", с помощью которой модуль B реализует эту функциональность.
Тогда мы (опять-таки косвенно) загружаем некий модуль C, реализующий ту же функциональность иным способом. Модуль C инсталлирует свои процедуры/объекты в "гнезда" модуля A, меняя его функциональность "на лету".
После этого модуль B можно безболезненно выгрузить, т.к. он сам напрямую никем не импортируется.
Voila!
Вот для таких "трюков" нам и нужны переменные -- для (пере)коммутации "на лету".
Вот почему я подозреваю (возможно, и неправильно; это только подозрение) ФП в недостаточной модульности.
№ 3449 24-03-2007 08:20 | |
Ответ на »сообщение 3447« (Geniepro)
___________________________
извините, я не понял, как это Вы сможете перезагрузить модуль без выгрузки других модулей, его использующих?
А уж перезагрузка менеджера памяти или загрузчика модуле без остановки и выгрузки всех других модулей - разве такое возможно???
очень просто. в erlang новая версия модуля загружается в память и используется для обслуживания новых вызовов в то время как старая продолжает работать пока не закончатся использующие её процессы. если например это модуль, обслуживающий телефонный разговор, то такая политика прекрасно работает - главное чтобы от старого модуля новому не приходилось передавать никакие ресурсы. с распределением памяти такого наверно не получится :)
№ 3448 24-03-2007 08:18 | |
Ответ на »сообщение 3415« (Geniepro)
___________________________
Вот и мне хотелось бы теперь сравнить два подхода - хаскеллерский и обероновский, и обсудить...
Вот это дело. Большое спасибо за столь подробный "рентген". Надо будет сопоставить. Кое-что попробую сделать сам, благо теперь есть два исходника, условие и подробный разбор процесса решения.
№ 3447 24-03-2007 07:01 | |
Ответ на »сообщение 3432« (Илья Ермаков)
___________________________
В Обероне я могу не то что даже реализацию работы с файлами, а реализацию менеджера памяти или загрузчика модулей "подмахнуть" прозрачно на лету без перезапуска программы, так что весь работающий код даже не заметит подмены... Таковы возможности модульных архитектур.
извините, я не понял, как это Вы сможете перезагрузить модуль без выгрузки других модулей, его использующих?
А уж перезагрузка менеджера памяти или загрузчика модуле без остановки и выгрузки всех других модулей - разве такое возможно???
Остановка же всех модулей и их выгрузка с последующей загрузкой - это и есть перезагрузка программы!
Естественно. Вопрос в том - поменять в статике или поменять в динамике.
Для перестройки "на лету" у ФП есть только один (старый, добрый, весьма мощный) способ - метапрограммирование, самомодифицирующийся код. Но это вотчина LISP, а никак не Haskell. В Haskell путь один - динамически регенерировать исходный код и перезагружать его...
В принципе, для Хаскелла построение среды, аналогичной БлэкБоксу - тоже вполне возможно, просто пока этого никто не удосужился сделать, увы...
Но никаких ограничений на это нет. По крайней мере, этих ограничений в Хаскелле ничуть не больше, чем в Оберонах/КП...
Нужен всего лишь механизм динамической коммутации модулей, а он может быть и декларативным. Но это еще нужно сделать, а ФП-исты в большей части равнодушны к инженерии, все больше "высокой математикой" балуются :-) Одни сферические кони в вакууме... :-)
Ну как сказать, как сказать...
Возможно, такая среда просто-напросто не так уж и нужна на самом деле...
Добавить свое сообщение
Отслеживать это обсуждение
Дополнительная навигация: |
|