[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: programming languages



Evening, Andrei. 

Andrei Sosnin <demonsly@hot.ee> 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: adept@umc.com.ua
GPG KeyID/fprint: F5D7639D/CA36 E6C4 815D 434D 0498  2B08 7867 4860 F5D7 639D



Reply to: