AndrewVK,
> Ш> Это достигается за счет очень серьёзных ограничений на возможности дженериков. Для шаблонов это неприемлимо.
> Никаких ограничений на выполнение основной задачи дженериков — дженерик программирования, это не накладывает.
Зависит от используемого определения generic программирования. Однако отрицать, что из generics доступны далеко не все возможности C# не приходится. Например, использование перегруженных операторов и (если не ошибаюсь) статических методов.
> Что же касается возможностей метапрограммирования — плюсовые шаблоны это один из худших вариантов, который можно придумать.
Можно ограничить рассмотрение только "обычным" generic программированием. Проблема только в том, что определить грань между generic программированием и метапрограммированием далеко не всегда легко.
Posted via RSDN NNTP Server 1.9
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте, Шахтер, Вы писали:
AVK>>Да? А если мы возьмем обыкновенные контейнеры? Там именно что дублирование — разница только в адресах функций и размерах оперируемых данных.
Ш>Да? А не освежить ли тебе память и не посмотреть ли на то, как устроен итератор по вектору и по списку?
возьмем обыкновенные контейнеры
Я понимаю, что есть случай, когда дублирование оправдано. Но ровно так же есть случаи, когда оно не оправдано. И если внимательно на такие случаи посмотреть, то это окажется как раз то самое метапрограммирование. Итераторы как раз и есть метапрограммирование.
Здравствуйте, _FRED_, Вы писали:
_FR>>> И, к слову, сильно ещё сама среда не готова к дженерикам. AVK>>Какая среда? _FR>Извини, не ясно высказался. Среда разработки. Whidbey. Столкнулся с парой неприятных моментов, но, к стыду своему, пока не нашёл времени попросить помощи в подготовке репорта в feedback.
VS 2005 еще очень сырая и дело далеко не только в дженериках.
_FR>Да! Это другое. Ну почему, например, не позволить, сделать такие мелочи, как, например, отдельное именование ограничения/уточнения?
Здравствуйте, AndrewVK, Вы писали:
AVK>Здравствуйте, Шахтер, Вы писали:
AVK>>>Да? А если мы возьмем обыкновенные контейнеры? Там именно что дублирование — разница только в адресах функций и размерах оперируемых данных.
Ш>>Да? А не освежить ли тебе память и не посмотреть ли на то, как устроен итератор по вектору и по списку?
AVK>возьмем обыкновенные контейнеры
Вектор и список -- самые что ни на есть обыкновеннейшие контейнеры.
AVK>Я понимаю, что есть случай, когда дублирование оправдано. Но ровно так же есть случаи, когда оно не оправдано. И если внимательно на такие случаи посмотреть, то это окажется как раз то самое метапрограммирование.
Просто не могу вкурить, что ты хочешь сказать. Наверно, я тупой.
AVK>Итераторы как раз и есть метапрограммирование.
Уф. Итераторы никаким боком не относятся к метапрограммированию. Метапрограммирование -- это набор техник, позволяющих провести вычисление над типами и константами во время компиляции.
Итераторы -- это как раз хороший пример обобщённого программирования.
И ещё. Обобщённое программирование потому так и называется, что позволяет абстрагироваться от деталей устройства того или иного типа и использовать его абстрактные свойства и поведение. Одинаковый код при этом получится никак не может. Если при использовании дженериков получается один и тот же MSIL код, то это означает только одно -- никаким обобщённым программированием там и не пахнет, максимум что там есть -- старый банальный полиморфизм (поданый под новым соусом).
AndrewVK,
> Я понимаю, что есть случай, когда дублирование оправдано. Но ровно так же есть случаи, когда оно не оправдано. И если внимательно на такие случаи посмотреть, то это окажется как раз то самое метапрограммирование. Итераторы как раз и есть метапрограммирование.
Ты, похоже, пользуешься каким-то уж очень нетрадиционным определением метапрограммирования.
А функция find() в этих "обыкновенных" контейнерах Vector и List тоже "будет метапрограммированием"? Если нет, чем она отличается от итераторов? Если да, то я вообще не понимаю, где в твоей трактовке грань между generic программированием, и метапрограммированием.
Если мы уберем из контейнеров итераторы, то, по-видимому, придется добавить индексацию (operator []). Индексация тоже "будет метапрограммированием", или нет?
Posted via RSDN NNTP Server 1.9
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте, AndrewVK, Вы писали: _FR>>>> И, к слову, сильно ещё сама среда не готова к дженерикам. AVK>>>Какая среда? _FR>>Извини, не ясно высказался. Среда разработки. Whidbey. Столкнулся с парой неприятных моментов, но, к стыду своему, пока не нашёл времени попросить помощи в подготовке репорта в feedback. AVK>VS 2005 еще очень сырая и дело далеко не только в дженериках.
Мирюсь :о)
_FR>>Да! Это другое. Ну почему, например, не позволить, сделать такие мелочи, как, например, отдельное именование ограничения/уточнения? AVK>Это как?
Вот есть у меня набор классов, взаимодействующих друг с другом, но не связанных "родственными отношениями".
Что-то на подобии O\R Mapping'а. Есть базовай класс Entity. Всё, что нужно от него остальным — его идентификотор.Может быть int, или Guid, или даже составным (из нескольких полей). Объявил я его примрно так:
public abstract class BizEntity<IdentiferType>
where IdentiferType : struct, IComparable<IdentiferType>
{
//...
// По сути всё, что внешний мир должен о нём знатьpublic IdentiferType EntityID {
get {
}
}
//...
}
CLRовские типы этим условиям удовлетворяют, будет составной ключ — напишу свою структуру под него и реализую нужный интерфейс.
Соответственно все классы, так или иначе с ним связанные, тащут за собой этот "хвост" из IdentiferType : struct, IComparable<IdentiferType>. А вдруг мне понадобится какой ещё интерфейс у этой структуры? Надо будет всё облазить и всё поправить.
Например, метод, который мне эту сущность должен вернуть такой получается:
public class BizEntityManager<IdentiferType> where IdentiferType : struct, IComparable<IdentiferType>
{
//...
E Load<E, IdentiferType>(IdentiferType ID)
where E : BizEntity<IdentiferType>
where IdentiferType : struct, IComparable<IdentiferType>
{
}
//...
}
Примерно так, если в синтаксисе нигде не запутался
Требуется что-то, даже на подобии юзинга, чтоб в каждом файле даже объявлять, что
using constraint IdentiferTypeC = struct, IComparable<IdentiferType>
public abstract class BizEntity<IdentiferType> where IdentiferType : IdentiferTypeC
{
//...
// По сути всё, что внешний мир должен о нём знатьpublic IdentiferType EntityID {
get {
}
}
//...
}
Хоть бы так.
Это "заставь дурака Богу мольться..." или нет?
Help will always be given at Hogwarts to those who ask for it.
Шахтер,
> И ещё. Обобщённое программирование потому так и называется, что позволяет абстрагироваться от деталей устройства того или иного типа и использовать его абстрактные свойства и поведение. Одинаковый код при этом получится никак не может.
Извини, немного уточню: может, но не должен
> Если при использовании дженериков получается один и тот же MSIL код, то это означает только одно -- никаким обобщённым программированием там и не пахнет, максимум что там есть -- старый банальный полиморфизм (поданый под новым соусом).
У меня тоже сложилось похожее ощущение. Насколько я понимаю, generics от "банального полиморфизма" в C# отличаются (только) тем, что позволяют лучше контролировать соответствие типов во время компиляции, плюс позволяют избегать множества приведений типов, в противном случае неизбежных без написания своих переходников к контейнерам и т.п.
Posted via RSDN NNTP Server 1.9
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте, Павел Кузнецов, Вы писали:
ПК>Шахтер,
>> И ещё. Обобщённое программирование потому так и называется, что позволяет абстрагироваться от деталей устройства того или иного типа и использовать его абстрактные свойства и поведение. Одинаковый код при этом получится никак не может.
ПК>Извини, немного уточню: может, но не должен
Похоже опять не совсем точно. Может и будет в определённых ситуациях. Например, если шаблон параметризуется типами int * и long * на платформе, на которой физически типы int и long устроены одинаково, то естественно, скорее всего, сгенерится одинаковый код. Тут надо заметить, однако, что современные компиляторы умеют устранять подобное дублирование кода.
Тем не менее, в общем случае, код, скорее всего, будет существенно разным. И в этом большая ценность обобщённого программирования. Оно позволяет лучше "сжимать" код. Т.е. меньшим количеством исходного кода можно получить больше результирующего ассемблерного кода.
Здравствуйте, Шахтер, Вы писали:
AVK>>возьмем обыкновенные контейнеры
Ш>Вектор и список -- самые что ни на есть обыкновеннейшие контейнеры.
Но не итератор. Это вобще не контейнер, а средство работы с ним.
AVK>>Я понимаю, что есть случай, когда дублирование оправдано. Но ровно так же есть случаи, когда оно не оправдано. И если внимательно на такие случаи посмотреть, то это окажется как раз то самое метапрограммирование.
Ш>Просто не могу вкурить, что ты хочешь сказать. Наверно, я тупой.
Я хочу сказать что метапрограммирование реализуется не только шаблонами. Более того — реализация метапрограммирования шаблонами на редкость неудачное. Отсюда невозможность использовать дженерики для метапрограммирования не есть их недостаток, поскольку они не предназначены для метапрограммирования.
AVK>>Итераторы как раз и есть метапрограммирование.
Ш>Уф. Итераторы никаким боком не относятся к метапрограммированию. Метапрограммирование -- это набор техник, позволяющих провести вычисление над типами и константами во время компиляции. Ш>Итераторы -- это как раз хороший пример обобщённого программирования.
Metaprogramming is the writing of programs that write or manipulate other programs (or themselves) as their data or that do part of the work that is otherwise done at runtime during compile time. This allows programmers to produce a larger amount of code and get more done in the same amount of time as they would take to write all the code manually.
Метапрограммирование это создание программ, создающих программы. Итератор как раз такая программа и есть — декларативное описание на этапе компиляции разворачивается в итеративный код.
Ш>И ещё. Обобщённое программирование потому так и называется, что позволяет абстрагироваться от деталей устройства того или иного типа и использовать его абстрактные свойства и поведение. Одинаковый код при этом получится никак не может. Если при использовании дженериков получается один и тот же MSIL код, то это означает только одно -- никаким обобщённым программированием там и не пахнет, максимум что там есть -- старый банальный полиморфизм (поданый под новым соусом).
In computer science, generics is a technique that allows one value to take different datatypes (so-called polymorphism) as long as certain contracts such as subtypes and signature are kept. The programming style emphasizing use of this technique is called generic programming.
Дотнетовские дженерики на 100% этому определению соответствуют.
Здравствуйте, AndrewVK, Вы писали:
AVK>Никаких ограничений на выполнение основной задачи дженериков — дженерик программирования, это не накладывает. Что же касается возможностей метапрограммирования — плюсовые шаблоны это один из худших вариантов, который можно придумать.
Подобные заявления попадают под категорию (цитируя классика) "космического масштаба и космической же глупости о том, как все поделить".
Шаблоны в C++ — ужасны. Но что-то пока не видать ни одного другого языка программирования, в котором было бы что-то подобное, с такой же свободой выражения мыслей и такой же эффективностью кода. С++ — язык свободы, за что он и снискал всеобщую любовь и всеобщую ненависть.
На самом деле, все выпады дот-нетчиков в сторону C++ сводятся к одной простой фразе:
Если вы все такие умные, чего же вы строем не ходите?
Без обид!
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
AndrewVK,
> Ш>Итераторы -- это как раз хороший пример обобщённого программирования.
>
Metaprogramming is the writing of programs that write or manipulate other programs (or themselves) as their data or that do part of the work that is otherwise done at runtime during compile time. This allows programmers to produce a larger amount of code and get more done in the same amount of time as they would take to write all the code manually.
> Метапрограммирование это создание программ, создающих программы. Итератор как раз такая программа и есть — декларативное описание на этапе компиляции разворачивается в итеративный код.
Ничего подобного. Итераторы программой как данными не оперируют. Более того, ничего принципиально декларативного в них тоже нет:
std::vector<int> v( 10 );
for (std::vector<int>::iterator i = v.begin(), e = v.end(); i != e; ++i)
*i = e - i;
самая что ни на есть итеративная программа.
Posted via RSDN NNTP Server 1.9
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте, Павел Кузнецов, Вы писали:
ПК>Проблема только в том, что определить грань между generic программированием и метапрограммированием далеко не всегда легко.
Точно! Может скажу и не в кассу, но слово "метапрограммирование" во мне до сих пор вызывает какой-то ступор, почти как "контрреволюция" — совершенно не понятно, что под ним скрывается. С этой точки зрения термин "generic" — гораздо более удачен. Есть сильное подозрение, что он рассчитан на профанов типа меня, не понимающих слова "метапрограммирование"
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
Здравствуйте, Павел Кузнецов, Вы писали:
ПК>Ничего подобного. Итераторы программой как данными не оперируют. Более того, ничего принципиально декларативного в них тоже нет: ПК>
ПК>std::vector<int> v( 10 );
ПК>for (std::vector<int>::iterator i = v.begin(), e = v.end(); i != e; ++i)
ПК> *i = e - i;
ПК>
ПК>самая что ни на есть итеративная программа.
Сам итератор декларативно задает некий алгоритм. Натуральная метапрограмма.
Здравствуйте, McSeem2, Вы писали:
MS>Шаблоны в C++ — ужасны. Но что-то пока не видать ни одного другого языка программирования, в котором было бы что-то подобное, с такой же свободой выражения мыслей и такой же эффективностью кода. С++ — язык свободы, за что он и снискал всеобщую любовь и всеобщую ненависть.
Подобные заявления попадают под категорию (цитируя классика) "космического масштаба и космической же глупости о том, как все поделить".
То что ты не знаешь языков гибче С++ еще не значит что их не существует. Например OpenC++ по гибкости на порядок круче С++.
Здравствуйте, AndrewVK, Вы писали:
AVK>То что ты не знаешь языков гибче С++ еще не значит что их не существует. Например OpenC++ по гибкости на порядок круче С++.
Фактически, если я о них не знаю, это как раз и означает, что их нет. Это все делается на уровне доморощенного энтузиазма, так же, как мой AGG или R#. До стандартизации и промышленного применения — ох как далеко. Короче говоря, здесь я больше верю в дот-нет, чем в OpenC++.
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
AndrewVK,
> ПК>Ничего подобного. Итераторы программой как данными не оперируют. Более того, ничего принципиально декларативного в них тоже нет: > ПК>
> ПК>std::vector<int> v( 10 );
> ПК>for (std::vector<int>::iterator i = v.begin(), e = v.end(); i != e; ++i)
> ПК> *i = e - i;
> ПК>
> ПК>самая что ни на есть итеративная программа.
> Сам итератор декларативно задает некий алгоритм. Натуральная метапрограмма.
Никакая это не метапрограмма, самая обычная абстракция. Давай выкинем шаблоны, но, скажем, оставим итератор для самописного контейнера VectorInt, повторяющего функциональность std::vector<int>. В этом случае его итератор по-прежнему VectorInt::Iterator является метапрограммой?
А если мы изменим VectorInt и его Iterator, так что они будут реализовывать интерфейсы IIteratableContainerInt и IIteratorInt, итератор VectorInt::Iterator по-прежнему будет метапрограммой?
Далее, можно взять аналогию еще и из другой области. Допустим, функция sort() принимает интерфейс предикат, устанавливающий порядок, какой-нибудь IComparator. Классы, реализующие этот IComparator, будут "задавать некий алгоритм". Это тоже метапрограммирование?
Если да, то половина паттернов GoF будет метапрограммами
В общем, если вернуться к определению метапрограммирования, которое ты процитировал ранее:
Metaprogramming is the writing of programs that write or manipulate other programs (or themselves) as their data or that do part of the work that is otherwise done at runtime during compile time.
то можно заметить, что оно состоит из трех вариантов:
writing of programs that write other programs (or themselves)
writing of programs that manipulate other programs (or themselves) as their data
writing of programs that do part of the work that is otherwise done at runtime during compile time
Во-первых, можно заметить, что ничего о декларативном программировании здесь нет, так что эту часть твоих рассуждений мы проигнорируем. Сразу очевидно, что ни первому, ни второму варианту итераторы не удовлетворяют. Остается третий вариант, о выполнении части run-time работы во время компиляции. Если трактовать эту часть достаточно широко, то сюда подойдет даже разрешение перегрузки, что вообще-то говорит о "качестве" определения Однако не видно, даже при такой широкой трактовке, чтобы сюда каким-нибудь боком подходили итераторы
Posted via RSDN NNTP Server 1.9
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте, Шахтер, Вы писали:
Ш>Дело ведь не в том, что придерживаются. А в том, что очень трудно технически перескочить с этого подхода на полностью модульный подход.
На самом деле, не так уж и трудно. Достаточно научить компилятор понимать формат OBJ-файлов и линковать в бинарный код. При этом, чисто Сишые (или Фортрановсеие) obj-файлы точно так же могут быть подключены к списку трансляции. При этом, тот самый единый модуль "компилинкер" имеет право транслировать и подключать шаблоны. Никаких технических препятствий для этого я не вижу. Единственная причина — традиции
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.