В чем разница между языком со строгой типизацией и языком со статической типизацией?

Кроме того, одно подразумевает другое?

10 ответов

Решение

В чем разница между языком со строгой типизацией и языком со статической типизацией?

Статически типизированный язык имеет систему типов, которая проверяется во время компиляции реализацией (компилятором или интерпретатором). Проверка типа отклоняет некоторые программы, и программы, которые проходят проверку, обычно имеют некоторые гарантии; например, компилятор гарантирует не использовать целочисленные арифметические инструкции для чисел с плавающей точкой.

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

Статический против динамического

Противоположностью статически типизированного является "динамически типизированный", что означает, что

  1. Значения, используемые во время выполнения, классифицируются по типам.
  2. Существуют ограничения на использование таких значений.
  3. Когда эти ограничения нарушаются, нарушение сообщается как ошибка (динамического) типа.

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

Сильный против слабого

Противоположностью "строго типизированного" является "слабо типизированный", что означает, что вы можете работать с системой типов. C общеизвестно слабо типизирован, потому что любой тип указателя можно преобразовать в любой другой тип указателя просто путем приведения. Паскаль был задуман для строгой типизации, но упущение в дизайне (записи вариантов без тегов) привело к появлению лазейки в системе типов, так что технически она слабо типизирована. Примеры действительно строго типизированных языков включают CLU, Standard ML и Haskell. Стандартный ML фактически подвергся нескольким ревизиям для удаления лазеек в системе типов, которые были обнаружены после широкого распространения языка.

Что на самом деле здесь происходит?

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

  • Любители часто отождествляют их со "статичным" и "динамическим".

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

  • Профессионалы не могут договориться о том, что именно означают термины.

  • В целом вы вряд ли будете информировать или просвещать свою аудиторию.

Печальная правда в том, что когда речь идет о системах типов, "сильный" и "слабый" не имеют общепризнанного технического значения. Если вы хотите обсудить относительную силу систем типов, лучше обсудить, какие именно гарантии есть, а какие нет. Например, хороший вопрос, который нужно задать, заключается в следующем: "гарантированно ли каждое значение данного типа (или класса) было создано путем вызова одного из конструкторов этого типа?" В С ответ нет. В CLU, F# и Haskell это да. Для C++ я не уверен - я хотел бы знать.

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

Одно подразумевает другое?

На педантичном уровне, нет, потому что слово "сильный" на самом деле ничего не значит. Но на практике люди почти всегда делают одно из двух:

  • Они (неправильно) используют "сильный" и "слабый" для обозначения "статический" и "динамический", и в этом случае они (неправильно) используют "строго типизированный" и "статически типизированный" взаимозаменяемо.

  • Они используют "сильный" и "слабый" для сравнения свойств систем статического типа. Очень редко можно услышать, как кто-то говорит о "сильной" или "слабой" динамической системе типов. За исключением FORTH, который на самом деле не имеет какой-либо системы типов, я не могу представить себе язык с динамической типизацией, где система типов может быть разрушена. По определению, эти проверки скрыты в механизме выполнения, и каждая операция проверяется на работоспособность перед выполнением.

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

Это часто неправильно понимают, поэтому позвольте мне прояснить это.

Статическая / Динамическая Печать

Статическая типизация - это место, где тип связан с переменной. Типы проверяются во время компиляции.

Динамическая типизация - это место, где тип связан со значением. Типы проверяются во время выполнения.

Так в Java например:

String s = "abcd";

s "навсегда" будет String, В течение своей жизни он может указывать на разные Stringс (с s это ссылка на Java). Это может иметь null значение, но оно никогда не будет относиться к Integer или List, Это статическая типизация.

В PHP:

$s = "abcd";          // $s is a string
$s = 123;             // $s is now an integer
$s = array(1, 2, 3);  // $s is now an array
$s = new DOMDocument; // $s is an instance of the DOMDocument class

Это динамическая типизация.

Сильный / слабый набор текста

(Изменить оповещение!)

