Имел как-то я неосторожность обмолвится, что Erlang — не совсем динамически типизирован, даже немножко статически.
Но давайте смотреть.
Разница между динамической типизацией и статической предельно проста: в динамически типизированном языке все объекты имеют один единственный тип; в статически типизированном типов может быть много.
Типы Erlang'а
Ну что ж, в Erlang действительно есть один тип, называется терм. Термом может быть число, атом, список, кортеж, идентификатор процесса и т.д. Haskell любезно согласился одолжить свой синтаксис и семантику для визуализации этого:
data Term = Num Float | Atom String | Tuple [Term] | List [Term] | Fun ([Term] -> Term) ...
Функции
В Erlang возможно задавать арность функций и проверять это на этапе компиляции. Рассмотрим две функции:
sqr(X) -> X * X. hypot(X, Y) -> math:sqrt(sqr(X) + sqr(Y)).
А вот какие они имеют типы:
sqr :: Term -> Term hypot :: Term -> Term -> Term
Думаю очевидно, что они разные. Получается в Erlang не один тип, а целое семейство, задаваемое рекуррентной формулой:
Type = Term | Term -> Type
variable 'X' is unbound
Многие видели это сообщение, прерывающее компиляцию. Значит это, что переменная не определена (кэп). Но откуда компилятор знает об этом? Все просто — проверка области видимости — компилятор о каждом имени точно скажет где оно определено (bound) и места где оно используется.
То же самое (проверка области видимости) происходит и с функциями компилируемого модуля, и с явно импортированными функциями — компилятор для каждой функции ищет место ее объявления и места ее использования. Более того в местах использования происходит проверка арности, что, как мы видели ранее, есть не что иное как проверка типа:
% imported function declaration % sqrt :: Term -> Term -import(math, [sqrt/1]). % module function declaration (and definition) % sqr :: Term -> Term sqr(X) -> X * X. % references to declared functions % and arity (type) checking weird_id(X) -> sqr(sqrt(X)).
Scope checking
- проверка области видимости является неотъемлемой частью статической типизации;
- далеко не все динамически типизируемые языки используют проверку области видимости во время компиляции, а только в runtime;
- компилятор Erlang проверяет на этапе компиляции область видимости локальных переменных;
- компилятор Erlang проверяет на этапе компиляции область видимости для явно импортируемых функций и функций компилируемого модуля;
Erlang не удовлетворят определению динамически типизированного языка, поскольку в нем не единственный тип. Он статически типизирован? Нет!
Erlang — язык с проверкой области видимости.
Вывод
Между статической и динамической типизациями есть еще целый мир.
> далеко не все динамически типизируемые языки используют проверку области видимости во время компиляции, а только в runtime;
ВідповістиВидалитиУгу, на кладбище языков можно много чего накопать.
> Erlang не удовлетворят определению динамически типизированного языка, поскольку в нем не единственный тип.
> Ну что ж, в Erlang действительно есть один тип, называется терм.
Взаимоисключающие параграфы — такие взаимоисключающие.
Кэп? Ну это же специально было сделано, разве это не понятно???
ВидалитиА кстати какие это по вашему динамически типизируемые языки используют scope checking?
Видалити> Ну это же специально было сделано, разве это не понятно???
ВидалитиСпециально написаны два противоречащих друг другу утверждения? Охотно верю. Менее противоречащими они от этого не становятся.
> А кстати какие это по вашему динамически типизируемые языки используют scope checking?
По-моему, сейчас уже все, если не считать парочки древних лиспов.
Python, Lua, Ruby, PHP, JavaScript, Clojure, Scheme - на вскидку - проверка области видимости только в runtime.
ВидалитиТак, въехал, я неправильно читаю. Сорри.
ВидалитиНо теперь связь между scope checking и типизацией совсем непонятна. Scope checking - атрибут компилируемого языка, а не статически типизированного.
И что там с противоречиями в статье?
Scope checking - это атрибут любого языка, просто в Python это происходит в рантайме, а в Haskell на этапе компиляции.
ВидалитиА противоречие придумал не я, это продукт общества. Есть аксиомы. Первая, что в динамически типизируемом языке только один тип. Другая, что Erlang - динамически типизируемый. Но в посте я показываю, что в нем больше одного типа. Противоречие.
> Но в посте я показываю, что в нем больше одного типа.
ВидалитиНет.
Вы уже признали, что неправильно читаете. Может стоит проверить нет ли рецидива?
ВидалитиМожет. Читаю "Думаю очевидно, что они разные." Вижу типы Хаскеля. То, что Хаскель статически типизирован мне доказывать не надо. Про эрланг соответствующего доказательства не нашёл.
Видалити> в динамически типизированном языке все объекты имеют один единственный тип
ВідповістиВидалитиЛолчто?! на примере питончика:
a = 2
b = 3
a/b # 0
a = 2.0
a/b # 0.6(6)
Ну да, 2.0 и 2 - разные значения одного и того же типа. Что не нравится?
ВидалитиТо есть ви таки хотите утверждать, что у нас переменные одного и того же типа у нас имеют разное поведение в зависимости от значения переменной? Это конечно, новое слово в CS, и IT вцелом. Давайте тогда разберемся, что из себя представляет "тип" переменной, чем он характеризуется и чем типа друг от друга отличаются.
Видалити> у нас переменные одного и того же типа у нас имеют разное поведение в зависимости от значения переменной?
ВидалитиГм. Сами поняли, что сказали?
Я вам секрет открою. Разные значения ВСЕГДА имеют разное поведение.
> что из себя представляет "тип" переменной, чем он характеризуется и чем типа друг от друга отличаются.
Тип переменной - класс эквивалентности по отношению "одну переменную можно подставить вместо другой, сохранив при этом валидность программы".
Окей, пусть есть некая сферическая функция f, принимающая в качестве аргумента значение типа . Далее, мы имеем 2 переменные:
Видалитиa =
b =
Означает ли это, что мы можем безболезненно заменить вызов f(a) на f(b)?
уродский парсер
Видалитиa = [некое-значение-integer]
b = [другое-значение-integer]
также допустим, что сам результат вычисления нам монопенисуален, важно только его наличие.
print f(a), f(b)
Тип задает интерфейс или протокол. А класс задает поведение. В питоне, к сожалению, чтобы узнать класс нужно воспользоваться функцией type, но на самом деле, она все равно (почти всегда) возвращает __class__.
ВидалитиВ Питоне все объекты имеют одинаковый интерфейс: у каждого можно спросить его класс, спросить какие у него есть атрибуты и т.д.
Короче, с абсолютно любым объектом в Питоне вы найдете общий язык, потому что вы знаете, какие вопросы ему задавать.
А вот что он на них ответит - это уже поведение - как реализация в C#.
То есть когда вы пишете на Питоне класс, вы задаете поведение.
Если уж очень грубо взять, то каждый объект в Питоне - это словарь. То есть нет ничего кроме словаря. Словарь - единственный тип.
Я хочу акцентировать внимание на фразе "в динамически типизированном языке все объекты имеют один единственный тип". Это ложное утверждение. Черт с ним, с питоном, возьмем GW-BASIC. Есть переменная A = 20, есть B = "FOOBAR". Одно можно поделить на 2, второе - нет. О каком единственном типе речь?
ВідповістиВидалитиИнтерпретатор по типу значения определяет, что можно, а что нельзя сделать с данным объектом (данным value). Это означает, что рядом с самим значением лежит ссылка (код, номер, ссылка на таблицу операций) на тип (интерфейс работы со значениями данного типа). Т.е. мы имеем своего рода boxed value.
В динамически типизированном языке реализация скрывает от нас множество типов, лежащих этажом ниже. Поэтому создается иллюзия, что тип якобы один (откуда, кстати, и растут все уродства динамически типизированных языков).
Это уже второстепенное. В первую очередь у объекта вы можете спросить его ссылку на поддерживаемые интерфейсы - это и есть его тип, который известный на этапе компиляции (IAskable :-D). И все. На этапе компиляции у вас нет доступа к списку поддерживаемых объектом интерфейсов.
ВидалитиПрошу учесть важный факт: типизация, проверка типов, а значит и сами типы есть только на этапе компиляции. В рантайме все - значения. Может показаться, что и типы тоже есть, но это всего лишь список поддерживаемых интерфейсов, и этот список уже представляется в виде значения.
Типизация (динамическая или статическая) определяется тем, что известно на этапе компиляции - это наверное мне нужно было подчеркнуть ранее.
в динамически типизированном языке всего один тип. то что вы называете типами на самом деле лучше называть видами. на existentialtype.wordpress.com все это обьясняется на пальцах.
ВидалитиПойду посмотрю...
ВидалитиА в какой именно статье?
Жонглирование словами без видимого результата.
ВідповістиВидалити