Продолжение темы, затронутой в предыдущей заметке, посвящённой проблемам сверхобобщённого программирования.
В доработке...Общие суждения
- Обобщения строятся на единообразии используемого
- Единообразие достигается в тождестве или в подобии
- Тождество может достигаться
- за счёт использования более широкого понятия (усложение модели)
- или за счёт избавления от второстепенных деталей, то есть абстракции (упрощение модели)
- Абстракция в рамках задачи самостоятельна и не требует связи с исходной более сложной моделью
- Подобие достигается за счёт косвенности через посредника, единообразно представляющего разные вещи. Из-за частичного сходства многие программисты путают это с абстрагированием
- В отличии от абстракции косвенность требует связи посредника с исходной моделью
- Косвенность может как сохраняться во время исполнения, так и устраняться при подготовке
- Можно выделить два вида посредничества: П0 — обеспечивающих одинаковое поведение (обычно приблизительно) и П1 — рассчитанных на одинаковую стыковку элементов с разным поведением
- П0 — платформы; нужны для обобщения условий, в которых работает код, для обеспечения его переносимости
- П1 — конструкторы; нужны как обобщённый способ создания разного поведения
- Тождество может достигаться
- Желательно выделение только естественного единообразия. Приведение недостаточно совместимых вещей к единому представлению должно рассматриваться как ошибка
- Когда выбор стоит не столько между общим и частным, сколько междум общими частностями и разрозненными частностями, не стоит отказываться от частного в пользу общего без большой надежды, что всё так и останется. Общепринятые частности не всегда, но часто относятся к такому случаю
- Инструмент должен стремиться к унификации приёмов, предлагая в большей степени дополняющие друг друга средства, чем соперничающие между собой
- Инструмент должен предлагать обобщения на едином уровне представления. Пример нарушения — внутристроковые языки, макросы препроцессора и синтаксические макросы против средств основного языка
- Не должно быть драматичной разницы между исполнением (runtime) и трансляцией (compiletime), потому что трансляция — это лишь исполнение компилятора. Вещи, необходимые компилятору, могут понадобиться и другим программам
- Эффективность крайне важна для обобщений. Чем она выше, тем потенциально больше возможность переиспользования. Обобщение не может считаться полноценным, если оно ограничено в применение из-за неэффективности
- Специализация является важным способом повышения эффективности решений, сформулированных обобщённо
- Лучше, если специализация будет доступна и во время исполнения
- Специализация является важным способом повышения эффективности решений, сформулированных обобщённо
- Высокая контролируемость важна, так как из-за повышенного переиспользования сверхобобщённый код может обрасти бо́льшим количеством связей, что может привести к усложнению их понимания и использования без дополнительной помощи. Инструмент должен предоставлять возможность строгих указаний, что ожидается
- Строгая статическая типизация и ограничения доступа, защищая от неправильного использования, также создают препятствия для ряда обобщений.
- Проще всего создать возможность эффективного переиспользования в безтиповом языке, но исчезает защита от ошибок и подсказки по правильному использованию
- Строгая динамическая типизация позволяет добиться схожей гибкости при сохранении защиты от ошибок во время исполнения, но теряются эффективность выполнения и статическая защита
- Сверхобобщённая же статическая типизация, сохраняя эффективность и наилучшую защиту, оказывается сверхсложной как для воплощения, так и для использования, то есть защищает не только от ошибок, но и от правильного кода
- Статическая типизация может служить не только дополнительным препятствием для переиспользования, но и наоборот служить основой для него, когда типы служат предметом рассмотрения кода
- Поскольку однозначно хорошее решение неизвестно, то прагматичный язык вынужден предоставлять компромиссное решение, сочетая эти возможности
- Классификация — это способ выделения подобия в рамках строгой типизации
- Правильная классификация не требует общего происхождения, а основана только на нахождении общих свойств, которые к тому же могут быть выражены по-разному. Одно и то же может входить в разные классы и даже в один класс входить по-разному в зависимости от рассмотрения
- Переменные подклассов применимы на чтение там, где ожидаются переменные класса, но в общем случае не применимы на запись, хотя при динамическом контроле подстановка допустима для случая, когда записываемое значение динамически принадлежит соответствующему подклассу. Инструмент должен уметь различать эти особенности, чтобы не мешать правильному переиспользованию
- Единообразие достигается в тождестве или в подобии
- Обобщение нужно но не только для одновременно существующих вещей, но и для разнесённых во времени. Инструмент должен учитывать развитие кода и давать возможность гладкой эволюции. Переиспользование не должно препятствовать последующему внесению улучшений в код, в том числе, и для большего обобщения
- Общая среда исполнения не должна выстраивать традиционных преград для взаимодействия кода. Это приводит к созданию частично похожих, но несовместимых систем кодирования по разные стороны этих преград, а также допослнительных средств для их преодоления
- Частный код (proprietary) создаёт дополнительное препятствие для обобщённого кода через усложнение переиспользования
- Платформа с торчащим наружу машинным представлением кода, как и распространение кода в машинном виде, тоже служат препятствиями для переиспользования и обобщения
Особенности языка для сверхобобщённого программирования
Эти особенности являются частными следствиями общих суждений.
- Данные и их тип связаны, но остаются отдельными сущностями, устраняя таким образом одно из препятствий для обобщения при сохранении безопасности данных
- Данные характеризуются ёмкостью
- Тип — это способ рассмотрения данных, не зависящий напрямую от ёмкости данных
- В случае чтения ёмкость данных может быть ниже ёмкости типа (вплоть до 0), а в случае записи — выше
- Тип — это тоже данные, но всегда неизменяемые при наличии привязки к данным без владения ними
- Статический тип, не учавствующий в рефлексии времени исполнения, не требует своего явного присутствия в памяти после трансляции
- Все типы являются обобщёнными в том смысле, что любые данные с рассмотрением, соответствующим внешнему описанию типа, могут рассматриваться как данные этого типа
- Новый тип для тех же данных может быть собран как надстройка над старым типом без необходимости менять что-либо в самих данных
- Подпрограмма принимает, фактически, два параметра — тип и данные. Они способны представлять любой набор обычных параметров. Синтаксически это не заметно
- Статическое и динамическое обобщения делаются единообразно
- Для статического обобщения параметр-тип является постоянной, а для динамического — переменной
- Значение для переменной-типа может быть получено не только из набора предопределённых в коде значений, но и собрано во время исполнения по входным данным
- Динамически полученный тип можно привести к статически заданному типу, если тот соответствует его требованиям
- Обобщённое понятие массива
- Возможна длина 0
- Срез массива тоже является массивом уменьшенной длины
- Размерность массива можно приводить к другому значению, сохраняя общую ёмкость
- В частности, любой тип может быть представлен как массив этого типа единичной длины
- Часть записи, подряд содержащая однородные элементы, тоже может рассматриваться как массив соответствующей длины
- Так как все типы являются обобщёнными, то всегда можно выделить уровень обобщения, на котором элементы будут однородными. Впрочем, такое приведение может быть ресурсоёмким
- Числовые типы
- Типы без знака являются лишь сокращением для обозначения переменных типов со знаком с указанием недопустимости отрицательных значений
- Ёмкость типов без знака равна ёмкости неотрицательных значений соответствующих им типов со знаком
- Ёмкость положительных и отрицательных значений у типов со знаком одинакова
- Значение по модулю и смена знака гарантировано происходят без переполнения отрезка значений операнда
- Без знака могут быть как целые, так и дроби
- Признаки переполнения верхней и нижней границ, а также неопределённость могут быть частью типа чисел (целых тоже), но не являются свойством по умолчанию (для дробей тоже)
- Для целых специальные значения вычитаются из отрезка значений типа-основы, для дробей зарезервированы в любом случае
- Признаки переполнения не следует трактовать как бесконечности
- При умножении на 0 результатом будет 0
- Если значение вычитается из самого себя, когда возможно отследить, что оно действительно пришло из одного источника, то результатом будет не неопределённость, а 0
- Аналогично для деления на само себя будет 1
- В промежуточных данных (переменных подпрограмм) допустимы только типы чисел со знаком
- Вычисления производятся в более ёмком типе относительно типа операндов
- Результат может сохраняться без дополнительных преобразований в типе, равном максимально ёмкому типу операндов, но с проверкой возможности переполнения
- Типы без знака являются лишь сокращением для обозначения переменных типов со знаком с указанием недопустимости отрицательных значений
- Место хранения данных
- С точки зрения использования нет различения между статическим (в том числе локально) и динамически размещёнными переменными. Но есть различение по владению данными — то, что косвенно задевалось способом размещения
- Утверждения (assertion), применённые к формальным параметрам, могут быть переиспользованы как мягкие проверки (if) для случаев, когда фактические параметры могут не соответствовать этим утверждениям
Комментариев нет:
Отправить комментарий