Строгая типизация - это фраза без общепринятого значения. Большинство программистов, которые используют этот термин для обозначения чего-то иного, чем статическая типизация, используют его, чтобы подразумевать, что существует компиляция типов, которая обеспечивается компилятором. Например, CLU имеет строгую систему типов, которая не позволяет клиентскому коду создавать значение абстрактного типа, за исключением использования конструкторов, предоставляемых типом. C имеет довольно сильную систему типов, но она может быть "подорвана" до некоторой степени, потому что программа всегда может привести значение одного типа указателя к значению другого типа указателя. Так, например, в C вы можете взять значение, возвращаемое malloc() и весело бросить его FILE*и компилятор не будет пытаться вас остановить или даже предупредить, что вы делаете что-то хитрое.

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

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

Оригинал этого ответа связывал слабую типизацию с неявным преобразованием (иногда также называемое "неявное продвижение"). Например, в Java:

String s = "abc" + 123; // "abc123";

Этот код является примером неявного продвижения: 123 неявно преобразуется в строку перед объединением с "abc", Можно утверждать, что компилятор Java переписывает этот код как:

String s = "abc" + new Integer(123).toString();

Рассмотрим классическую проблему PHP "начинается с":

if (strpos('abcdef', 'abc') == false) {
  // not found
}

Ошибка здесь в том, что strpos() возвращает индекс совпадения, будучи 0. 0 приведен в булево false и, таким образом, условие действительно верно. Решение заключается в использовании === вместо == чтобы избежать неявного преобразования.

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

Сравните это с Ruby:

val = "abc" + 123

что является ошибкой во время выполнения, потому что в Ruby объект 123 не преобразуется неявным образом только потому, что он передается + метод. В Ruby программист должен сделать преобразование явным:

val = "abc" + 123.to_s

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

Статический / Динамический против Сильного / Слабого

Дело в том, что статическая / динамическая ось не зависит от сильной / слабой оси. Люди путают их, вероятно, отчасти потому, что сильная и слабая типизация не только менее четко определены, но и нет единого мнения о том, что именно подразумевается под сильной и слабой. По этой причине сильная / слабая типизация является скорее оттенком серого, чем черного или белого.

Итак, чтобы ответить на ваш вопрос: еще один способ взглянуть на это, который в основном правильный, это сказать, что статическая типизация - это безопасность типов во время компиляции, а строгая типизация - безопасность типов во время выполнения.

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

Но важно понимать, что язык может быть статическим / сильным, статическим / слабым, динамическим / сильным или динамическим / слабым.

Оба полюса на двух разных осях:

  • строго типизированный против слабо типизированный
  • статически типизированный или динамически типизированный

Строго типизированный означает, что не будет автоматически преобразован из одного типа в другой. Слабо напечатано наоборот: Perl может использовать строку вроде "123" в числовом контексте, путем автоматического преобразования его в int 123, Сильно типизированный язык, такой как python, этого не сделает.

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

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

Ответ уже дан выше. Попытка провести различие между концепцией "сильный против недели" и "статический против динамики".

Что Сильно Типизировано VS Слабый Тип?

Сильно типизированный: не будет автоматически преобразован из одного типа в другой

В Go или Python, как в строго типизированных языках, "2" + 8 вызовет ошибку типа, потому что они не допускают "приведение типа".

Слабо (слабо) типизированный: будет автоматически преобразован в один тип в другой: слабо типизированные языки, такие как JavaScript или Perl, не будут выдавать ошибку, и в этом случае javascript выдаст "28", а perl - 10.

Пример Perl:

my $a = "2" + 8;
print $a,"\n";

Сохраните его в main.pl и запустите perl main.pl и вы получите вывод 10.

Что такое статический VS тип Dyamic?

В программировании программисты определяют статическую типизацию и динамическую типизацию относительно точки, в которой проверяются типы переменных. Статические типизированные языки - это те языки, в которых проверка типов выполняется во время компиляции, тогда как динамические типизированные языки - это языки, в которых проверка типов выполняется во время выполнения.

  • Статический: типы проверены перед выполнением
  • Динамический: типы проверяются на лету, во время выполнения

