Evening, Andrei. Andrei Sosnin <[EMAIL PROTECTED]> 14:31 13/1/2003 wrote:
>> Вот именно. Всегда будет иметь _строго_ _определенный_ тип. А как насчет >> _произвольного_ типа, главное, чтобы он совпадал с типом аргумента функции >> f, который тоже _произвольный_? Как сделать hard-coded решение на шаблонах >> для конкретной задачи - мне понятно. Мне также понятно, как можно возвести >> это решение в ранг "универсального"/"библиотечног", обвешав его "своими", >> "удобными" >> реализациями контейнеров, итераторов и т.п. (по этому пути пошел STL). Мне >> непонятно, как заставить это решение работать в самом общем случае. Более >> того - я уверен, что реализовать такое решение невозможно. AS> Насколько общим должно быть решение? То есть где кончается type-safe и AS> начинается (иногда даже абсурдная) type-independent? :-) (См. также AS> комментарии ниже) Смотри, какая штука - если у меня есть "нормальный" map, то с его помощью я могу обработать произвольный список произвольной функцией при условии, что тип эл-то списка совпадает с типом параметра функции. Это - очень общее решение. Список - любой, функция - любая. Теперь берем язык, в котором средства создания контейнерных типов изначально не предусмотрены. И получается, что для данной конкретной реализации сущности "список" можно придумать худо-бедно применимую реализацию "map", но решение не получается общим и какой ценой оно может быть использовано? А type-safe мною упоминается ровно потом, что без него - не получается адекватности того, что предлагаешь ты, и того, что предлагаю я. >> AS> for_each(my_list.begin(), my_list.end(), addvaluesbyone()); >> AS> И при этом класс addvaluesbyone не перегружает оператор () или >> этот >> AS> перегруженный оператор не принимает объекты типа MyClass, а только int >> AS> или float, или user_defined, то будет выдана ошибка компиляции. >> Вот. А если функция принимает, к примеру, аргумент типа >> ConcreteSuperclassOfMyClass - >> будет ли ошибка или нет? Если нет - то правильно ли это? :) Я считаю, что >> это - неправильно, приводит к трудноловимым ошибкам и костылям. AS> Если ты специально не написал такого перегруженного оператора в AS> addvaluesbyone(), то ошибка будет (я это подчеркнул). Если же AS> родительский класс - конкретный (не виртуальный), и в addvaluesbyone() AS> перегружен оператор(), тогда не будет, и вероятно, ты именно этого и AS> хотел (то есть, видимо, добавление одного к элементам типа AS> ConcreteSuperclassOfMyClass допустимо. Да. Проблемы начинаются тогда, когда поведение addvaluesbyone для MyClass и ConcreteSuperclassOfMyClass - различно (такое очень часто пишут горе-програмисты при наследовании, т.е. реализуют в вирт. методе поведение, нарушающее семантику, заложенную в предка). Что приводит к трудноловимым ошибкам и костылям. AS> Как ошибка такого рода решается в других языках? Разве может AS> компилятор решать за тебя, к чему ты хотел добавлять единицу, если ты AS> сам это запрограммировал, инстанцировав addvaluesbyone() для класса AS> ConcreteSuperclassOfMyClass? :-) Без этого (без инстанцирования, т.е. AS> конкретизации типов для шаблона) addvaluesbyone() и для MyClass не AS> будет работать. В других языках может не быть иерархии сущностей и понятия наследования в том виде, в котором оно есть в С++... Соответственно, может не быть и проблемы. >> Ты не замечаешь разницы между тем, что написал я, и тем, что написал >> ты? У >> меня функция f имеет тип "отображение из X в Y", функция g имеет тип >> "отображение из Y в Z", результат compose имеет тип "отображение из X в Z", >> где X,Y,Z - _произвольные_ типы. Главное, чтобы тип результата f и >> аргумента g совпадал. >> Как мне при помощи твоего "решения" скомбинировать функции из float в >> string и из string в int ? AS> В С для этого пишется отдельная функция, в С++ - шаблон с инстанцированием. AS> template <class RetType, class RecType, class RepType = double> AS> class f_func{ [skip пример, который "мимо темы"] AS> Затем, f_func специализируется для каждого "необычного" типа (вроде AS> string), а также - обязательно - для принятия самой себя в качестве AS> аргумента: [skip] AS> Главное условие (в простейшем случае), чтобы существовал конструктор AS> для return_type, принимающий RepType. Конечно, для перевода float -> AS> string, string -> int понадобятся соответствующие специализации AS> класса, но для int -> long нет. Спасибо, мне не нужно реализовывать приведение типов. Мне нужна композиция функций. Есть знакомство с математическим смыслом этого понятия? Мне нужен инструмент, который позволяет взять функцию string -> int (например, с семантикой "кол-во строк в файле с указаным именем"), функцию int -> string (например, с семантикой "число прописью"), сделать "compose spell_number count_lines" и получить сущность типа "функция из string -> string" с семантикой "число строк в файле с указаным именем прописью". Напомню, что все это - иллюстрация того, что такое "first-class funcitons". AS> Если это можно сделать на Haskell без дополнительного кодирования, то AS> только потому, что это просто было включено в "стандартную AS> библиотеку". Конкретная реализация перевода string -> int, float -> AS> string останется на совести разработчиков библиотеки. То есть можно AS> сказать спасибо разработчикам, что не поленились. Но это заслуга не AS> языка, а разработчиков интерпретатора и стандартной библиотеки. Может AS> это одни и те же люди, но это разные их заслуги. Имхо, кое-кто не понял задачи, решаемой примером. И этот кое-то - не я :) >> AS> На С++ это можно записать совершенно также, но можно применить и >> ООП-метод. >> Увы, скорее "так же", а не "также". Так же плохо. [skip] >> AS> инстанциация должна проходить так, например: composite_func<float>(); >> Ничего, что у тебя получаются только функции из X в X? :) AS> См. выше... Если немного потрудиться, можно заставить и из float в AS> string переводить. Только не понимаю, зачем необходимо из класса Мух AS> делать класс Слонов, а потом еще из Слонов делать Комаров? Если нужно [skip] Ты решаешь совсем не ту задачу. AS> уж совсем type-independent (почувствуй разницу с type-safe), то нужно AS> будет немного потрудиться. Но обычно это не так уж необходимо. Если мы AS> пишем библиотеку математических вычислений, то нам не нужно совсем уж AS> произвольный класс складывать и умножать с другим. Определенно, мы AS> будем иметь дело с классами и типами, которые могут представлять числа Елки же ж моталки. Ну что такого сложно в выражении "получить функцию z как результат композиции функций f и g, где g - .... (см. выше)"? Неужели я настолько путано все изложил? AS> Да нет, именно "на С++ можно все то же самое". ;-) Просто, когда с AS> пеной у рта пытаются что-то доказать, думают, что это считается самым AS> лучшим из лучших. Я же лишь пытаюсь доказать, что С++ - язык AS> достаточно универсальный, чтоб позволить делать очень многое. И чтобы AS> не подумали чего большего, заявляю, что С++ все равно *может быть* AS> неидеальным. Пока что примеры бьют немного мимо цели ... AS> Но, между тем, я придерживаюсь мнения, что С++, по крайней мере, не AS> менее достоен чести быть широко используемым языком программирования, AS> по сравнению с языками ФП. То есть, ФП не обязательно должно быть AS> предпочтительнее ИП (ООП, ...). Да, C++ - это оцень хороший target для компиляторов с языков высокого уровня, с этим сложно поспорить. Хотя C - легковеснее и лучше. >> Да-да.... А кто до сих пор сомневается - плохо ее читал, так? :) AS> Может, просто не читал... Я просто вижу, что ты (как и я) не знаешь AS> тонкостей языка, делающих возможным то, чего не позволяли раньше AS> императивные языки. Я почему-то вижу несколько иное ... -- Dmitry Astapov //ADEpt E-mail: [EMAIL PROTECTED] GPG KeyID/fprint: F5D7639D/CA36 E6C4 815D 434D 0498 2B08 7867 4860 F5D7 639D