Как система статических типов влияет на разработку языка на основе прототипов?

15

Статья Википедии на прототипы языков на основе содержит следующий пункт:

Почти все системы на основе прототипов основаны на интерпретируемых и динамически типизированных языках. Однако системы, основанные на статически типизированных языках, технически осуществимы.

Каким образом статическая система типов накладывает ограничения или усложняет язык на основе прототипов, и почему существуют более динамически типизированные языки-прототипы?

Джо
источник
2
+1 и fav'd: Я сам долго обдумывал это и не нашел каких-либо чрезвычайно сложных проблем со структурной системой типов. На самом деле, это настолько беспокоит меня, что я хочу
Я только начинаю этот процесс сам по той же причине :)
Джо

Ответы:

6

Граница между фундаментальным типом и объектом размыта и часто искусственно вводится. Например, в C структура - это просто набор записей, просто производный необъектный тип. В C ++ структура - это класс со всеми открытыми полями, объект. Тем не менее, C ++ почти полностью обратно совместим с C ... граница здесь действительно мягкая.

Для программирования на основе прототипов вы должны иметь изменяемые объекты во время выполнения. Они ДОЛЖНЫ иметь мягкий тип, потому что каждый изменяется во время выполнения, класс одного вида меняется на другой - его тип меняется.

Вы можете сохранить основные и производные необъектные типы как статические. Но это вводит странное несоответствие, объекты мягкого типа, не-объекты статического типа, и между ними должен быть установлен жесткий барьер. Должны ли вы быть в состоянии изменить структуру? Строка? Должен ли Number быть классом или фундаментальным типом, или набором фундаментальных типов, int / float / bignum / etc?

Это более естественно и легко изучать, использовать и писать, чтобы иметь эту униформу, все типы являются изменяемыми или никакие типы не могут изменяться во время выполнения. Если вы объявляете, что только один тип (Object) является изменяемым, вы в конечном итоге сталкиваетесь с головными болями и проблемами обоих миров.

Статический тип:

  • легче реализовать
  • быстрее / эффективнее
  • безопаснее
  • легче поддерживать / документировать большие системы благодаря абстракции.

Динамический тип:

  • быстрее писать в
  • более кратким
  • язык легче выучить
  • больше прощать за ошибки проектирования.

Смешивая два, вы жертвуете много.

  • Реализация становится сложнее, чем любой из предыдущих двух.
  • скорость зависит, используете ли вы мягкие типы или нет ... Если вы это делаете, она низкая, если нет, зачем вообще выбирать язык?
  • безопасность типов вне окна для всех типов объектов.
  • Следить за тем, как один тип превращается в другой, довольно трудная задача. Документировать это - очень сложно.
  • Вам все еще нужно вести всю бухгалтерию с основными типами, которые убивают краткость и скорость письма
  • Сложность языка выше (сложнее в изучении), чем у любого из «конкретных»,
  • «прощение» с динамическим типом заменяется тенденцией к некоторым очень хитрым ошибкам при несовпадении типов атрибутов.
Научная фантастика
источник
1
Не забудьте привести пример, почему объекты должны быть «изменяемыми» (я предполагаю, что вы имеете в виду добавление и удаление атрибутов, а не их изменение, поскольку это обычно не связано с типизацией).
@delnan: не совсем, в программировании на основе прототипов вы можете копать кишки объекта по своему усмотрению, удалять, добавлять, заменять, покрывать, как методы, так и атрибуты в реальном экземпляре. В этом весь смысл и очень удобная, гибкая замена для модификации объектов посредством жестких правил классического наследования. Если язык использует класс в качестве типа, вы не можете изменить его структуру на лету, если тип не является мягким.
SF.
1
Я так не думаю. По той же логике можно утверждать, что программирование на основе классов нуждается в тех же свободах, что и динамические языки на основе классов. Нет, статические прототипы со структурными системами типов будут аннотировать объекты списком его членов и рекурсивно их типами, а также статически проверять, что эти члены существуют (и имеют правильный тип), требуя, чтобы все члены были предоставлены при создании объекта или представлены в прототип и просто не включая способ удаления членов. Результат все еще выглядит довольно прототипно для меня и гарантирует, что каждый участник присутствует всегда.
@delnan: Вы только что описали классическое наследование через композицию. Да, это выглядит довольно прототипно и является (очень нервным) способом выполнения программирования на основе прототипов в классическом языке модели наследования. Это просто лишает pb.p 90% удовольствия, убивая его самые большие преимущества (и одновременно устраняя самые большие опасности). Да, по старой аналогии со стрельбой по ногам, полнофункциональный pb.p поможет вам отстрелить обе ноги чайной ложкой. Если вам не нравится такая власть, вам лучше придерживаться классического наследования.
SF.
1
Вы путаете «динамический» с «прототипами». Эти свободы, которые плохо сочетаются со статическими системами типов, не являются особенностями прототипов, они являются особенностями динамизма. Конечно, добавление статической типизации предотвращает их, но они не являются частью прототипов (это, в основном, IMGO - отсутствие классов в пользу клонирования объектов, чтобы выступать в роли родителей). Этот динамизм ортогональн к прототипам. Все популярные языки прототипов включают их, но они не зависят от прототипов, как указано ранее. Рассмотрим этот фрагмент на вымышленном языке: pastebin.com/9pLuAu9F . Как это не прототипы?
3