Что это значит?

В Go он проверяет набранный до выполнения (статическая проверка). Это означает, что он не только переводит и проверяет код, который он выполняет, но и сканирует весь код, и ошибка типа будет выдана еще до того, как код будет запущен. Например,

package main

import "fmt"

func foo(a int) {
    if (a > 0) {
        fmt.Println("I am feeling lucky (maybe).")
    } else {
        fmt.Println("2" + 8)
    }
}

func main() {
    foo(2)
}

Сохраните этот файл в main.go и запустите его, вы получите сообщение об ошибке компиляции.

go run main.go
# command-line-arguments
./main.go:9:25: cannot convert "2" (type untyped string) to type int
./main.go:9:25: invalid operation: "2" + 8 (mismatched types string and int)

Но этот случай не действителен для Python. Например, следующий блок кода будет выполнен для первого вызова foo(2) и завершится ошибкой для второго вызова foo(0). Это потому, что Python динамически типизирован, он только переводит и проверяет код, на котором он выполняется. Блок else никогда не выполняется для foo(2), поэтому "2" + 8 даже никогда не просматривается, и при вызове foo(0) он попытается выполнить этот блок и потерпел неудачу.

def foo(a):
    if a > 0:
        print 'I am feeling lucky.'
    else:
        print "2" + 8
foo(2)
foo(0)

Вы увидите следующий вывод

python main.py
I am feeling lucky.
Traceback (most recent call last):
  File "pyth.py", line 7, in <module>
    foo(0)
  File "pyth.py", line 5, in foo
    print "2" + 8
TypeError: cannot concatenate 'str' and 'int' objects

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

Приведенный выше пример слабой типизации Java из-за

String s = "abc" + 123;

Не является слабо типизированным примером, потому что его действительно делают:

String s = "abc" + new Integer(123).toString()

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

Это не похоже на C. C является одним из лучших примеров слабо типизированных. Среда выполнения не имеет представления, является ли 4 байта целым числом, структурой, указателем или 4 символами.

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

РЕДАКТИРОВАТЬ: После дальнейших размышлений это не обязательно верно, поскольку среда выполнения не обязательно должна иметь все типы, реализованные в системе времени выполнения, чтобы быть строго типизированной системой. Haskell и ML имеют такой полный статический анализ, что могут потенциально пропускать информацию о типах из среды выполнения.

Одно не подразумевает другого. Для статически типизируемого языка это означает, что типы всех переменных известны или выводятся во время компиляции.

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

Строгая типизация, вероятно, означает, что переменные имеют четко определенный тип и что существуют строгие правила объединения переменных разных типов в выражениях. Например, если A - целое число, а B - число с плавающей точкой, то строгое правило относительно A+B может заключаться в том, что A приводится к числу с плавающей точкой, а результат возвращается как число с плавающей точкой. Если A является целым числом, а B является строкой, то строгое правило может заключаться в том, что A+B недопустимо.

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

Обратите внимание, что эти классификации не являются взаимоисключающими, и я бы ожидал, что они часто встречаются вместе. Многие строго типизированные языки также являются статически типизированными.

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

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

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

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

Например: если в моем приложении есть переменная с именем Acceleration , то ясно, что если способ объявления и использования переменной позволяет присвоить ускорению значение « Понедельник » , это проблема, поскольку очевидно, что ускорение не может быть днем ​​недели (и нить).

Другой пример: В Аде можно определить: подтип Month_Day — целочисленный диапазон 1..31;, Тип Month_Day является слабым в том смысле, что он не является отдельным типом от Integer (потому что это подтип), однако он ограничен диапазоном 1..31. Напротив: тип Month_Day является новым целым числом;создаст отдельный тип, сильный в том смысле, что его нельзя смешивать с целыми числами без явного приведения, но он не ограничен и может принимать значение -17, что бессмысленно. Так что технически он прочнее, но менее надежен. Конечно, можно объявить тип Month_Day новым Integer range 1..31;для создания типа, который является отличным и ограниченным.

Другие вопросы по тегам