Здравствуйте, jazzer, Вы писали:
FR>>Это в тебе голос привычного ОО говорит, при структурной типизации никаких классов по сути нет, есть объекты и есть методы объектов и семантика должна быть завязана именно на это, а не на мифические классы
J>И как структурная типизация позволит защититься от сравнения яблок с апельсинами?
Вот вопрос как раз и показывает отличия в мышлении, меня самого правда тоже клинит
Что такое яблоки и апельсины? Классы? А нет их в нашем ОО есть только объекты и если они позволяют друг друга
сравнивать то и будут успешно сравнены, не позволяют не будут.
J>Все хорошо к месту, и структурная типизация не отменяет номинативной, это ортогональные измерения, и они отлично вместе сосуществуют, не отменяя друг друга.
Не совсем они ортогональны очень прилично пересекаются. а сосуществовать конечно вполне могут.
J>(Хотя в С++, в котором можно в "структурную" типизцию на шаблонах впихнуть типы и вообще все, что угодно (traits, например), можно эмулировать и нормальную типизацию через те же traits. Но в С++ шаблоны намного мощнее простой стуктурной типизации. Структурная типизация — это просто кастрированная версия предикатной типизации (когда можно задать любой вопрос относительно типа), в которой предикаты ограничены примитивными "есть член с таким именем и сигнатурой")
Про предикатную не слышал и достаточно трудно для меня представимо.
FR>>Шаблоны C++ (да и D) это все-таки не совсем структурная типизация, а нечто на нее очень похожее.
J>"нечто на нее очень похожее" — в терминах duck typing это высказывание эквивалентно "это оно и есть" J>Если спор не чисто терминологический, конечно.
Нет есть вполне реальные отличия, главное шаблоны это именно шаблоны в которые что-то можно подставить и только после этого
понять подходит это или нет. В структурной наоборот из использования в функции мы выводим тип который наша функция может
принять.
FR>>В том же OCaml статическая типизация нигде ни нарушается, и структурно типизированные функции шаблонами не являются. J>И как они работают на бинарном уровне тогда? Вот у тебя есть функция, и ты ее зовешь с тремя абсолютно по-разному устроенными, но структурно-совместимыми объектами. В С++ для каждого вызова сгенерится код, наиболее подходящий для каждого типа (т.е. если искомая функция в одном объекте виртуальная, а в другом — нет, то будут сгенерены виртуальный и невиртуальный вызовы соответственно). Что генерит компилятор окамла?
Здравствуйте, FR, Вы писали:
FR>Здравствуйте, jazzer, Вы писали:
FR>>>Это в тебе голос привычного ОО говорит, при структурной типизации никаких классов по сути нет, есть объекты и есть методы объектов и семантика должна быть завязана именно на это, а не на мифические классы
J>>И как структурная типизация позволит защититься от сравнения яблок с апельсинами?
FR>Вот вопрос как раз и показывает отличия в мышлении, меня самого правда тоже клинит FR>Что такое яблоки и апельсины? Классы? А нет их в нашем ОО есть только объекты и если они позволяют друг друга FR>сравнивать то и будут успешно сравнены, не позволяют не будут.
Это сущности предметной области, устроенные одинаково, но с разным смыслом. И ты хочешь, чтоб компилятор не дал тебе написать код, которые позволит сравнить несравнимое.
В стандартно-типизированном языке это понятно как делается — разные типы. Они могут быть устроены внутри как угодно, в том числе и одинаково, главное, что они сами по себе разные, и на этом можно построить проверки.
Что мне делать в структурно-типизированном языке, чтоб получить такой же силы проверки? Делать разную структуру? Ну это же изврат. Та же пара чисел — это может быть просто пара, а может быть размер, а может быть точка на плоскости, а может быть комплексное число...
J>>Все хорошо к месту, и структурная типизация не отменяет номинативной, это ортогональные измерения, и они отлично вместе сосуществуют, не отменяя друг друга.
FR>Не совсем они ортогональны очень прилично пересекаются. а сосуществовать конечно вполне могут.
В чем же они пересекаются, если обычно-типизированные построены на понятии type identity (см выше)?
J>>(Хотя в С++, в котором можно в "структурную" типизцию на шаблонах впихнуть типы и вообще все, что угодно (traits, например), можно эмулировать и нормальную типизацию через те же traits. Но в С++ шаблоны намного мощнее простой стуктурной типизации. Структурная типизация — это просто кастрированная версия предикатной типизации (когда можно задать любой вопрос относительно типа), в которой предикаты ограничены примитивными "есть член с таким именем и сигнатурой")
FR>Про предикатную не слышал и достаточно трудно для меня представимо.
Предикатная — это когда ты просто говоришь: "функция принимает нечто, удовлетворяющее следующему набору условий", где условия могут быть какими угодно. Если ты ограничиваешь условия так: "тип должен быть только А или его наследником" — ты получаешь обычную ООП-типизацию. Если "тип должен содержать такие-то методы с такими-то сигнатурами" — получаешь структурную. С шаблоанми С++ ты можешь делать что угодно — хоть структурную, хоть ООП, хоть "помесь бобика со свиньёй" (с) типа "тип должен быть А или Б, или их наследники, но не прямые, а через одного, и содержать при этом такие-то методы, и еще чтоб у них был вложенный тип iterator с такими-то методами, и чтоб у вот этого метода возвращаемый тип удовлетворял предикату, который юзер передал первым параметром".
FR>>>Шаблоны C++ (да и D) это все-таки не совсем структурная типизация, а нечто на нее очень похожее.
J>>"нечто на нее очень похожее" — в терминах duck typing это высказывание эквивалентно "это оно и есть" J>>Если спор не чисто терминологический, конечно.
FR>Нет есть вполне реальные отличия, главное шаблоны это именно шаблоны в которые что-то можно подставить и только после этого FR>понять подходит это или нет. В структурной наоборот из использования в функции мы выводим тип который наша функция может FR>принять.
Разницы не уловил
FR>>>В том же OCaml статическая типизация нигде ни нарушается, и структурно типизированные функции шаблонами не являются. J>>И как они работают на бинарном уровне тогда? Вот у тебя есть функция, и ты ее зовешь с тремя абсолютно по-разному устроенными, но структурно-совместимыми объектами. В С++ для каждого вызова сгенерится код, наиболее подходящий для каждого типа (т.е. если искомая функция в одном объекте виртуальная, а в другом — нет, то будут сгенерены виртуальный и невиртуальный вызовы соответственно). Что генерит компилятор окамла?
FR>На бинарном как обычные, (вернее не совсем обычные http://lj.rossia.org/community/programming/920.html) вызовы.
клёво! (интересно, клёво — это калька с clever?)
Правда, все равно получаются ран-тайм проверки на нули в соответствующих местах таблицы, если я правильно понял, плюс дополнительный уровень косвенности. Никакие невиртуальные вызовы и заточка под конкретный тип невозможна. Не говоря уже о том, что нечто может быть не функцией, а объектом-функтором (хотя, может, в окамле этого нет в принципе).
Здравствуйте, jazzer, Вы писали:
FR>>Что такое яблоки и апельсины? Классы? А нет их в нашем ОО есть только объекты и если они позволяют друг друга FR>>сравнивать то и будут успешно сравнены, не позволяют не будут.
J>Это сущности предметной области, устроенные одинаково, но с разным смыслом. И ты хочешь, чтоб компилятор не дал тебе написать код, которые позволит сравнить несравнимое.
Без проблем, ничто ни мешает если они разные хоть и устроенные одинаково называть методы этих объектов по разному.
В мейнстримном ООП только копи-паст будет чуть проще в этом случае.
J>В стандартно-типизированном языке это понятно как делается — разные типы. Они могут быть устроены внутри как угодно, в том числе и одинаково, главное, что они сами по себе разные, и на этом можно построить проверки.
Так и в структурном также, просто нужно помнить что разными должны быть имена методов, а не имена классов.
J>Что мне делать в структурно-типизированном языке, чтоб получить такой же силы проверки? Делать разную структуру? Ну это же изврат. Та же пара чисел — это может быть просто пара, а может быть размер, а может быть точка на плоскости, а может быть комплексное число...
Просто давать разные имена методам, имя часть сигнатуры.
FR>>Не совсем они ортогональны очень прилично пересекаются. а сосуществовать конечно вполне могут. J>В чем же они пересекаются, если обычно-типизированные построены на понятии type identity (см выше)?
В решаемых задачах.
FR>>Про предикатную не слышал и достаточно трудно для меня представимо.
J>Предикатная — это когда ты просто говоришь: "функция принимает нечто, удовлетворяющее следующему набору условий", где условия могут быть какими угодно. Если ты ограничиваешь условия так: "тип должен быть только А или его наследником" — ты получаешь обычную ООП-типизацию. Если "тип должен содержать такие-то методы с такими-то сигнатурами" — получаешь структурную. С шаблоанми С++ ты можешь делать что угодно — хоть структурную, хоть ООП, хоть "помесь бобика со свиньёй" (с) типа "тип должен быть А или Б, или их наследники, но не прямые, а через одного, и содержать при этом такие-то методы, и еще чтоб у них был вложенный тип iterator с такими-то методами, и чтоб у вот этого метода возвращаемый тип удовлетворял предикату, который юзер передал первым параметром".
Понятно, но это что-то слишком обще размытое.
FR>>Нет есть вполне реальные отличия, главное шаблоны это именно шаблоны в которые что-то можно подставить и только после этого FR>>понять подходит это или нет. В структурной наоборот из использования в функции мы выводим тип который наша функция может FR>>принять. J>Разницы не уловил
Разница как-раз в возможностях статического контроля. Для структурной он не теряется.
( Рыбаки говорят от слова клевать )
J>Правда, все равно получаются ран-тайм проверки на нули в соответствующих местах таблицы, если я правильно понял, плюс дополнительный уровень косвенности. Никакие невиртуальные вызовы и заточка под конкретный тип невозможна. Не говоря уже о том, что нечто может быть не функцией, а объектом-функтором (хотя, может, в окамле этого нет в принципе).
Да вызов по сути виртуальный, заточка под конкретный тип как в шаблонах в виде частичной специализации и т. п. невозможна, но компилятор если тип задан жестко может соптимизировать и подставить прямой вызов.
Объект-функтор для полноценного ФП языка конечно бессмыслен, хотя в принципе наверно можно сделать.
Здравствуйте, Jack128, Вы писали:
J>Я правильно понял, что в OCaml каждый _объект_ (не класс) содержит свою VMT ?? Что то мне кажется не шибко эффективно по памяти.
Каждый экземпляр объекта (созданный new) конечно не содержит свою VMT. У всех структурно совпадающих объектов будет общая VMT.
Например для:
class elephant =
object
method say = printf "elephant\n"end(* с точки зрения компилятора этот класс совпадает с elephant *)class mamont =
object
method say = printf "mamont\n"end
class dog =
object
method say = printf "dog\n"method dog_id = ()
end
class wolf =
object
method say = printf "wolf\n"method wolf_id = ()
end
let elephant1_ = new elephant
let elephant2_ = new elephant
let mamont_ = new mamont
let dog_ = new dog
let wolf_ = new wolf
У elephant1_, elephant2_ и mamont_ будет одна и та же VMT.
Здравствуйте, FR, Вы писали:
FR>>>Что такое яблоки и апельсины? Классы? А нет их в нашем ОО есть только объекты и если они позволяют друг друга FR>>>сравнивать то и будут успешно сравнены, не позволяют не будут.
J>>Это сущности предметной области, устроенные одинаково, но с разным смыслом. И ты хочешь, чтоб компилятор не дал тебе написать код, которые позволит сравнить несравнимое.
FR>Без проблем, ничто ни мешает если они разные хоть и устроенные одинаково называть методы этих объектов по разному.
Т.е. программер должен прошерстить все совместимыые классы и убедиться, что новый класс, который он пишет, имеет уникальные имена? Звучит несколько непрактично, не?
FR>В мейнстримном ООП только копи-паст будет чуть проще в этом случае.
При чем тут копи-паст? Я про типобезопасность.
J>>В стандартно-типизированном языке это понятно как делается — разные типы. Они могут быть устроены внутри как угодно, в том числе и одинаково, главное, что они сами по себе разные, и на этом можно построить проверки.
FR>Так и в структурном также, просто нужно помнить что разными должны быть имена методов, а не имена классов.
см. выше.
Или ты предлагаешь в каждом классе завести метод типа this_is_apple, this_is_orange и матчить по нему?
J>>Что мне делать в структурно-типизированном языке, чтоб получить такой же силы проверки? Делать разную структуру? Ну это же изврат. Та же пара чисел — это может быть просто пара, а может быть размер, а может быть точка на плоскости, а может быть комплексное число... FR>Просто давать разные имена методам, имя часть сигнатуры.
см. выше.
FR>>>Не совсем они ортогональны очень прилично пересекаются. а сосуществовать конечно вполне могут. J>>В чем же они пересекаются, если обычно-типизированные построены на понятии type identity (см выше)? FR>В решаемых задачах.
Я говорю, что фичи ортогональны (а не взаимоисключающи). Естественно, ортогональные фичи пересекаются в реальных задачах.
FR>>>Про предикатную не слышал и достаточно трудно для меня представимо. J>>Предикатная — это когда ты просто говоришь: "функция принимает нечто, удовлетворяющее следующему набору условий", где условия могут быть какими угодно. FR>Понятно, но это что-то слишком обще размытое.
Тем не менее в шаблонах С++ это прекрасно работает.
Что я делаю не так?
FR>>>Нет есть вполне реальные отличия, главное шаблоны это именно шаблоны в которые что-то можно подставить и только после этого FR>>>понять подходит это или нет. В структурной наоборот из использования в функции мы выводим тип который наша функция может FR>>>принять. J>>Разницы не уловил
FR>Разница как-раз в возможностях статического контроля. Для структурной он не теряется.
А в шаблонах он теряется, что ли?
FR>Да вызов по сути виртуальный, заточка под конкретный тип как в шаблонах в виде частичной специализации и т. п. невозможна, но компилятор если тип задан жестко может соптимизировать и подставить прямой вызов.
Ну тогда неинтересно.
FR>Объект-функтор для полноценного ФП языка конечно бессмыслен, хотя в принципе наверно можно сделать.
Ну вот Питон — это полноценный ФП-язык? А в нем функторы есть.
ЗЫ В сигнатуре метода, кроме имени, проверяются также и типы аргументов — т.е. обычные типы все-таки нужны даже структурной типизации
Здравствуйте, jazzer, Вы писали:
FR>>Без проблем, ничто ни мешает если они разные хоть и устроенные одинаково называть методы этих объектов по разному. J>Т.е. программер должен прошерстить все совместимыые классы и убедиться, что новый класс, который он пишет, имеет уникальные имена? Звучит несколько непрактично, не?
С точки зрения "классового" программиста конечно.
Но если у нас с самого начала дизайн был завязан на объекты и методы то нет.
FR>>В мейнстримном ООП только копи-паст будет чуть проще в этом случае. J>При чем тут копи-паст? Я про типобезопасность.
Ну в обоих случаях для сущности предметной области, устроенные одинаково, но с разным смыслом придется дублировать
код.
А типобезопасность в структурном ОО никак ни меньше чем в номинативном, просто не стоит забывать что
типы там образуются по разному.
FR>>Так и в структурном также, просто нужно помнить что разными должны быть имена методов, а не имена классов. J>см. выше. J>Или ты предлагаешь в каждом классе завести метод типа this_is_apple, this_is_orange и матчить по нему?
Нет я предлагаю плясать не от мифических в случае структурной типизации классов а от объектов и методов.
FR>>Понятно, но это что-то слишком обще размытое. J>Тем не менее в шаблонах С++ это прекрасно работает.
Что не отменяет размытость
В питоне с декораторами этот же подход тоже вполне себе прекрасно работает, при еще большей размытости.
FR>>Разница как-раз в возможностях статического контроля. Для структурной он не теряется. J>А в шаблонах он теряется, что ли?
Частично да, просто в подстановочной модели это по моему неизбежно. Тот же SFINAE как пример.
FR>>Да вызов по сути виртуальный, заточка под конкретный тип как в шаблонах в виде частичной специализации и т. п. невозможна, но компилятор если тип задан жестко может соптимизировать и подставить прямой вызов. J>Ну тогда неинтересно.
Неинтерсно если как в С++ нужны побочные эффекты шаблонов.
FR>>Объект-функтор для полноценного ФП языка конечно бессмыслен, хотя в принципе наверно можно сделать. J>Ну вот Питон — это полноценный ФП-язык? А в нем функторы есть.
При всей мой любви к питону на полноценный ФП язык он не тянет. Нет неизменяемых данных, нет раскрутки хвостовой рекурсии.
А функторы там необходимы из-за неполноценности замыканий, при захвате переменные превращаются в немутабельные.
J>ЗЫ В сигнатуре метода, кроме имени, проверяются также и типы аргументов — т.е. обычные типы все-таки нужны даже структурной типизации
Конечно
Вообще по моему структурный ОО хорош именно как дополнение к другим мощным свойствам языка, например как в OCaml.
Здравствуйте, FR, Вы писали:
FR>Здравствуйте, jazzer, Вы писали:
FR>>>Без проблем, ничто ни мешает если они разные хоть и устроенные одинаково называть методы этих объектов по разному. J>>Т.е. программер должен прошерстить все совместимыые классы и убедиться, что новый класс, который он пишет, имеет уникальные имена? Звучит несколько непрактично, не?
FR>С точки зрения "классового" программиста конечно. FR>Но если у нас с самого начала дизайн был завязан на объекты и методы то нет.
Можешь привести пример? А то общие слова только.
Вот реальный пример неудобства, который, имхо, структурной типизацией не решается, ибо интерфейс у всех числовых типов в принципе одинаковый, независимо от смысла: http://www.rsdn.ru/forum/cpp/4266827.1.aspx
FR>>>В мейнстримном ООП только копи-паст будет чуть проще в этом случае. J>>При чем тут копи-паст? Я про типобезопасность.
FR>Ну в обоих случаях для сущности предметной области, устроенные одинаково, но с разным смыслом придется дублировать FR>код.
Про дублирование кода я не говорил, с ним все очевидно. Я про типобезопасность.
FR>А типобезопасность в структурном ОО никак ни меньше чем в номинативном, просто не стоит забывать что FR>типы там образуются по разному.
Ну да, и в результате куча типов неожиданно оказываются подходящими. Где безопасность?
FR>>>Так и в структурном также, просто нужно помнить что разными должны быть имена методов, а не имена классов. J>>см. выше. J>>Или ты предлагаешь в каждом классе завести метод типа this_is_apple, this_is_orange и матчить по нему?
FR>Нет я предлагаю плясать не от мифических в случае структурной типизации классов а от объектов и методов.
У абсолютно разных и несовместимых по смыслу объектов могут быть одинаковые по сигнатурам и разные по смыслу методы, с этим-то ты согласен?
Причем даже если их нет сейчас, они могут появиться завтра, потому что сосед-программер добавил новый метод.
Как мне теперь сделать так, чтоб компилятор несовместимые объекты не пропустил и дал ошибку компиляции?
FR>>>Понятно, но это что-то слишком обще размытое. J>>Тем не менее в шаблонах С++ это прекрасно работает. FR>Что не отменяет размытость FR>В питоне с декораторами этот же подход тоже вполне себе прекрасно работает, при еще большей размытости.
Отсюда следует вывод, что размытость не имеет физического смысла, раз все прекрасно работает
FR>>>Разница как-раз в возможностях статического контроля. Для структурной он не теряется. J>>А в шаблонах он теряется, что ли? FR>Частично да, просто в подстановочной модели это по моему неизбежно. Тот же SFINAE как пример.
И где тут что теряется? Можно пример?
FR>>>Да вызов по сути виртуальный, заточка под конкретный тип как в шаблонах в виде частичной специализации и т. п. невозможна, но компилятор если тип задан жестко может соптимизировать и подставить прямой вызов. J>>Ну тогда неинтересно. FR>Неинтерсно если как в С++ нужны побочные эффекты шаблонов.
Что ты называешь побочными эффектами шаблонов? Частичную специализацию? Возможность заточки под тип? SFINAE? это все прямые эффекты, это то, зачем шаблоны вообще делались. У шаблонов С++ единственный побочный эфект — шаблонное метапрограммирование, но здесь оно не при делах.
FR>>>Объект-функтор для полноценного ФП языка конечно бессмыслен, хотя в принципе наверно можно сделать. J>>Ну вот Питон — это полноценный ФП-язык? А в нем функторы есть. FR>При всей мой любви к питону на полноценный ФП язык он не тянет. Нет неизменяемых данных, нет раскрутки хвостовой рекурсии. FR>А функторы там необходимы из-за неполноценности замыканий, при захвате переменные превращаются в немутабельные.
То у тебя плохо, что нет неизменяемых данных, то что переменные становятся неизменяемые Ты уж определись
J>>ЗЫ В сигнатуре метода, кроме имени, проверяются также и типы аргументов — т.е. обычные типы все-таки нужны даже структурной типизации
FR>Конечно FR>Вообще по моему структурный ОО хорош именно как дополнение к другим мощным свойствам языка, например как в OCaml.
Тут полностью согласен. На одной структурной типизации нормальной безопасной системы программирования, имхо, не напишешь. Но в качестве приправы — очень даже вкусненько.
Обычная типизация призвана отражать предметную область приложения, а структурная построена на артефактах объектов.
Т.е. программы в любом случае пишутся в терминах типов ("перевести деньги с этого счета на тот"), а не в терминах того, что можно сделать с произвольных объектом ("взять две любые фигни, у которых есть методы add и subtract, и которые принимают третью фигню, отнять третью у первого, добавить третью второму").
Стандартная типизация консервативна и закрыта, т.е. то, что явно не объявлено совместимым, совместимым не является, даже если одно — полный копипейст другого. Уже поэтому она гораздо более безопасна и надежна, но ценой гибкости, естественно. А структурная — наоборот: все может быть совместимым, гибкости хоть отбавляй, зато безопасность так себе. Предикатная охватывает оба варианта, так что в зависимости от стиля ее использования можно получить требуемый баланс между безопасностью и гибкостью.
Здравствуйте, jazzer, Вы писали:
FR>>Но если у нас с самого начала дизайн был завязан на объекты и методы то нет. J>Можешь привести пример? А то общие слова только.
В структурном ОО вряд-ли, пока сам во многом разбираюсь только.
J>Вот реальный пример неудобства, который, имхо, структурной типизацией не решается, ибо интерфейс у всех числовых типов в принципе одинаковый, независимо от смысла: http://www.rsdn.ru/forum/cpp/4266827.1.aspx
Структурной типизацией как раз и решаются, ведь те же алгебраические типы данных структурно типизированы, хоть и жестко ограниченны.
Но в том же OCaml есть полиморфные варианты в которых как раз и сняты ограничения. На них проблема из твоей ссылки решается так вместо
int используем вариантные `ImageIndex nIndex of int, `PixelIndex nPixel of int, `Milliseconds nMilliseconds of int и теперь добраться до их
значений можно только через паттерн матчинг и перепутать никак ни получится.
FR>>А типобезопасность в структурном ОО никак ни меньше чем в номинативном, просто не стоит забывать что FR>>типы там образуются по разному. J>Ну да, и в результате куча типов неожиданно оказываются подходящими. Где безопасность?
А это ортогонально типобезопасности вообще-то.
FR>>Нет я предлагаю плясать не от мифических в случае структурной типизации классов а от объектов и методов. J>У абсолютно разных и несовместимых по смыслу объектов могут быть одинаковые по сигнатурам и разные по смыслу методы, с этим-то ты согласен? J>Причем даже если их нет сейчас, они могут появиться завтра, потому что сосед-программер добавил новый метод. J>Как мне теперь сделать так, чтоб компилятор несовместимые объекты не пропустил и дал ошибку компиляции?
Никак. Если у объектов все сигнатуры методов совпадают то тип этих объектов считается одинаковым.
Ограничить принимаемые объекты при этом вполне возможно, например функция let f (o : my_object) = ...
будет принимать только объекты полностью структурно совпадающие с my_object. Это позволяет эмулировать
номинальный ОО добавляя фейковые методы типа method my_object_id = ()
FR>>В питоне с декораторами этот же подход тоже вполне себе прекрасно работает, при еще большей размытости. J>Отсюда следует вывод, что размытость не имеет физического смысла, раз все прекрасно работает
FR>>>>Разница как-раз в возможностях статического контроля. Для структурной он не теряется. J>>>А в шаблонах он теряется, что ли? FR>>Частично да, просто в подстановочной модели это по моему неизбежно. Тот же SFINAE как пример. J>И где тут что теряется? Можно пример?
В общем тут теряюсь я
Ладно попытаюсь по другому сформулировать: сам шаблон (при не частичной специализации) работает с неизвестным типом
(понятно что концепты или D'шный Template Constraints это чуть улучшают), отсюда вытекает что мы не можем до подстановки
применять жесткую типизацию. В структурной же тип выводится, он известен и типизация всегда жесткая.
FR>>Неинтерсно если как в С++ нужны побочные эффекты шаблонов. J>Что ты называешь побочными эффектами шаблонов? Частичную специализацию? Возможность заточки под тип? SFINAE? это все прямые эффекты, это то, зачем шаблоны вообще делались. У шаблонов С++ единственный побочный эфект — шаблонное метапрограммирование, но здесь оно не при делах.
Основной побочный эффект исполнение во время компиляции. Из него и мета вытекает и без него и SFINAE не очень то и нужен.
J>То у тебя плохо, что нет неизменяемых данных, то что переменные становятся неизменяемые Ты уж определись
В полноценном ФП языке или должны быть по умолчанию константные значения или хотя бы возможность их явно задать, хотя бы как const
в C++ (лучше как invariant из D) в питоне этого нет. Неизменяемость же переменных в замыкания питона это просто побочный эффект
от реализации, который только мешает в не ленивых языках использовать замыкания.
FR>>Конечно FR>>Вообще по моему структурный ОО хорош именно как дополнение к другим мощным свойствам языка, например как в OCaml. J>Тут полностью согласен. На одной структурной типизации нормальной безопасной системы программирования, имхо, не напишешь. Но в качестве приправы — очень даже вкусненько.
На одной структурной сделаешь, на одном структурном ОО типа OCaml'овского согласен нет.
Просто в базе вся типизация в функциональных языках структурная http://newstar.rinet.ru/~goga/tapl/tapl023.html#toc98
J>Обычная типизация призвана отражать предметную область приложения, а структурная построена на артефактах объектов. J>Т.е. программы в любом случае пишутся в терминах типов ("перевести деньги с этого счета на тот"), а не в терминах того, что можно сделать с произвольных объектом ("взять две любые фигни, у которых есть методы add и subtract, и которые принимают третью фигню, отнять третью у первого, добавить третью второму"). J>Стандартная типизация консервативна и закрыта, т.е. то, что явно не объявлено совместимым, совместимым не является, даже если одно — полный копипейст другого. Уже поэтому она гораздо более безопасна и надежна, но ценой гибкости, естественно. А структурная — наоборот: все может быть совместимым, гибкости хоть отбавляй, зато безопасность так себе. Предикатная охватывает оба варианта, так что в зависимости от стиля ее использования можно получить требуемый баланс между безопасностью и гибкостью.
Здравствуйте, jazzer, Вы писали:
J>Предикатная охватывает оба варианта, так что в зависимости от стиля ее использования можно получить требуемый баланс между безопасностью и гибкостью.