Трудность довольно проста: если рассматривать объекты в качестве словарей методов или вещей, отвечающих на сообщения, обратите внимание на следующее в общих статически типизированных ОО-языках:

  • Все словарные ключи / сообщения обычно объявляются заранее с использованием статически объявленных идентификаторов.

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

  • Отношения включения одного набора сообщений, являющегося подмножеством другого, объявляются статически и явно; необъявленные, но логические подмножества недействительны.

  • Проверка типов пытается гарантировать, что все сообщения отправляются только объектам, которые на них отвечают.

Каждый из них в некоторой степени конфликтует с системой на основе прототипов:

  • Имена сообщений могут быть объявлены заранее, в форме «атомов», интернированных строк или еще чего-нибудь, но не более того; пластичность объектов означает, что присвоение типов методам неудобно.

  • Возможно, существенной особенностью системы на основе прототипов является то, что наборы сообщений определяются тем, на что реагирует объект, а не наоборот. Было бы разумно назначать псевдонимы определенным комбинациям во время компиляции, но наборы сообщений, определенные во время выполнения, должны быть возможны.

  • Реальное влияние вышеупомянутых двух результатов отражается в отношениях включения, где явные декларации совершенно неосуществимы. Наследование в статическом, номинальном смысле подтипирования противоположно прототипной системе.

Что подводит нас к последнему пункту, который мы на самом деле не хотим менять. Мы все еще хотим, чтобы сообщения отправлялись только тем объектам, которые на них отвечают. Тем не мение:

  • Мы не можем знать статически, какие сообщения могут быть сгруппированы вместе.
  • Мы не можем знать, какие группировки являются подмножествами других.
  • Мы не можем знать, какие группировки возможны.
  • Мы даже не можем указать, какие аргументы отправляются вместе с одним сообщением.
  • По сути, мы обнаружили, что вообще ничего не можем указать в общем случае.

Так как это можно обойти? Либо каким-то образом ограничьте полную общность (что неприятно и может быстро убить любые преимущества использования системы на основе прототипа), либо сделайте систему типов намного более гибкой и выражайте ограничения, а не точные типы .

Система типов, основанная на ограничениях, быстро приводит к понятию структурной подтипировки , которое в очень широком смысле можно рассматривать как статический эквивалент «типизации утки». Самым большим препятствием здесь является то, что такие системы намного сложнее для проверки типов и менее известны (что означает небольшую предварительную работу для изучения).

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

CA Макканн
источник
1

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

Концепции когда-то были запланированной функцией для C ++ 0x. Общий код в шаблонах C ++ уже де-факто «статически утка». Идея Concepts заключается в том, чтобы иметь возможность сказать что-то о необходимых членах и характеристиках типов, не требуя и не подразумевая модель наследования классов, лежащую в основе этих отношений (потому что она должна была работать с существующим кодом шаблона, который уже был «статически утка» ).

В языке, основанном на шаблонах и концепциях, именно концепции были бы основаны на прототипах, а шаблоны избавили бы вас от заботы о любой модели классов, которая может или не может использоваться для реализации типов значений.

Помимо уловок использования поэтапной компиляции, чтобы позволить языку быть его собственным мета-языком, эти прототипные производные концепций обязательно будут неизменными после создания. Однако, возражение, что это не основано на прототипе, является красной сельдью. Это был бы просто функциональный язык. Динамический прототип базы языка , который также является функциональным имеет , по крайней мере , была предпринята попытка .

Деннис Феррон
источник