Здравствуйте, Gaperton, Вы писали:
А>>"Динамически типизированный" и бестиповый — это одно и то же. G>Кто это вам сказал?
В литературе термины "бестиповый язык", "динамически типизированный язык","язык со скрытыми типами" и т.п. используются как синонимы. Просто "бестиповый"- короче и, имхо, лучше отражает суть дела.
G>Вы не правы. Не стоит повторяться, я и так прекрасно вас понял. К мануалу я уже вас отсылал, раз не помогло, приведу цитату.
[]
А вот это как раз и есть те самые типы, существующие в нашем сознании.
G>Что-то я не понял. То есть если я напишу так G>
G>funct( { X, Y } ) -> X * Y.
G>то эрланг бестиповый язык. А если я добавлю вот это G>
G>funct( { X, Y } ) where is_integer( X ), is_integer( Y ) -> X * Y.
G>то он превратится в типизированный (чем, кстати, не замедлит воспользоваться компилятор). И это все не меняя самого языка. Чудеса? Как будем разрешать этот забавный казус?
Элементарно, Ватсон. В типизированный он не превратится. Принципиально ничего нового по сравнению с
funct( { X, Y } ) where X <10, Y>0 -> X * Y.
А вот если компилятор начнет сообщать о том, что функцию нельзя применить к терму из-за несоответствия типов, вот тогда и язык и станет типизированным.
G>Понятна точка зрения. Не согласен с вашим пониманием полиморфизма.
Ну, это не столько мое понимание, сколько авторское. G>Попробуйте перенести эти рассуждения на Smalltalk. Он динамически типизирован, т. е. в ваших терминах "бестиповый". Ваши рассуждения сведутся к абсурду. Если я не прав, напишите здесь про Smalltalk подробно.
Поскольку я не вижу способа приведения к абсурду, то писать про Smalltalk не буду, лучше уж Вы.
G>Намек понял. Формально — да, это один тип.
Так тип и есть формальное понятие.
G>А вы не сильно удивитесь, если я скажу, что определение типа несложно разбить на три определения, так, чтобы и tuple и list являлись отдельными типами? И что это у нас поменяет? Радикально — ничего, но функция станет полиморфной, так?
С какой это стати она станет полиморфной?
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, Sinclair, Вы писали:
S>>Влад, перестань упираться.
VD>И признать очевидную ерунду?
S>> Ок, паттерн матчинг — это отсутствие разницы в использовании объектов разного типа. Где я не прав?
VD>В выделенном жирным. ПМ — это средство управление ветвлением при исполнении на основе анализа значений. Красивый аналог if-а и switch-а.
Тогда вызов виртуальной функции тоже не полиморфизм, а средство управления ветвлением при исполнении на основе анализа значений. Красивый аналог if-a и switch-a.
Здравствуйте, Nick_, Вы писали:
N_>Тогда вызов виртуальной функции тоже не полиморфизм, а средство управления ветвлением при исполнении на основе анализа значений. Красивый аналог if-a и switch-a.
А вот вызов виртуальной функции зависит исключительно от динамического типа объекта. При этом никаких условий ни в методе, ни при его вызове нет.
... << RSDN@Home 1.1.4 beta 3 rev. 207>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, Nick_, Вы писали:
N_>>Тогда вызов виртуальной функции тоже не полиморфизм, а средство управления ветвлением при исполнении на основе анализа значений. Красивый аналог if-a и switch-a.
VD>А вот вызов виртуальной функции зависит исключительно от динамического типа объекта. При этом никаких условий ни в методе, ни при его вызове нет.
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, Nick_, Вы писали:
А>>>"Динамически типизированный" и бестиповый — это одно и то же. N_>>Сомнительное утверждение. Не мог бы ты это обосновать? А>Некоторая сущность (в данном случае тип) присутствует в языке, если в нем имеются средства для её выражения. В противном случае все эти "типы" существуют только в нашем сознании, но никак ни в программах, ни в языке.
Плохо ищете типы в языке. Если бы типы отсутствовали, например, в языке Erlang, а существовали только в моем сознании, то и паттерн-матчинг я мог бы выполнять только в своем сознании. Однако то, что с этим вполне справляется Erlang runtime — это факт, причем этот факт доказан многочисленными независимыми экспериментами. Из которых большинство людей, которые представляют себе устройство компилятора и рантайма, делают вывод о наличии информации о типах (каждое значение в динамически типизированном языке сопровождается информацией о его типе, JFYI, иначе динамическая типизация работать не будет), и о происходящих во время выполнения проверках типов.
Вывод об отсутствии типов (sic!) в динамически типизированных языках экстравагантен, и, гхм, экспериментально не подтверждается, как, впрочем, и априорно — достаточно прочесть любой мануал по любому динамически типизированному языку.
Термин же "бестиповый" в специализированной литературе не распространен, а встречается исключительно в форумах и мэйллистах. Где его часто берут в кавычки, и сразу же поясняют "в том смысле, что...". Единственно где видал "бестиповый" в литературе — это у Дяхтеренко на софткрафте. Его труд, впрочем, во многих аспектах не отличается научной точностью, хоть и в целом там все в порядке. И вообще, посчитайте количество ссылок в гугле по сочетанию "бестиповый язык", прежде чем говорить о распространенности термина (десятки страниц).
И это неспроста. Сложно называть "бестиповыми" языки, к которым существуют системы типов, это нонсенс (soft type system — не меняющая семантики динамически типизированного языка система типов, которая используется для выведения типов и статической их проверки). Для лиспа их целых три (реализованных в ряде тулзов), для эрланга несколько штук (статической проверкой типов занимается т. н. Dyalizer), для JScript автор ее описал подробно в своем блоге — еще бы, компилятор JScript, как и многие современные компляторы динамически типизированных языков, выполняет type inference — как здесь без системы типов? Так что у кого-то типы может и существуют в сознании, но только не у людей, занимающихся компиляторами.
А>>>Полиморфизм нужен чтобы обходить ограничения, накладываемые системой типов. Если никаких А>>>ограничений нет, значит нет и типов и полиморфизм ни к чему. N_>>Разные системы типов, естественно, накладывают разные ограничения на программу. Но полиморфизм — это не сбоку приделка к простой системе типов, а ее обобщение. А>Ну правильно, обобщение. Но вот зачем понадобилось это обобщение? Очевидно, как раз потому, что ограничения, накладываемые мономорфной системой типов слишком серьезные.
Не правильно, не обобщение. И никто его специально не придумывал, это элементарное наблюдение. Полиморфной функцией называется функция, способная принимать аргументы разных типов. А все остальное существует только в вашем сознании. Можете верить, можете нет, но именно это, не зависящее от языка программирования определение используется или подразумевается в специализированной литературе.
Кстати, нам понадобится определение типа. Нестрого, но по существу верно: тип определяется множеством значений + правилами преобразования из/в другие типы. Абстрактные типы данных — это более специальный случай — они определяются только набором допустимых операций над ними (не структурой, но при этом у ADT все равно есть множество значений). Определение "подтипа" нам не понадобится — полиморфизм в общем случае не завязан на подтипы.
Функция в Visual Basic, принимающая значение типа вариант — полиморфна. Функция printf из стандарной либы C — полиморфна. Виртуальная функция (метод) класса — полиморфна, так как объект является неявным параметром (а с точки зрения вызывающего эта функция выглядит как одна функция, и неважно, что ее определение раскидано по разным классам). Шаблонная функция в языке С++ полиморфна. Любой метод в языке Smalltalk полиморфен по всем аргументам. Любой вызов в динамически типизированном языке полиморфен по определению, так как любое значение несет информацию о типе. То, как реализуется полиморфизм — дело десятое, это вопрос синтаксиса и семантики языка.
Полиморфизм подразделяется на исскуственный (если программист явно передает функции информацию о типе, как например в printf; в этом случае говорят, что полиморфизм языком не поддерживается, но это не мешает определить полиморфную функцию, используя специальные соглашения о передаче информации о типе. Полиморфизм не поддерживается языками С, Forth, Pascal) и естественный (если информация о типе передается неявно, т. е. средствами языка — это виртуальные функции, вызовы в динамически типизированных языках, итд).
Также, полиморфизм подразделяется на ad-hoc (разное действие для аргумента разного типа — printf, виртуальные функции) и параметрический (одинаковое действие для аргументов разных типов — например функция append для объекта "очередь" в языках Erlang, Java, Smalltalk).
Можно также выделить полиморфизм времени выполнения и компиляции, но для динамически типизированных языков смысловой разницы нет (вот оно, единственное место, где полиморфизм пересекается с динамической типизацией).
И все. Вот эта "теория" не противоречит здравому смыслу, не приводит к парадоксальным выводам "по определению", и реально описывает то общее, что есть в системах типов и полиморфизме разных языков программирования. Примерно в таком виде она преподается на ВМиК МГУ. Разумеется, прекрасно согласуясь с практикой. И с печатными работами .
Здравствуйте, Gaperton, Вы писали:
Здравствуйте, Gaperton, Вы писали: G>Термин же "бестиповый" в специализированной литературе не распространен, а встречается исключительно в форумах и мэйллистах.
Не буду спорить, термин "бестиповый" менее распространен, но "исключительно в форумах и мэйллистах" — явный перебор. На запрос "typeless language" scirus возвращает более 200 страниц. На "untyped language" — еще больше. Это все равно меньше чем "dynamically typed language", но не настолько чтобы можно было говорить о неупотребительности термина. Наконец, мне лично достаточно одной статьи Карделли, для того чтобы игнорировать любую статистику и считать термин "бестиповый язык" вполне легитимным. Мне он нравится из-за соответствующих параллелей: бестиповое/типизированное лямбда-исчисление, бестиповые/типизированные логики и т.д.
G>Если бы типы отсутствовали, например, в языке Erlang, а существовали только в моем сознании, то и паттерн-матчинг я мог бы выполнять только в своем сознании.
Здесь неявно используется ложная посылка, что паттерн-матчинг связан с типами.
f(1)->...
f(2)->...
f(3)->...
Следует ли признать, что 1,2 и 3 имеют разные типы?
Вообще из Вашей теории следует, что существуют такие типы, как:
— положительные числа;
— четные числа;
— простые числа;
— непустые списки;
— списки, первый элемент которых 1, а второй — alpha;
....
и что любая функция является полиморфной.
Здравствуйте, Трурль, Вы писали:
G>>Если бы типы отсутствовали, например, в языке Erlang, а существовали только в моем сознании, то и паттерн-матчинг я мог бы выполнять только в своем сознании. Т>Здесь неявно используется ложная посылка, что паттерн-матчинг связан с типами. Т>
Т>f(1)->...
Т>f(2)->...
Т>f(3)->...
Т>
Т>Следует ли признать, что 1,2 и 3 имеют разные типы? Т>Вообще из Вашей теории следует, что существуют такие типы, как: Т>- положительные числа; Т>- четные числа; Т>- простые числа; Т>- непустые списки; Т>- списки, первый элемент которых 1, а второй — alpha; Т>.... Т>и что любая функция является полиморфной.
Здравствуйте, Трурль, Вы писали:
G>>Если бы типы отсутствовали, например, в языке Erlang, а существовали только в моем сознании, то и паттерн-матчинг я мог бы выполнять только в своем сознании. Т>Здесь неявно используется ложная посылка, что паттерн-матчинг связан с типами.
А она не ложная. Он связан одновременно и с типами, и со значениями, а не только с типами. Вот например, эта функция принимает аргументом списки и кортежи целых чисел размерности 2. Это разные типы, и я не понимаю, где здесь ложная посылка. У каждого значения в динамически типизированном языке есть тип.
f( { A, B } ) where is_integer( A ), is_integer( B ) ->
f( X ) where is_integer( X ) ->
f( [ H | T ] ) where is_integer( H ) ->
f( [] ) ->
Т>Следует ли признать, что 1,2 и 3 имеют разные типы?
Не следует.
Т>Вообще из Вашей теории следует, что существуют такие типы, как: Т>- положительные числа; Т>- четные числа; Т>- простые числа; Т>- непустые списки; Т>- списки, первый элемент которых 1, а второй — alpha; Т>....
Будут существовать, если я такие типы определю, и буду думать о них как о типах. Вот например на С++ я смогу классы под все перечисленные типы создать, и ограничить операции, и это будет являться полноценным типом с точки зрения языка.
В Erlang же с точки зреня языка, компилятора, и системы типов перечисленные вещи типами не являются. При этом, с точки зрения теории типов они являются подтипами number и list, а паттерн-матчинг является способом конструировать типы и подтипы на лету. Этот взгляд на вещи тоже вполне корректен. Выбирайте любую точку зрения, которая удобна в данный момент.
Т>и что любая функция является полиморфной.
Переменная полиморфна, если может хранить значения разных типов. Функция полиморфна, если ее аргументы — полиморфные переменные. Следовательно, в динамически типизированном языке формально любая функция является полиморфной, это жесткая правда жизни. Но есть три нюанса.
1) В статически типизированном языке это очевидно не так, так как далеко не любая переменная там может хранить значения разных типов. Но вот, допустим, переменная-указатель на базовый класс или интерфейс — может вполне.
2) В динамически типизированном языке с аннотацией типов далеко не любая переменная может хранить значение любого типа. Примеры — JScript .NET, Erlang.
non_poly_fun( X ) where is_integer( X ) ->
3) В динамически типизированном языке без аннотации типов тоже не любая функция будет полиморфной де-факто. Так как функция должна не просто принимать аргументы разных типов, но и выполнять с ними осмысленную работу.
non_poly_fun( Array, Index ) -> element( Array, Index ).
Эта функция не полиморфна, так как типы аргументов установлены жестко — шаг влево шаг вправо — и exception.
Вот например, я такую функцию
process( [ H | T ] ) where is_integer( H ) ->
process( [] ) ->
полиморфной не считаю. А также такую
process( [ H | T ], S ) -> process( T, S + H )
process( [], S ) -> S
Почему? Да потому, что в этой функции из контекста определяются типы элементов списка и S — это number. При передаче внутрь чего-нибудь другого вылетит exception, не смотря на отсутствие проверки типа в паттерне (хотя number это на самом деле два типа — integer и float, так что ее можно считать полиморфной).
Здравствуйте, Трурль, Вы писали:
Т>Здравствуйте, Nick_, Вы писали:
N_>>И чему это противоречит?
Т>Ничему не противоречит. Но, согласитесь, странно вводить термин, обозначающий свойство которым обладают все функции.
Не все. Читайте мой ответ.
Здравствуйте, Gaperton, Вы писали: G>Следовательно, в динамически типизированном языке формально любая функция является полиморфной, это жесткая правда жизни.
Следовательно, в динамически типизированном языке сказать "f-полиморфная функция" то же самое, что сказать "f-функция".
G>Будут существовать, если я такие типы определю, и буду думать о них как о типах.
Вот, вот. Только в сознании.
Здравствуйте, Трурль, Вы писали:
G>>Если бы типы отсутствовали, например, в языке Erlang, а существовали только в моем сознании, то и паттерн-матчинг я мог бы выполнять только в своем сознании. Т>Здесь неявно используется ложная посылка, что паттерн-матчинг связан с типами. Т>
Т>f(1)->...
Т>f(2)->...
Т>f(3)->...
Т>
Т>Следует ли признать, что 1,2 и 3 имеют разные типы? Т>Вообще из Вашей теории следует, что существуют такие типы, как: Т>- положительные числа; Т>- четные числа; Т>- простые числа; Т>- непустые списки; Т>- списки, первый элемент которых 1, а второй — alpha; Т>.... Т>и что любая функция является полиморфной.
Вот именно. И самое смешное, что создать типы с ограничением на значение можно. Но это уже совсем другая история.
... << RSDN@Home 1.1.4 beta 3 rev. 207>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Трурль, Вы писали:
Т>Здравствуйте, Gaperton, Вы писали: G>>Следовательно, в динамически типизированном языке формально любая функция является полиморфной, это жесткая правда жизни. Т>Следовательно, в динамически типизированном языке сказать "f-полиморфная функция" то же самое, что сказать "f-функция".
Читай все письмо, для тебя писал. Там было перечислено три нюанса. Из которых два относятся к этому вопросу.
G>>Будут существовать, если я такие типы определю, и буду думать о них как о типах. Т>Вот, вот. Только в сознании.
Не только в сознании.
На С++ и Haskell я их могу определить явно, о чем написал в следующем же предложении.
Ты читаешь и отвечаешь только на первое предложение абзаца, так?
P.S.: Слушай, тебе правда кажется, что если ты удалишь содержательные части ответа, и будешь отвечать на фразы вырванные из контекста, то этого никто не заметит, и ты таким образом докажешь свою правоту?
Здравствуйте, Gaperton, Вы писали:
G>Не только в сознании. G>На С++ и Haskell я их могу определить явно, о чем написал в следующем же предложении. G>Ты читаешь и отвечаешь только на первое предложение абзаца, так?
Кстати, тип не обязательно должен быть определен явно, чтобы существовать не только "в голове". В том же С можно в любой момент получить и использовать значение типа, скажем, void***, нигде его явно не определяя. В ML/Haskell просто возможности конструирования типов "на лету" более широки.
Здравствуйте, Gaperton, Вы писали:
G>Хотя, если посмотреть книжку Александреску, в которой он жестко надругался над С++ — то очень даже можно и нужно . Там он демонстрирует, что в compile time при помощи шаблонов можно сделать практически все, что угодно — благодаря наличию рекурсии мы имеем вычислительную полноту. Ничего не напоминает? Мне напоминает макросы лисп . Так что ответ не так однозначен.