Каковы преимущества и ограничения динамических языков типов по сравнению со статическими языками типов?
Смотрите также : что с любовью к динамическим языкам (гораздо более спорная тема ...)
Каковы преимущества и ограничения динамических языков типов по сравнению со статическими языками типов?
Смотрите также : что с любовью к динамическим языкам (гораздо более спорная тема ...)
Ответы:
Способность интерпретатора выводить преобразования типов и типов ускоряет время разработки, но также может спровоцировать сбои во время выполнения, которые вы просто не можете получить на языке со статической типизацией, где вы ловите их во время компиляции. Но какой из них лучше (или даже если это всегда так) горячо обсуждается в сообществе в эти дни (и с давних времен).
Хороший принять по этому вопросу от статической типизации , где это возможно, динамической типизации , когда это необходимо: Конец холодной войны между Языками программирования Эриком Мейером и Питером Дрейтон в Microsoft:
Сторонники статической типизации утверждают, что преимущества статической типизации включают более раннее обнаружение ошибок программирования (например, предотвращение добавления целого числа к логическому значению), лучшую документацию в форме сигнатур типов (например, включение числа и типов аргументов при разрешении имен), больше возможности для оптимизации компилятора (например, замена виртуальных вызовов прямыми вызовами, когда точный тип получателя известен статически), повышенная эффективность времени выполнения (например, не все значения должны нести динамический тип) и лучший опыт разработчика во время разработки (например, знание Тип получателя, IDE может представить раскрывающееся меню всех применимых членов). Фанатики статической типизации пытаются заставить нас поверить, что «программы с хорошей типизацией не могут ошибаться». Хотя это звучит впечатляюще, это довольно пустое утверждение. Проверка статического типа - это абстракция поведения вашей программы во время компиляции, и, следовательно, она обязательно является только частично правильной и неполной. Это означает, что программы по-прежнему могут работать неправильно из-за свойств, которые не отслеживаются средством проверки типов, и что существуют программы, которые, хотя они и не могут работать неправильно, не могут быть проверены по типу. Стремление сделать статическую типизацию менее частичной и более полной приводит к тому, что системы типов становятся чрезмерно сложными и экзотическими, о чем свидетельствуют такие понятия, как «фантомные типы» [11] и «шаткие типы» [10]. Это похоже на попытку пробежать марафон с мячом и цепью, привязанными к вашей ноге, и с триумфом кричать, что вы почти сделали это, даже если вы выпрыгнули после первой мили. Проверка статического типа - это абстракция поведения вашей программы во время компиляции, и, следовательно, она обязательно является только частично правильной и неполной. Это означает, что программы по-прежнему могут работать неправильно из-за свойств, которые не отслеживаются средством проверки типов, и что существуют программы, которые, хотя они и не могут работать неправильно, не могут быть проверены по типу. Стремление сделать статическую типизацию менее частичной и более полной приводит к тому, что системы типов становятся чрезмерно сложными и экзотическими, о чем свидетельствуют такие понятия, как «фантомные типы» [11] и «шаткие типы» [10]. Это похоже на попытку пробежать марафон с мячом и цепью, привязанными к вашей ноге, и с триумфом кричать, что вы почти сделали это, даже если вы выпрыгнули после первой мили. Проверка статического типа - это абстракция поведения вашей программы во время компиляции, и, следовательно, она обязательно является только частично правильной и неполной. Это означает, что программы по-прежнему могут работать неправильно из-за свойств, которые не отслеживаются средством проверки типов, и что существуют программы, которые, хотя они и не могут работать неправильно, не могут быть проверены по типу. Стремление сделать статическую типизацию менее частичной и более полной приводит к тому, что системы типов становятся чрезмерно сложными и экзотическими, о чем свидетельствуют такие понятия, как «фантомные типы» [11] и «шаткие типы» [10]. Это похоже на попытку пробежать марафон с мячом и цепью, привязанными к вашей ноге, и с триумфом кричать, что вы почти сделали это, даже если вы выпрыгнули после первой мили. и, следовательно, это обязательно только частично здоровым и неполным. Это означает, что программы по-прежнему могут работать неправильно из-за свойств, которые не отслеживаются средством проверки типов, и что существуют программы, которые, хотя они и не могут работать неправильно, не могут быть проверены по типу. Стремление сделать статическую типизацию менее частичной и более полной приводит к тому, что системы типов становятся чрезмерно сложными и экзотическими, о чем свидетельствуют такие понятия, как «фантомные типы» [11] и «шаткие типы» [10]. Это похоже на попытку пробежать марафон с мячом и цепью, привязанными к вашей ноге, и с триумфом кричать, что вы почти сделали это, даже если вы выпрыгнули после первой мили. и, следовательно, это обязательно только частично здоровым и неполным. Это означает, что программы по-прежнему могут работать неправильно из-за свойств, которые не отслеживаются средством проверки типов, и что существуют программы, которые, хотя они и не могут работать неправильно, не могут быть проверены по типу. Стремление сделать статическую типизацию менее частичной и более полной приводит к тому, что системы типов становятся чрезмерно сложными и экзотическими, о чем свидетельствуют такие понятия, как «фантомные типы» [11] и «шаткие типы» [10]. Это похоже на попытку пробежать марафон с мячом и цепью, привязанными к вашей ноге, и с триумфом кричать, что вы почти сделали это, даже если вы выпрыгнули после первой мили. и что существуют программы, которые, хотя они и не могут работать неправильно, не могут быть проверены. Стремление сделать статическую типизацию менее частичной и более полной приводит к тому, что системы типов становятся чрезмерно сложными и экзотическими, о чем свидетельствуют такие понятия, как «фантомные типы» [11] и «шаткие типы» [10]. Это похоже на попытку пробежать марафон с мячом и цепью, привязанными к вашей ноге, и с триумфом кричать, что вы почти сделали это, даже если вы выпрыгнули после первой мили. и что существуют программы, которые, хотя они и не могут работать неправильно, не могут быть проверены. Стремление сделать статическую типизацию менее частичной и более полной приводит к тому, что системы типов становятся чрезмерно сложными и экзотическими, о чем свидетельствуют такие понятия, как «фантомные типы» [11] и «шаткие типы» [10]. Это похоже на попытку пробежать марафон с мячом и цепью, привязанными к вашей ноге, и с триумфом кричать, что вы почти сделали это, даже если вы выпрыгнули после первой мили.
Сторонники языков с динамической типизацией утверждают, что статическая типизация является слишком жесткой, и что мягкость динамических языков делает их идеально подходящими для прототипирования систем с изменяющимися или неизвестными требованиями или которые взаимодействуют с другими системами, которые изменяются непредсказуемо (интеграция данных и приложений). Конечно, динамически типизированные языки незаменимы для работы с действительно динамичным поведением программы, таким как перехват методов, динамическая загрузка, мобильный код, отражение во время выполнения и т. Д. В основных статьях по написанию сценариев [16] Джон Оустерхаут утверждает, что статически типизированные системы языки программирования делают код менее пригодным для повторного использования, более многословным, не более безопасным и менее выразительным, чем языки сценариев с динамической типизацией. Этот аргумент буквально повторяется многими сторонниками динамически типизированных языков сценариев. Мы утверждаем, что это заблуждение и относится к той же категории, что и утверждение, что суть декларативного программирования заключается в устранении присваивания. Или, как говорит Джон Хьюз [8], логически невозможно сделать язык более мощным, опуская функции. Отстаивая тот факт, что откладывать все проверки типов до времени выполнения - это хорошая вещь, мы играем в страусиную тактику с тем фактом, что ошибки должны быть обнаружены как можно раньше в процессе разработки. логически невозможно сделать язык более мощным, пропустив функции. Отстаивая тот факт, что откладывать все проверки типов до времени выполнения - это хорошая вещь, мы играем в страусиную тактику с тем фактом, что ошибки должны обнаруживаться как можно раньше в процессе разработки. логически невозможно сделать язык более мощным, пропустив функции. Отстаивая тот факт, что откладывать все проверки типов до времени выполнения - это хорошая вещь, мы играем в страусиную тактику с тем фактом, что ошибки должны обнаруживаться как можно раньше в процессе разработки.
Системы статического типа стремятся устранять определенные ошибки статически, проверяя программу без ее запуска и пытаясь доказать правильность в определенных отношениях. Некоторые системы типов способны отлавливать больше ошибок, чем другие. Например, C # может устранить исключения нулевого указателя при правильном использовании, тогда как Java не имеет такой возможности. У Twelf есть система типов, которая фактически гарантирует, что доказательства прекратятся , «решая» проблему остановки .
Однако ни одна система типов не является идеальной. Чтобы устранить определенный класс ошибок, они также должны отклонить определенные совершенно допустимые программы, которые нарушают правила. Вот почему Twelf на самом деле не решает проблему остановки, он просто избегает ее, выбрасывая большое количество совершенно достоверных доказательств, которые заканчиваются странным образом. Аналогично, система типов Java отклоняет PersistentVector
реализацию Clojure из-за использования гетерогенных массивов. Он работает во время выполнения, но система типов не может это проверить.
По этой причине большинство систем типов предоставляют «экранированные» способы переопределения статической проверки. Для большинства языков они принимают форму приведения, хотя некоторые (например, C # и Haskell) имеют целые режимы, помеченные как «небезопасные».
Субъективно мне нравится статическая типизация. Правильно реализованная (подсказка: не Java), система статических типов может оказать огромную помощь в устранении ошибок до их сбоя в производственной системе. Динамически типизированные языки, как правило, требуют больше модульного тестирования, что в лучшие времена утомительно. Кроме того, статически типизированные языки могут иметь определенные функции, которые либо невозможны, либо небезопасны в динамических системах типов ( на ум приходят неявные преобразования ). Это все вопрос требований и субъективного вкуса. Я не собирался создавать следующий Eclipse в Ruby больше, чем пытался написать скрипт резервного копирования в Assembly или исправить ядро с помощью Java.
О, и люди , которые говорят , что « х набрав в 10 раз более продуктивны , чем у набрав» просто дует дым. Динамическая типизация во многих случаях может «ощущаться» быстрее, но она теряет свои позиции, когда вы действительно пытаетесь заставить ваше модное приложение работать . Аналогичным образом, статическая типизация может показаться идеальной защитной сеткой, но один взгляд на некоторые из более сложных определений универсального типа в Java заставляет большинство разработчиков суетиться на глазах. Даже с системой типов и производительностью, нет серебряной пули.
Последнее замечание: не беспокойтесь о производительности при сравнении статических и динамических типов. Современные JIT, такие как V8 и TraceMonkey, опасно приближаются к производительности статического языка. Кроме того, тот факт, что Java на самом деле компилируется до изначально динамического промежуточного языка, должен быть подсказкой о том, что в большинстве случаев динамическая типизация не является огромным фактором, снижающим производительность, как это делают некоторые люди.
dadd
потому что он заранее знает, что операнды - это double
s.
Ну, и то, и другое очень, очень, очень очень неправильно понято, а также две совершенно разные вещи. которые не являются взаимоисключающими .
Статические типы являются ограничением грамматики языка. Можно сказать, что строго типизированные языки не являются контекстно-свободными. Простая истина в том, что становится неразумно выражать язык разумно в контекстно-свободных грамматиках, которые не обрабатывают все свои данные просто как битовые векторы. Системы статических типов являются частью грамматики языка, если таковые имеются, они просто ограничивают ее больше, чем могла бы сделать контекстно-свободная грамматика, поэтому грамматические проверки в действительности происходят в два прохода над источником. Статические типы соответствуют математическому понятию теории типов, теория типов в математике просто ограничивает законность некоторых выражений. Мол, я не могу сказать 3 + [4,7]
по математике, это из-за теории типов этого.
Таким образом, статические типы не являются способом «предотвращения ошибок» с теоретической точки зрения, они являются ограничением грамматики. Действительно, при условии, что +, 3 и интервалы имеют обычные теоретические определения множеств, если мы удалим систему типов, получим 3 + [4,7]
довольно хорошо определенный результат, который является множеством. «ошибок типа времени выполнения» теоретически не существует, практическое использование системы типов заключается в предотвращении операций, которые для людей не имели бы смысла. Конечно, операции - это всего лишь сдвиг и манипулирование битами.
Подвох в том, что система типов не может решить, будут ли такие операции выполняться или нет, будет ли разрешено выполнение. Например, точно разделите набор всех возможных программ на те, у которых будет «ошибка типа», и те, которые не имеют. Это может сделать только две вещи:
1: доказать, что ошибки типа будут возникать в программе
2: доказать, что они не возникнут в программе
Может показаться, что я противоречу себе. Но что делает средство проверки типов C или Java, так это то, что оно отклоняет программу как «неграмотную», или как она называет это «ошибкой типа», если она не может преуспеть в 2. Она не может доказать, что она не произойдет, это не значит, что они не произойдут, просто это не может доказать это. Вполне возможно, что программа, у которой не будет ошибки типа, отклоняется просто потому, что она не может быть доказана компилятором. Простой примерif(1) a = 3; else a = "string";
, конечно, поскольку это всегда так, ветвь else никогда не будет выполнена в программа, и ошибка типа не должна возникать. Но он не может доказать эти случаи в общем виде, поэтому он отклонен. Это главная слабость многих статически типизированных языков: если вы защищаете себя от себя, вы также обязательно защищены в тех случаях, когда вам это не нужно.
Но, вопреки распространенному мнению, существуют также статически типизированные языки, которые работают по принципу 1. Они просто отвергают все программы, которые могут доказать, что это вызовет ошибку типа, и пропускают все программы, которые они не могут. Поэтому возможно, что они разрешают программам, в которых есть ошибки типов, хорошим примером является Typed Racket, это гибрид между динамической и статической типизацией. И некоторые утверждают, что вы получаете лучшее из обоих миров в этой системе.
Другое преимущество статической типизации состоит в том, что типы известны во время компиляции, и, таким образом, компилятор может использовать это. Если мы в Java делаем "string" + "string"
или 3 + 3
, и оба +
токена в тексте в конце представляют совершенно разные операции и данные, компилятор знает, какой из этих типов выбрать один.
Теперь я собираюсь сделать очень спорное утверждение здесь , но медведь со мной: «динамическая типизация» не существует .
Звуки очень спорные, но это правда, динамически типизированные языки с теоретической точки зрения нетипизированной . Это просто статически типизированные языки только одного типа. Или, проще говоря, это языки, которые действительно грамматически генерируются грамматикой без контекста на практике.
Почему у них нет типов? Поскольку каждая операция определена и разрешена для каждого операнда, что именно является «ошибкой типа времени выполнения»? Это из теоретического примера чисто побочный эффект . Если выполнение, print("string")
которое печатает строку, является операцией, то length(3)
первое имеет побочный эффект записи string
в стандартный вывод, второе просто error: function 'length' expects array as argument.
, вот и все. С теоретической точки зрения нет такого понятия, как динамически типизированный язык. Они нетипизированы
Хорошо, очевидное преимущество «динамически типизированного» языка - выразительная сила, система типов - это не что иное, как ограничение выразительной силы. И вообще, языки с системой типов действительно будут иметь определенный результат для всех тех операций, которые недопустимы, если система типов просто игнорируется, результаты просто не будут иметь смысла для людей. Многие языки теряют свою полноту по Тьюрингу после применения системы типов.
Очевидным недостатком является тот факт, что могут происходить операции, которые приводят к результатам, которые не имеют смысла для людей. Чтобы защититься от этого, динамически типизированные языки обычно переопределяют эти операции, вместо того, чтобы давать этот бессмысленный результат, они переопределяют его на наличие побочного эффекта выписывания ошибки и, возможно, остановки программы в целом. Это вовсе не «ошибка», фактически, спецификация языка обычно подразумевает это, это такое же поведение языка, как и печать строки с теоретической точки зрения. Таким образом, системы типов заставляют программиста рассуждать о потоке кода, чтобы убедиться, что этого не происходит. Или в самом деле, причина , так что она делаетКроме того, в некоторых случаях для отладки может оказаться полезен случай, показывающий, что это вовсе не «ошибка», а четко определенное свойство языка. По сути, единственный остаток «динамической типизации», который есть в большинстве языков, защищает от деления на ноль. Вот что такое динамическая типизация: нет типов, нет больше типов, чем тот, что ноль отличается от всех других чисел. То, что люди называют «типом», - это просто еще одно свойство элемента данных, например длина массива или первый символ строки. И многие динамически типизированные языки также позволяют записывать такие вещи, как "error: the first character of this string should be a 'z'"
.
Другое дело, что языки с динамической типизацией имеют тип, доступный во время выполнения, и обычно могут проверять его, справляться с ним и принимать решения. Конечно, в теории это ничем не отличается от доступа к первому символу массива и просмотра, что это такое. Фактически, вы можете создать свой собственный динамический C, просто используйте только один тип, например long long int, и используйте его первые 8 бит для хранения вашего «type» и соответственно написания функций, которые проверяют его и выполняют операции с плавающей запятой или целочисленным сложением. У вас есть статически типизированный язык с одним типом или динамический язык.
На практике это все показывает, статически типизированные языки обычно используются в контексте написания коммерческого программного обеспечения, тогда как динамически типизированные языки обычно используются в контексте решения некоторых проблем и автоматизации некоторых задач. Написание кода на статически типизированных языках просто занимает много времени и является обременительным, потому что вы не можете делать то, что, как вы знаете, может получиться хорошо, но система типов по-прежнему защищает вас от ошибок, которые вы не делаете. Многие кодеры даже не осознают, что они делают это, потому что это в их системе, но когда вы кодируете на статических языках, вы часто обходите стороной тот факт, что система типов не позволит вам делать то, что не может пойти не так, потому что это не могу доказать, что это не пойдет не так.
Как я уже отмечал, «статически типизированный» в общем случае означает случай 2, виновный до тех пор, пока не доказано невиновность. Но некоторые языки, которые вообще не выводят свою систему типов из теории типов, используют правило 1: невиновен до тех пор, пока его вина не доказана, что может быть идеальным гибридом. Так что, может быть, Typed Racket для вас.
Также, для более абсурдного и экстремального примера, я сейчас реализую язык, где «типы» действительно являются первым символом массива, это данные, данные «типа», «типа», которые сами по себе тип и датум, единственный тип данных, который имеет себя как тип. Типы не являются конечными или статически ограниченными, но новые типы могут генерироваться на основе информации времени выполнения.
Возможно, самое большое «преимущество» динамической типизации - это более мелкая кривая обучения. Нет системы типов для изучения и нетривиального синтаксиса для угловых случаев, таких как ограничения типов. Это делает динамическую типизацию доступной для гораздо большего числа людей и выполнимой для многих людей, для которых сложные системы статического типа недоступны. Следовательно, динамическая типизация приобрела популярность в контексте образования (например, Scheme / Python в MIT) и в предметно-ориентированных языках для непрограммистов (например, Mathematica ). Динамические языки также завоевали популярность в нишах, где у них практически нет конкурентов (например, Javascript).
Наиболее сжатые языки с динамической типизацией (например, Perl, APL, J, K, Mathematica ) являются предметно-ориентированными и могут быть значительно более краткими, чем наиболее сжатые языки общего назначения со статической типизацией (например, OCaml ) в нишах, для которых они были разработаны. ,
Основными недостатками динамической типизации являются:
Ошибки типа во время выполнения.
Может быть очень сложно или даже практически невозможно достичь того же уровня корректности и требует значительно большего тестирования.
Нет проверенной компилятором документации.
Низкая производительность (обычно во время выполнения, но иногда вместо этого во время компиляции, например, схема Сталина) и непредсказуемая производительность из-за зависимости от сложных оптимизаций.
Лично я вырос на динамических языках, но не стал бы трогать их с 40-дюймовым шестом как профессионал, если бы не было других жизнеспособных вариантов.
Из Artima's Typing: сильная и слабая, статическая и динамическая статья:
строгая типизация предотвращает смешивание операций между несовпадающими типами. Чтобы смешивать типы, вы должны использовать явное преобразование
слабая типизация означает, что вы можете смешивать типы без явного преобразования
В газете Паскаля Костанзы Динамическая и статическая типизация - анализ на основе шаблонов» (PDF) он утверждает, что в некоторых случаях статическая типизация более подвержена ошибкам, чем динамическая типизация. Некоторые статически типизированные языки вынуждают вас вручную эмулировать динамическую типизацию, чтобы сделать «правильную вещь». Это обсуждается в Lambda the Ultimate .
Это зависит от контекста. Существует множество преимуществ, которые подходят как для динамически типизированной системы, так и для строго типизированной. Я придерживаюсь мнения, что поток языка динамических типов быстрее. Динамические языки не ограничены атрибутами класса и мышлением компилятора о том, что происходит в коде. У тебя есть какая-то свобода. Кроме того, динамический язык обычно более выразителен и приводит к меньшему количеству кода, что хорошо. Несмотря на это, он более подвержен ошибкам, что также сомнительно и больше зависит от покрытия модульного теста. Это простой прототип с динамическим языком, но обслуживание может стать кошмаром.
Основным преимуществом над статической типизированной системой является поддержка IDE и, конечно, статический анализатор кода. Вы становитесь более уверенным в коде после каждого изменения кода. Обслуживание с помощью таких инструментов - это просто пирог.
В статических и динамических языках есть много разных вещей. Для меня главное отличие в том, что в динамических языках переменные не имеют фиксированных типов; вместо этого типы привязаны к значениям. Из-за этого точный код, который выполняется, не определен до времени выполнения.
В ранних или наивных реализациях это приводит к значительному снижению производительности, но современные JIT-интерфейсы очень близки к лучшему, что вы можете получить с помощью оптимизации статических компиляторов. (в некоторых дополнительных случаях это даже лучше).
Это все о правильном инструменте для работы. Ни один не лучше в 100% случаев. Обе системы были созданы человеком и имеют недостатки. Извините, но мы сосем и делаем идеальные вещи.
Мне нравится динамическая типизация, потому что это мешает мне, но да, ошибки времени выполнения могут появиться, что я не планировал. Где статическая типизация может исправить вышеупомянутые ошибки, но сводит с ума начинающего (на типизированных языках) программиста, пытающегося привести между константным символом и строкой.
Статическая типизация: языки, такие как Java и Scala, имеют статическую типизацию.
Переменные должны быть определены и инициализированы перед использованием в коде.
например int x; х = 10;
System.out.println (х);
Динамический набор текста: Perl - язык динамической типизации.
Переменные не нужно инициализировать перед использованием в коде.
у = 10; используйте эту переменную в более поздней части кода