Только начинаю касаться ООП.
Подскажите, а что такое Полиморфизм. Ну вообще не догоняю. Если лучше на примере, можно и пример, просто и примитивный.
Везде какой то бред написан, нихрена не пойму.
Вот что такое Инкапсуляция, Наследование — это понятно. Это я вижу где приминить можно, где воспользоваться и т.д. А вот Полиморфизм вообще никуда не упирается.
Здравствуйте, Zender, Вы писали:
Z>Только начинаю касаться ООП. Z>Подскажите, а что такое Полиморфизм. Ну вообще не догоняю. Если лучше на примере, можно и пример, просто и примитивный. Z>Везде какой то бред написан, нихрена не пойму. Z>Вот что такое Инкапсуляция, Наследование — это понятно. Это я вижу где приминить можно, где воспользоваться и т.д. А вот Полиморфизм вообще никуда не упирается.
Здравствуйте, Zender, Вы писали:
Z>Только начинаю касаться ООП. Z>Подскажите, а что такое Полиморфизм. Ну вообще не догоняю. Если лучше на примере, можно и пример, просто и примитивный. Z>Везде какой то бред написан, нихрена не пойму. Z>Вот что такое Инкапсуляция, Наследование — это понятно. Это я вижу где приминить можно, где воспользоваться и т.д. А вот Полиморфизм вообще никуда не упирается.
Здравствуйте, Zender, Вы писали:
Z>Только начинаю касаться ООП. Z>Подскажите, а что такое Полиморфизм. Ну вообще не догоняю. Если лучше на примере, можно и пример, просто и примитивный. Z>Везде какой то бред написан, нихрена не пойму. Z>Вот что такое Инкапсуляция, Наследование — это понятно. Это я вижу где приминить можно, где воспользоваться и т.д. А вот Полиморфизм вообще никуда не упирается.
ООП без полиморфизма невозможно. Без полиморфизма это тупо С с классами.
Класс [Животное]
{
virtual срать() = 0;
}
Класс [Лошадь] : [Животное]
{
virtual срать()
{
поднять_хвост();
навалить_яблок();
}
}
Класс [Собака] : [Животное]
{
virtual срать()
{
присесть();
навалить();
}
}
Класс [Ферма]
{
//Список зверей на ферме
std::list<Животное *> звери;
//Конструктор фермы
Ферма()
{
//Добавляем зверей
звери.append(new Лошадь());
звери.append(new Собака());
}
//все срём по рассписаниюvoid дефекация()
{
for_each(Животное * зверь, звери)
{
зверь->срать();
//Каждое животное будет срать по своему
//Обрати внимание что в списке у нас Животное
//а добавляем мы конкретных зверей
//но срать заставляем через указатель на Животное
//это и есть полиморфизм
}
}
}
Простейший пример из алгоритмов, вводим некий интерфейс comparable который только устанавливает между объектами некое свойство "старшинства"
bool Icomparable::isGreater(Icomparable& lh);
Теперь мы можем написать большое множество алгоритмов сортировки , операций над множествами и т.п. используя этот интерфейс (контракт).
Теперь любой объект который реализует этот интерфейс может пользоваться алгоритмами реализованными для этой операции.
Например строка с учетом заглавных букв и без учета , действительные числа с учетом знака и без учета, животный мир по к-ву ног или глаз, эксперты по уровню квалификации и т.п.
Здравствуйте, Zender, Вы писали:
Z>Вот что такое Инкапсуляция, Наследование — это понятно. Это я вижу где приминить можно, где воспользоваться и т.д. А вот Полиморфизм вообще никуда не упирается.
из документации по функции addWidget класса QLayout
Или QIODevice, где можно написать алгоритм на его методах. Потом создать объекты QFile, QBuffer и QTcpSocket, и через динамическое приведение типов передать их этому алгоритму. Алгоритм закодирован один раз, но благодаря полиморфизму может работать с разными источниками данных. Аналогичных полиморфизму (объектно-ориентированное программирование) результатов в C++ можно добиться с помощью шаблонов C++ (обобщённое программирование), так поступают в stl и boost. Тоже самое касается Java, C# и других.
Z>Только начинаю касаться ООП. Z>Подскажите, а что такое Полиморфизм. Ну вообще не догоняю. Если лучше на примере, можно и пример, просто и примитивный. Z>Везде какой то бред написан, нихрена не пойму. Z>Вот что такое Инкапсуляция, Наследование — это понятно. Это я вижу где приминить можно, где воспользоваться и т.д. А вот Полиморфизм вообще никуда не упирается.
Это возможность выполнять одну и ту же операцию над разными данными:
print( 10 ); // <= операция print выполняется над числом.
print( "опа" ); // <= операция print выполняется над строкой.
// Полиморфизм, однако.
Полиморфизм в целом бывает signature based — когда задаются несколько пераций с одним именем, принимающие разные данные. А еще бывает capability based — это когда сами данные предоставляют некий одинаковый интерфейс, чтобы с ними могла работать одна операция. Еще полиморфизм бывае времени выполнения и вреени компиляции. Полиморфизму сильно помогают фияи, реализованные в языках программирования — перегрузка функций/методов, интерфейсы, шаблоны. Но в целом можно обойтись и без них, просто кода становится несколько больше.
В целом полиморфизм почему-то сильно связывают с ООП, но на мой профессиональный взгляд это все же разные штуки.
Здравствуйте, CannyMan, Вы писали:
CM>Здравствуйте, Eye of Hell, Вы писали: EOH>>Это возможность выполнять одну и ту же операцию над разными данными: EOH>>
EOH>>print( 10 ); // <= операция print выполняется над числом.
EOH>>print( "опа" ); // <= операция print выполняется над строкой.
EOH>>// Полиморфизм, однако.
EOH>>
CM>Какой же тут полиморфизм. Банальная перегрузка функций.
Банальная перегрузка функций есть ad-hoc полиморфизм
Здравствуйте, samius, Вы писали:
S>Здравствуйте, CannyMan, Вы писали:
CM>>Здравствуйте, Eye of Hell, Вы писали: EOH>>>Это возможность выполнять одну и ту же операцию над разными данными: EOH>>>
EOH>>>print( 10 ); // <= операция print выполняется над числом.
EOH>>>print( "опа" ); // <= операция print выполняется над строкой.
EOH>>>// Полиморфизм, однако.
EOH>>>
CM>>Какой же тут полиморфизм. Банальная перегрузка функций. S>Банальная перегрузка функций есть ad-hoc полиморфизм
Вы путаете overloading и overriding. Полиморфизм это overriding. А в этом случае overloading.
Здравствуйте, CannyMan, Вы писали:
CM>>>Какой же тут полиморфизм. Банальная перегрузка функций. S>>Банальная перегрузка функций есть ad-hoc полиморфизм CM>Вы путаете overloading и overriding. Полиморфизм это overriding. А в этом случае overloading.
Никто ничего не путает. Полиморфизм бывает разный. Когда мы пишем List<T> — это тоже вполне себе полиморфизм, только уже параметрический. Полиморфизм — это очень общее понятие, и не надо его путать с dynamic binding, который попросту один из механизмов реализации.
Здравствуйте, CannyMan, Вы писали:
CM>Здравствуйте, samius, Вы писали:
S>>Здравствуйте, CannyMan, Вы писали:
CM>>>Какой же тут полиморфизм. Банальная перегрузка функций. S>>Банальная перегрузка функций есть ad-hoc полиморфизм CM>Вы путаете overloading и overriding. Полиморфизм это overriding. А в этом случае overloading.
Здравствуйте, Zender, Вы писали:
Z>Только начинаю касаться ООП. Z>Подскажите, а что такое Полиморфизм. Ну вообще не догоняю. Если лучше на примере, можно и пример, просто и примитивный. Z>Везде какой то бред написан, нихрена не пойму. Z>Вот что такое Инкапсуляция, Наследование — это понятно. Это я вижу где приминить можно, где воспользоваться и т.д. А вот Полиморфизм вообще никуда не упирается.
А вот нам прямо сегодня на курсе тренер из Л******* объяснил: "это когда мы можем подсунуть, а он смимикрирует".
Здравствуйте, Eye of Hell, Вы писали:
CM>>Какой же тут полиморфизм. Банальная перегрузка функций.
EOH>Увы, но по имеющейся у меня информации перегрузка функций — это один из самых банальных способов реализации полиморфизма.
Ага, и как ваш код из DLL будет банально перегружать функции классов которых еще нету на момент компиляции DLL-ки?
Дворник Василий вам информацию задарма скинул?
Ну тогда уже Двойная диспетчеризация вообще никому никогда не понадобится, разве что перед Девками хвастаться здесь
EOH>>Увы, но по имеющейся у меня информации перегрузка функций — это один из самых банальных способов реализации полиморфизма. V>Ага, и как ваш код из DLL будет банально перегружать функции классов которых еще нету на момент компиляции DLL-ки?
Не понял вашего вопроса. При чем тут перегрузка методов классов, код которых недоступен на момент компиляци? Если код на момент компиляции недоступен — то средствами языка с static binding оно не перегружается. Для таких вещей другие конструкции придумали — тот же COM, например.
Здравствуйте, Vaako, Вы писали:
V>Здравствуйте, Eye of Hell, Вы писали:
CM>>>Какой же тут полиморфизм. Банальная перегрузка функций.
EOH>>Увы, но по имеющейся у меня информации перегрузка функций — это один из самых банальных способов реализации полиморфизма.
V>Ага, и как ваш код из DLL будет банально перегружать функции классов которых еще нету на момент компиляции DLL-ки? V>Дворник Василий вам информацию задарма скинул? V>Ну тогда уже Двойная диспетчеризация вообще никому никогда не понадобится, разве что перед Девками хвастаться V>здесь
Вы хотите дискредитировать саму информацию, ее источник, или свою способность к анализу и осмыслению информации?
Здравствуйте, Vaako, Вы писали:
V>Ага, и как ваш код из DLL будет банально перегружать функции классов которых еще нету на момент компиляции DLL-ки?
Полиморфизм бывает статический — работающий на этапе компиляции, и динамическим. Перегрузка вид статического полиморфизма. Шаблоны С++ и перегрузка так же обеспечивают статический полиморфизм.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, Vaako, Вы писали:
V>>Ага, и как ваш код из DLL будет банально перегружать функции классов которых еще нету на момент компиляции DLL-ки?
VD>Полиморфизм бывает статический — работающий на этапе компиляции, и динамическим. Перегрузка вид статического полиморфизма. Шаблоны С++ и перегрузка так же обеспечивают статический полиморфизм.
Я так плохо разбираюсь в таких вещах, что надо погуглить:
Перегрузка функций это специальная техника, позволяющая создавать несколько функций с одинаковыми именами в одной области имен. При этом функции должны отличаться т.н. сигнатурой функции.(1)
В процессе компиляции C++ принимает во внимание количество аргументов, используемых каждой функцией, и затем вызывает именно требуемую функцию. Предоставление компилятору выбора среди нескольких функций называется перегрузкой.
Полиморфизмом в программировании называется переопределение наследником функций-членов базового класса. Какая именно из функций будет вызвана определяется во время компиляции.
class Figure
{
...
void Draw() const;
};
class Circle : public Figure
{
...
void Draw() const;
};
Circle *c = new Circle(0,0,5);
Figure *f = c; // Всё ok: Figure — базовый класс для Circle
c->Draw();
f->Draw();
// Указатели друг другу равны, но для f будет вызвана другая функция, чем для c
Несмотря на то, что оба указателя указывают на один и тот же объект класса Circle, для c будет вызвана Circle::Draw(), а для f — Figure::Draw(), поскольку f — указатель на объект класса Figure. Такой полиморфизм называется статическим. (2)
Но в C++ есть и динамический полиморфизм, когда вызываемая функция определяется во время выполнения. Для этого функции-члены базового класса должны быть объявлены виртуальными.(3)
(*) Ага, значит при перегрузке множество функций из которых компилятор выбирает должны отличатся сигнатурой. Неявный параметр (this, self и т.д.) к сигнатуре не относится. Статический полиморфизм this также не использует(2).
(**) При полиморфизме сигнатуры должны совпадать? Вроде должны.
(***) Перегрузка кроме сравнения сигнатур перебирает все явные и неявные преобразования типов. Это значит, что код может перестать компилироваться, если возникнут неопределенности с преобразованиями типов (ambiguous call to overloaded function). Не уверен что при статическом полиморфизме возможна неоднозначность в выборе нужной функции.
Потому действительно если нет желания различать эти два механизма, то можно путать их между собой. Хотя при двойной диспетчеризации нужно использовать и перегрузку и полиморфизм. Хотя постойте, можно ведь все функции переделать добавив два новых аргумента foo(A* thisA, B* thisB, …. ).
Уря у меня получилось простой перегрузкой охватить и динамический полиморфизм и двойную диспетчеризацию. Думаю если постараться то можно и множественное наследование свести до перегрузки функций. Так можно все что угодно свести к перегрузке.
V>Полиморфизмом в программировании называется переопределение наследником функций-членов базового класса. Какая именно из функций будет вызвана определяется во время компиляции.
Здесь описан частный случай одной из реализаций полиморфизма для конкретного языка. Автор забыл упомянуть, что это частный случай реализации — такое бывает, википедия, увы, несовершенна.
V> Дворник Василий вам информацию задарма скинул? V> Я так плохо разбираюсь в таких вещах, что надо погуглить:
Если вы плохо разбираетесь в таких вещах — зачем наезжать на программистов, у которых по 15 лет опыта коммерческой разработки? Наверное, я не просто так про полиморфизм написал именно то, что написал?
Здравствуйте, Zender, Вы писали:
Z>Только начинаю касаться ООП. Z>Подскажите, а что такое Полиморфизм. Ну вообще не догоняю. Если лучше на примере, можно и пример, просто и примитивный. Z>Везде какой то бред написан, нихрена не пойму. Z>Вот что такое Инкапсуляция, Наследование — это понятно. Это я вижу где приминить можно, где воспользоваться и т.д. А вот Полиморфизм вообще никуда не упирается.
Полиморфизм это наше все. Главная мысля что б одинаково было написано для разных применений. Т.е. в этом смысле и евкливодо пространство предпочтительно перед другими системами своим полиморфизмом. Теория относительности и ньютона и эйнштейна это, собственно, тоже замеченый ими полиморфизм. Удобней так. Вот это единственное и самое главное достоинство полиморфизма.
Здравствуйте, Vaako, Вы писали:
V>Здравствуйте, VladD2, Вы писали:
V>Полиморфизмом в программировании называется переопределение наследником функций-членов базового класса. Какая именно из функций будет вызвана определяется во время компиляции.
Здравствуйте, Vaako, Вы писали:
V>Хотя при двойной диспетчеризации нужно использовать и перегрузку и полиморфизм.
Двойная диспетчеризация может прекрасно работать без использования перегрузки.
V>Хотя постойте, можно ведь все функции переделать добавив два новых аргумента foo(A* thisA, B* thisB, …. ).
разве что диспетчеризацию надо будет делать руками
Здравствуйте, Eye of Hell, Вы писали:
V>>Полиморфизмом в программировании называется переопределение наследником функций-членов базового класса. Какая именно из функций будет вызвана определяется во время компиляции.
EOH>Здесь описан частный случай одной из реализаций полиморфизма для конкретного языка. Автор забыл упомянуть, что это частный случай реализации — такое бывает, википедия, увы, несовершенна.
V>> Дворник Василий вам информацию задарма скинул? V>> Я так плохо разбираюсь в таких вещах, что надо погуглить:
EOH>Если вы плохо разбираетесь в таких вещах — зачем наезжать на программистов, у которых по 15 лет опыта коммерческой разработки? Наверное, я не просто так про полиморфизм написал именно то, что написал?
Не обижайтесь.
Но как только кто либо упоминает "Полиморфизм" это сразу подразумевает и "наследование", поскольку это сильно связанные понятия.
Другими словами "Полиморфизм" не является отдельным независимым понятием или концепцией как перегрузка функций. Даже если мы применяем "Полиморфизм" применительно к функциям, а не классам. Технически это совершенно разные механизмы и могут быть совмещены в одном и том же классе. Перегрузка начинается и заканчивается на этапе компиляции производя поиск и выбор одной функции из множества. Полиморфизм не требует никакого поиска или выбора, поскольку компилятор вставляет сразу либо конкретную функцию, либо блок вызывающий функцию через таблицу виртуальных функций, либо блок осуществляющий поиск нужной функции при множественном наследовании. Эти и другие механизмы срабатывают во время исполнения, а не компиляции.
Следовательно, в первом приближении, если опыт подсказывает, что полиморфизм скорее перегрузка, то, либо опыт не заслуживает доверия, либо программист сам не понимает что говорит. Сравнивать полиморфизм с перегрузкой все равно что сравнивать коров с заборами. Хотя переход к точным формулировкам если и разрешит путаницу, но, имхо, из=за своего математически-подобной формулировки, прививающий математический способ мышления, плохо отражает естественное мышление программиста. Например, все математические рассуждения без исключения исследуют только такие объекты, которые не меняются во время этого самого рассуждения. В математике правила рассуждения заданы в исходных предпосылках и аксиомах и не меняются на протяжении рассуждений. Программист же работает с постоянно меняющейся программой. В любом случае упоминание полиморфизма подразумевает и требует упоминание наследования, инкапсуляции и абстракции.
С другой стороны, психологам известна интересная особенность естественного мышления, которую пока не удалось представить строго математически. Мышлению присуща способность выделить в рассуждении некоторой объект Х и заменить его на использование объекта Y с совершенно другими свойствами. Возможно это имеет какое-то отношение к единообразному манипулировнию совершенно разными объектами. Тогда неправ я и программист хотел сказать, что перегрузка и полиморфизм хотя и являются разными механизмами но вместе отражают эту странную способность человеческого мышления. Но достаточно ли в таком случае только перегрузки и полиморфизма? Я бы сказал в самом сложном случае перегрузка и полиморфизм преследуют одинаковую цель, и эта цель не выражается ни одним из них ни каким-либо другим механизмом или принципом, даже математической формулировки не имеет. Тогда да действительно не было никакого смысла в точных формулировках.
Здравствуйте, samius, Вы писали:
S>Здравствуйте, Vaako, Вы писали:
V>>Здравствуйте, VladD2, Вы писали:
V>>Полиморфизмом в программировании называется переопределение наследником функций-членов базового класса. Какая именно из функций будет вызвана определяется во время компиляции.
S>Сравни это с английской версией той же страницы http://en.wikipedia.org/wiki/C%2B%2B#Polymorphism, или со статьей, куда ведет ссылка из русской версии от слова "Полиморфизмом".
Да точно:
Polymorphism enables one common interface for many implementations, and for objects to act differently under different circumstances.
Это один к одному определение перегрузки функций, особенно если переводить "one common interface" как разные сигнатуры у функций. Очевидно упоминание "перегрузка функций — это один из самых банальных способов реализации полиморфизма" тут как раз к месту. Осталось только уточнить что означает самый банальный "common interface". Я не прав7
Здравствуйте, samius, Вы писали:
S>Здравствуйте, Vaako, Вы писали:
V>>Хотя при двойной диспетчеризации нужно использовать и перегрузку и полиморфизм. S>Двойная диспетчеризация может прекрасно работать без использования перегрузки.
V>>Хотя постойте, можно ведь все функции переделать добавив два новых аргумента foo(A* thisA, B* thisB, …. ). S>разве что диспетчеризацию надо будет делать руками
Да можно, как и перегрузку без полиморфизма, поскольку это разные механизмы вообще. Вопрос же заключается, почему опыт программиста подсказывает использовать совершенно разные механизмы для практически очень похожих задач. Вы же не собираетесь переименовать перегрузку в "примитивный полиморфизм"?
Здравствуйте, Eye of Hell, Вы писали:
EOH>Не понял вашего вопроса. При чем тут перегрузка методов классов, код которых недоступен на момент компиляци? Если код на момент компиляции недоступен — то средствами языка с static binding оно не перегружается. Для таких вещей другие конструкции придумали — тот же COM, например.
Потому что вы сами говорили:
В целом полиморфизм почему-то сильно связывают с ООП, но на мой профессиональный взгляд это все же разные штуки.
хотя опыт вам подсказывает иногда обратное. Скажем так, зачем программист использует полиморфизм? Уточнение терминологии тут мало чем поможет, поскольку мы не знаем как мыслит программист. Опыт на самом деле не подтверждает теорию, он может ее только опровергнуть.
Здравствуйте, Vaako, Вы писали:
V>Здравствуйте, samius, Вы писали:
V>Да точно:
V>
V>Polymorphism enables one common interface for many implementations, and for objects to act differently under different circumstances.
V>Это один к одному определение перегрузки функций, особенно если переводить "one common interface" как разные сигнатуры у функций. Очевидно упоминание "перегрузка функций — это один из самых банальных способов реализации полиморфизма" тут как раз к месту.
Перегрузка функций — не самый банальный способ реализации полиморфизма. Есть еще банальнее: арифметические операторы в ЯП, как правило, являются полиморфными, даже в тех ЯП, которые не позволяют перегрузку операторов или даже функции как таковые.
V>Осталось только уточнить что означает самый банальный "common interface". Я не прав7
Можно пойти дальше по википедии к определению interface, а значение common посмотреть в справочнике, т.к. википедия на "common interface" предлагает статью о девайсе в телевизоре.
Здравствуйте, Vaako, Вы писали:
V>Здравствуйте, samius, Вы писали:
V>>>Хотя постойте, можно ведь все функции переделать добавив два новых аргумента foo(A* thisA, B* thisB, …. ). S>>разве что диспетчеризацию надо будет делать руками
V>Да можно, как и перегрузку без полиморфизма, поскольку это разные механизмы вообще.
Перегрузка — частный случай полиморфизма, потому использовать перегрузку без полиморфизма не получится.
V>Вопрос же заключается, почему опыт программиста подсказывает использовать совершенно разные механизмы для практически очень похожих задач.
Может быть потому что программист может анализировать, какой механизм подойдет лучше в конкретном случае? Причем тут название концепции? Программист ведь может использовать и совершенно одинаковые механизмы для очень различных задач.
V>Вы же не собираетесь переименовать перегрузку в "примитивный полиморфизм"?
не собираюсь.
Здравствуйте, samius, Вы писали:
V>>Это один к одному определение перегрузки функций, особенно если переводить "one common interface" как разные сигнатуры у функций. Очевидно упоминание "перегрузка функций — это один из самых банальных способов реализации полиморфизма" тут как раз к месту. S>Перегрузка функций — не самый банальный способ реализации полиморфизма. Есть еще банальнее: арифметические операторы в ЯП, как правило, являются полиморфными, даже в тех ЯП, которые не позволяют перегрузку операторов или даже функции как таковые.
V>>Осталось только уточнить что означает самый банальный "common interface". Я не прав7 S>Можно пойти дальше по википедии к определению interface, а значение common посмотреть в справочнике, т.к. википедия на "common interface" предлагает статью о девайсе в телевизоре.
Так можно заблудиться и не вернутся.
Ещё в 1960-х гг. Р. Хиндли (Roger Hindley) исследовал типизацию в комбинаторной логике. Его проблемной областью была типизация в языках, основанных на теории лямбда-исчисления. Позднее, в конце 1960-х годов, тот же учёный исследовал полиморфные системы типов. Позже, в 1970-х годах, Робин Милнер предложил практическую реализацию расширенной системы полиморфной типизации для языка функционального программирования ML.
Так что говоря о полиморфизме вы подразумеваете полиморфные типы, а в общем математическом смысле полиморфизм не реализован ни в одном языке программирования. Кроме того, математический полиморфизм не покрывает всех возможностей обобщений естественного языка, так что либо использовать точные термины и уточнять о каком именно полиморфизме речь, либо признать что полиморфность человеческого мышления пока остается вне математический определений. А так как вы делать и то и другое я не могу.
Здравствуйте, Vaako, Вы писали:
V>Здравствуйте, samius, Вы писали:
V>Так что говоря о полиморфизме вы подразумеваете полиморфные типы
Полиморфные системы типов — знаю. А что такое полиморфные типы — нет.
V>а в общем математическом смысле полиморфизм не реализован ни в одном языке программирования.
А какой у полиморфизма общий математический смысл? Ну это так, для общего развития. Ведь полиморфизм в компьютерном смысле очень даже реализован в куче языков программирования.
V>Кроме того, математический полиморфизм не покрывает всех возможностей обобщений естественного языка
Я не специалист в области естественных языков, это со мной можно не обсуждать.
Здравствуйте, samius, Вы писали:
S>Здравствуйте, Vaako, Вы писали:
V>>Здравствуйте, samius, Вы писали:
V>>>>Хотя постойте, можно ведь все функции переделать добавив два новых аргумента foo(A* thisA, B* thisB, …. ). S>>>разве что диспетчеризацию надо будет делать руками
V>>Да можно, как и перегрузку без полиморфизма, поскольку это разные механизмы вообще. S>Перегрузка — частный случай полиморфизма, потому использовать перегрузку без полиморфизма не получится.
V>>Вопрос же заключается, почему опыт программиста подсказывает использовать совершенно разные механизмы для практически очень похожих задач. S>Может быть потому что программист может анализировать, какой механизм подойдет лучше в конкретном случае? Причем тут название концепции? Программист ведь может использовать и совершенно одинаковые механизмы для очень различных задач.
Так я же и говорю, мыслить разные объекты одинаково не означает использовать полиморфизм в какой-то конкретной реализации, даже в самом самом общем математическом смысле. Программист вынужден спуститься на землю и применить известные ему технические приемы, возможно не имеющие к полиморфизму классов никакого отношения. Полиморфизм в мышлении нужен для рассуждений, а в программировании — для представления программы в конечном виде. Потому это разные вещи и для разных целей.
V>>Вы же не собираетесь переименовать перегрузку в "примитивный полиморфизм"? S>не собираюсь.
Но в первом предложении применили. Ваш полиморфизм в общем случае не охватывает всей гибкости человеческого мышления. Потому нет никакого смысла продолжать, сразу можно свести все к 4 принципам Фоннеймана и спорить о них. Что весть полиморфизм во всех языках программирования выходит за рамки этих 4 принципов? Я думаю нет, а значит и спорить вроде как не очем больше. И терминов меньше
Здравствуйте, samius, Вы писали:
S>Здравствуйте, Vaako, Вы писали:
V>>Здравствуйте, samius, Вы писали:
V>>Так что говоря о полиморфизме вы подразумеваете полиморфные типы S>Полиморфные системы типов — знаю. А что такое полиморфные типы — нет.
V>>а в общем математическом смысле полиморфизм не реализован ни в одном языке программирования. S>А какой у полиморфизма общий математический смысл? Ну это так, для общего развития. Ведь полиморфизм в компьютерном смысле очень даже реализован в куче языков программирования.
V>>Кроме того, математический полиморфизм не покрывает всех возможностей обобщений естественного языка S>Я не специалист в области естественных языков, это со мной можно не обсуждать.
Согласен, обсуждение должно основываться на обмене мнениями, а скептицизм одного по отношению к мнению другого обсуждением являться не может по определению.
Здравствуйте, Vaako, Вы писали:
V>Здравствуйте, samius, Вы писали:
V>>>Вопрос же заключается, почему опыт программиста подсказывает использовать совершенно разные механизмы для практически очень похожих задач. S>>Может быть потому что программист может анализировать, какой механизм подойдет лучше в конкретном случае? Причем тут название концепции? Программист ведь может использовать и совершенно одинаковые механизмы для очень различных задач.
V>Так я же и говорю, мыслить разные объекты одинаково не означает использовать полиморфизм в какой-то конкретной реализации, даже в самом самом общем математическом смысле.
Что подразумевать под "мыслить разные объекты одинаково"? Что за математический смысл? Он отличается от того что описано в википедии? Если да, то я о нем не знаю и рассуждать об этом не спешу.
V>Программист вынужден спуститься на землю и применить известные ему технические приемы, возможно не имеющие к полиморфизму классов никакого отношения. Полиморфизм в мышлении нужен для рассуждений, а в программировании — для представления программы в конечном виде. Потому это разные вещи и для разных целей.
Это имеет какое-то отношение к тому что перегрузка есть полиморфизм?
V>>>Вы же не собираетесь переименовать перегрузку в "примитивный полиморфизм"? S>>не собираюсь.
V>Но в первом предложении применили.
Я сказал: перегрузка — это частный случай полиморфизма. Есть возражения по сути?
V>Ваш полиморфизм в общем случае не охватывает всей гибкости человеческого мышления.
Не собираюсь рассуждать о гибкости человеческого мышления, спасении вселенной и т.п.
Здравствуйте, Vaako, Вы писали:
V>Здравствуйте, samius, Вы писали:
V>>>Так что говоря о полиморфизме вы подразумеваете полиморфные типы S>>Полиморфные системы типов — знаю. А что такое полиморфные типы — нет.
Что такое полиморфные типы?
V>>>а в общем математическом смысле полиморфизм не реализован ни в одном языке программирования. S>>А какой у полиморфизма общий математический смысл? Ну это так, для общего развития. Ведь полиморфизм в компьютерном смысле очень даже реализован в куче языков программирования.
Так что по поводу общего математического смысла?
V>>>Кроме того, математический полиморфизм не покрывает всех возможностей обобщений естественного языка S>>Я не специалист в области естественных языков, это со мной можно не обсуждать.
V>Согласен, обсуждение должно основываться на обмене мнениями, а скептицизм одного по отношению к мнению другого обсуждением являться не может по определению.
Дальнейший обмен мнениями невозможен без уточнения терминов "полиморфный тип", "общий математический смысл полиморфизма".
EOH>>Здесь описан частный случай одной из реализаций полиморфизма для конкретного языка. Автор забыл упомянуть, что это частный случай реализации — такое бывает, википедия, увы, несовершенна. V>Но как только кто либо упоминает "Полиморфизм" это сразу подразумевает и "наследование", поскольку это сильно связанные понятия.
Боюсь, это не так. Наследование — это прежде всего один из способов композиции, при котором общее для нескольких фрагментов кода поведение выносится в иерархию "родительских классво". Да, в большинстве языков механизм наследования включает в себя также механизм для реализации полиморфизма времени исполнения — переопределение функций и/или интерфейсы. Но поддржка переопределения методов — это только малая часть механики наследования. А понятия у нас все сильно связанные — область такая. Многие вон, говорят "процессор" — а подразумевают "системный блок". Но это не повод утверждать что "одно и то же, потому что сильно связанные понятия".
V>http://ru.wikipedia.org/wiki/%D0%9D%D0%B0%D1%81%D0%BB%D0%B5%D0%B4%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%28%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5%29 V>Насле́дование — механизм объектно-ориентированного программирования (наряду с инкапсуляцией, полиморфизмом и абстракцией), позволяющий описать новый класс на основе уже существующего (родительского), при этом свойства и функциональность родительского класса заимствуются новым классом. V> V>Другими словами "Полиморфизм" не является отдельным независимым понятием или концепцией как перегрузка функций.
В упор не вижу как из приведенной фразы следует, что полиморфизм не является независимым понятием. Перегрузка (overload) функции на числовой и строковый аргумент, как в моем примере — типичный полиморфизм времени компиляции, это в любом учебники написано. В википедии тоже — ниже по топику ссылки приводили. Обратите внимание — обычные функции, никаких классов, и, тем более, наследования.
V>Даже если мы применяем "Полиморфизм" применительно к функциям, а не классам. Технически это совершенно разные механизмы и могут быть совмещены в одном и том же классе. Перегрузка начинается и заканчивается на этапе компиляции производя поиск и выбор одной функции из множества. Полиморфизм не требует никакого поиска или выбора, поскольку компилятор вставляет сразу либо конкретную функцию, либо блок вызывающий функцию через таблицу виртуальных функций, либо блок осуществляющий поиск нужной функции при множественном наследовании. Эти и другие механизмы срабатывают во время исполнения, а не компиляции.
У меня крепнет подозрение что вы все же путаете полиморфизм и переопределение методов (override). То что вы пишете про таблицы виртуальных функций — это частный случай реализации переопределения методов для C++, который в свою очередь используется для организации полиморфизма времени исполнения. Но, хочу вас огорчить — в COM и GLib то же самое реализвано на чистом C, без классов и наследования.
V>Следовательно, в первом приближении, если опыт подсказывает, что полиморфизм скорее перегрузка, то, либо опыт не заслуживает доверия, либо программист сам не понимает что говорит. Сравнивать полиморфизм с перегрузкой все равно что сравнивать коров с заборами. Хотя переход к точным формулировкам если и разрешит путаницу, но, имхо, из=за своего математически-подобной формулировки, прививающий математический способ мышления, плохо отражает естественное мышление программиста.
В первом приближении мы оперируем понятиями, которые кто-то сформулировал и затемсформулированое было признано общественностью. Так вот мы, программисты, когда говорим про полиморфизм, оперируем вот этим: http://en.wikipedia.org/wiki/Polymorphism_(computer_science)
То же самое написано во всех учебниках по computer science, начиная от SICP и заканчивая "The Art of Computer Programming".
А чем оперируете вы я в упор не понимаю — какие-то вырванные из контекста фрагменты из русской википедии.
V>Например, все математические рассуждения без исключения исследуют только такие объекты, которые не меняются во время этого самого рассуждения. В математике правила рассуждения заданы в исходных предпосылках и аксиомах и не меняются на протяжении рассуждений. Программист же работает с постоянно меняющейся программой. В любом случае упоминание полиморфизма подразумевает и требует упоминание наследования, инкапсуляции и абстракции.
Если я вам скажу, что полиморфизм можно реализовать не только с помощью наследования и классов, но и с помощью шаблонов — вас это убедит?
V>С другой стороны, психологам известна интересная особенность естественного мышления, которую пока не удалось представить строго математически. Мышлению присуща способность выделить в рассуждении некоторой объект Х и заменить его на использование объекта Y с совершенно другими свойствами. Возможно это имеет какое-то отношение к единообразному манипулировнию совершенно разными объектами. Тогда неправ я и программист хотел сказать, что перегрузка и полиморфизм хотя и являются разными механизмами но вместе отражают эту странную способность человеческого мышления. Но достаточно ли в таком случае только перегрузки и полиморфизма? Я бы сказал в самом сложном случае перегрузка и полиморфизм преследуют одинаковую цель, и эта цель не выражается ни одним из них ни каким-либо другим механизмом или принципом, даже математической формулировки не имеет. Тогда да действительно не было никакого смысла в точных формулировках.
Перегрузка — это один из механизмов реализации полиморфизма. Другие механизмы — переопределение, шаблоны, dynamic dispatch и много чего еще.
Здравствуйте, samius, Вы писали:
V>>Но в первом предложении применили. S>Я сказал: перегрузка — это частный случай полиморфизма. Есть возражения по сути?
Здравствуйте, Eye of Hell, Вы писали:
EOH>>>Здесь описан частный случай одной из реализаций полиморфизма для конкретного языка. Автор забыл упомянуть, что это частный случай реализации — такое бывает, википедия, увы, несовершенна. V>>Но как только кто либо упоминает "Полиморфизм" это сразу подразумевает и "наследование", поскольку это сильно связанные понятия.
EOH>Боюсь, это не так. Наследование — это прежде всего один из способов композиции, при котором общее для нескольких фрагментов кода поведение выносится в иерархию "родительских классво". Да, в большинстве языков механизм наследования включает в себя также механизм для реализации полиморфизма времени исполнения — переопределение функций и/или интерфейсы. Но поддржка переопределения методов — это только малая часть механики наследования. А понятия у нас все сильно связанные — область такая. Многие вон, говорят "процессор" — а подразумевают "системный блок". Но это не повод утверждать что "одно и то же, потому что сильно связанные понятия".
V>>http://ru.wikipedia.org/wiki/%D0%9D%D0%B0%D1%81%D0%BB%D0%B5%D0%B4%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%28%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5%29 V>>Насле́дование — механизм объектно-ориентированного программирования (наряду с инкапсуляцией, полиморфизмом и абстракцией), позволяющий описать новый класс на основе уже существующего (родительского), при этом свойства и функциональность родительского класса заимствуются новым классом. V>> V>>Другими словами "Полиморфизм" не является отдельным независимым понятием или концепцией как перегрузка функций.
EOH>В упор не вижу как из приведенной фразы следует, что полиморфизм не является независимым понятием. Перегрузка (overload) функции на числовой и строковый аргумент, как в моем примере — типичный полиморфизм времени компиляции, это в любом учебники написано. В википедии тоже — ниже по топику ссылки приводили. Обратите внимание — обычные функции, никаких классов, и, тем более, наследования.
V>>Даже если мы применяем "Полиморфизм" применительно к функциям, а не классам. Технически это совершенно разные механизмы и могут быть совмещены в одном и том же классе. Перегрузка начинается и заканчивается на этапе компиляции производя поиск и выбор одной функции из множества. Полиморфизм не требует никакого поиска или выбора, поскольку компилятор вставляет сразу либо конкретную функцию, либо блок вызывающий функцию через таблицу виртуальных функций, либо блок осуществляющий поиск нужной функции при множественном наследовании. Эти и другие механизмы срабатывают во время исполнения, а не компиляции.
EOH>У меня крепнет подозрение что вы все же путаете полиморфизм и переопределение методов (override). То что вы пишете про таблицы виртуальных функций — это частный случай реализации переопределения методов для C++, который в свою очередь используется для организации полиморфизма времени исполнения. Но, хочу вас огорчить — в COM и GLib то же самое реализвано на чистом C, без классов и наследования.
V>>Следовательно, в первом приближении, если опыт подсказывает, что полиморфизм скорее перегрузка, то, либо опыт не заслуживает доверия, либо программист сам не понимает что говорит. Сравнивать полиморфизм с перегрузкой все равно что сравнивать коров с заборами. Хотя переход к точным формулировкам если и разрешит путаницу, но, имхо, из=за своего математически-подобной формулировки, прививающий математический способ мышления, плохо отражает естественное мышление программиста.
EOH>В первом приближении мы оперируем понятиями, которые кто-то сформулировал и затемсформулированое было признано общественностью. Так вот мы, программисты, когда говорим про полиморфизм, оперируем вот этим: EOH>http://en.wikipedia.org/wiki/Polymorphism_(computer_science) EOH>То же самое написано во всех учебниках по computer science, начиная от SICP и заканчивая "The Art of Computer Programming". EOH>А чем оперируете вы я в упор не понимаю — какие-то вырванные из контекста фрагменты из русской википедии.
V>>Например, все математические рассуждения без исключения исследуют только такие объекты, которые не меняются во время этого самого рассуждения. В математике правила рассуждения заданы в исходных предпосылках и аксиомах и не меняются на протяжении рассуждений. Программист же работает с постоянно меняющейся программой. В любом случае упоминание полиморфизма подразумевает и требует упоминание наследования, инкапсуляции и абстракции.
EOH>Если я вам скажу, что полиморфизм можно реализовать не только с помощью наследования и классов, но и с помощью шаблонов — вас это убедит?
V>>С другой стороны, психологам известна интересная особенность естественного мышления, которую пока не удалось представить строго математически. Мышлению присуща способность выделить в рассуждении некоторой объект Х и заменить его на использование объекта Y с совершенно другими свойствами. Возможно это имеет какое-то отношение к единообразному манипулировнию совершенно разными объектами. Тогда неправ я и программист хотел сказать, что перегрузка и полиморфизм хотя и являются разными механизмами но вместе отражают эту странную способность человеческого мышления. Но достаточно ли в таком случае только перегрузки и полиморфизма? Я бы сказал в самом сложном случае перегрузка и полиморфизм преследуют одинаковую цель, и эта цель не выражается ни одним из них ни каким-либо другим механизмом или принципом, даже математической формулировки не имеет. Тогда да действительно не было никакого смысла в точных формулировках.
EOH>Перегрузка — это один из механизмов реализации полиморфизма. Другие механизмы — переопределение, шаблоны, dynamic dispatch и много чего еще.
Ладно уламали. Но в СОМ есть наследование интерфейсов, нету наследования реализаций.
Почему тогда вы сами признались что перегрузка и полиморфизм должны быть разными вещами? Не потому ли что такие общие понятия как полиморфизм во всех своих проявлениях не имеют для программиста практической пользы? Программисту нужно знать какой именно полиморфизм используется в каждом конкретном случае. Это же кошмар просто чтобы компилятор сам решал какой именно вариант полиморфизма должен использоваться Ad-hoc, Parametric или Subtype polymorphism. Вот даже разные названия придумали для специфических частных случаев. Значит нельзя говорить о пользе полиморфизма в программировании вообще в самом общем смысле. Каждая разновидность полиморфизма полезна по своему применяется в разных случаях, должна явно разграничиваться синтаксически и иметь свои достоинства и недостатки. А это подводит нас к вопросу охватывают ли все известные варианты полиморфизма полностью то, что сам программист называет "мыслить разные объекты единообразно"?
There are several fundamentally different kinds of polymorphism
то получается нельзя путать разные варианты полиморфизма между собой. Т.е. нельзя говорить, что Ad-hoc polymorphism является упрощенным вариантом Subtype polymorphism. Это математически некорректно, как и упоминание полиморфизма вообще без конкретизации по его контексту
Есть разные полиморфизмы. А программист мысля разные объекты единообразно должен еще сообразить как запихнуть свое единообразное мышление в программу с помощью того, этого или другого полиморфизма. Или ну его вообще этот полиморфизм который так галимо отражает наше естественное мышление
Кстати полиморфные типы википедии известны. Правда не вы о них спрашивали, но вам отвечать приятнее
V>Ладно уламали. Но в СОМ есть наследование интерфейсов, нету наследования реализаций.
В целом рад, что мои теоретические знания достаточны, чтобы аргументированно доказать свою позицию .
V>Почему тогда вы сами признались что перегрузка и полиморфизм должны быть разными вещами? Не потому ли что такие общие понятия как полиморфизм во всех своих проявлениях не имеют для программиста практической пользы? Программисту нужно знать какой именно полиморфизм используется в каждом конкретном случае. Это же кошмар просто чтобы компилятор сам решал какой именно вариант полиморфизма должен использоваться Ad-hoc, Parametric или Subtype polymorphism. Вот даже разные названия придумали для специфических частных случаев. Значит нельзя говорить о пользе полиморфизма в программировании вообще в самом общем смысле. Каждая разновидность полиморфизма полезна по своему применяется в разных случаях, должна явно разграничиваться синтаксически и иметь свои достоинства и недостатки. А это подводит нас к вопросу охватывают ли все известные варианты полиморфизма полностью то, что сам программист называет "мыслить разные объекты единообразно"?
На мой профессиональный взгляд, понимание общих понятий позволяет лучше определить что, как и когда применять. Понимание того, что полиморфизм — это когда один и тот же код работает над разными данными — позволяет программисту чуть лучше писать программы. Я считаю, что чем лучше программист понимает почему и зачем в языках программирования и платформах какие-то фичи реализованые каким-то способом — тем лучше у него получаются программы. Да, для клепания формочек не обязательно знать чем "expression" отличается от "statement" и что такое "expression statement". Для практического применения достаточно знаний вида "эта хренька вот в эу хреновину, и — хоп!". Но мы ведь стремимся к лучшему?
V>то получается нельзя путать разные варианты полиморфизма между собой. Т.е. нельзя говорить, что Ad-hoc polymorphism является упрощенным вариантом Subtype polymorphism. Это математически некорректно, как и упоминание полиморфизма вообще без конкретизации по его контексту
Полиморфизм вообще — это возможность выполнять одну и ту же операцию над разными данными. Достаточно высокоуровневое определение, которое позволяет ответить на вопрос "когда и зачем применять эту штуку". А конкретных реализаций очень много.
V>Есть разные полиморфизмы. А программист мысля разные объекты единообразно должен еще сообразить как запихнуть свое единообразное мышление в программу с помощью того, этого или другого полиморфизма. Или ну его вообще этот полиморфизм который так галимо отражает наше естественное мышление
Программирование само по себе — это перевод с человеческого языка на компьютерный. Как только мы сможем общаться с компьютером без переводчика — программирование исчезнет как класс.
V>Кстати полиморфные типы википедии известны. Правда не вы о них спрашивали, но вам отвечать приятнее
Здравствуйте, Eye of Hell, Вы писали:
V>>то получается нельзя путать разные варианты полиморфизма между собой. Т.е. нельзя говорить, что Ad-hoc polymorphism является упрощенным вариантом Subtype polymorphism. Это математически некорректно, как и упоминание полиморфизма вообще без конкретизации по его контексту EOH>Полиморфизм вообще — это возможность выполнять одну и ту же операцию над разными данными. Достаточно высокоуровневое определение, которое позволяет ответить на вопрос "когда и зачем применять эту штуку". А конкретных реализаций очень много.
Наверно всетаки если бы параметризация была разновидностью Subtype polymorphism то это так бы и описали, но у математиков есть привычка называть объекты принципиально разными если их определения практически не отличаются друг от друга. Вы же не скажите, что Ad-hoc polymorphism во всех самых сложных ситуациях является не более чем Subtype polymorphism в каждом простом случае. Если бы это было так. то механизмы поддерживающие эти концепции в языках программирования были бы одними и теми же, а это не так. Нельзя забывать, например, что объединение разных концепций под одним названием "Полиморфизм" не является таким простым действием как нам бы того хотелось. Напомню историю с классификацией простых конечных групп :
В 1970-е годы более сотни специалистов по теории групп образовали своеобразный консорциум, целью которого было представить полную классификацию простых конечных групп.
...
Но даже если проект увенчается исчерпывающим итоговым докладом, в мире, наверное, не найдется и десяти математиков, которые будут вправе утверждать, что они понимают хотя бы основные линии многотомного доказательства.
V>>Есть разные полиморфизмы. А программист мысля разные объекты единообразно должен еще сообразить как запихнуть свое единообразное мышление в программу с помощью того, этого или другого полиморфизма. Или ну его вообще этот полиморфизм который так галимо отражает наше естественное мышление EOH>Программирование само по себе — это перевод с человеческого языка на компьютерный. Как только мы сможем общаться с компьютером без переводчика — программирование исчезнет как класс.
Я усиленно предлагал вам иную точку зрения, когда программирование является рассуждением программиста о программе, а описание программы на естественном языке не более чем состояние этого процесса в определенный момент времени. То есть в разные моменты времени описания различны и различие принципиальное и не устранимое. Потому умение переводить с с естественного языка не заменяет, собственно, программирования .
Хочу сказать что программисту важнее знание механизмов чем математическое обоснование, когда программист думает про Ad-hoc polymorphism он учитывает правила преобразования типов и ограничения связанные с этим, когда программист думает про Subtype polymorphism он учитывает иерархию типов, ведь не любые два классы должны удовлетворять требованиям полиморфизма, когда программист думает про Parametric polymorphism то он должен помнить про нюансы value и reference типов. Значит опыт должен научить программиста воспринимать перегрузку и полиморфизм классов как совершенно разные задачи сопровождающиеся очень разными размышлениями. Даже в том случае если с математической точки зрения это все подвиды одного и того же математичексого понятия.
Не стоит забывать что довольно долгое время программисты и ученые верили в невозможность того, что компьютер может допустить ошибку — там же математическое обеспечение, а в математике нет и не может быть ошибок. Разве что случится катаклизм и логический элемент выдаст 2+2=5 ! Теперь же математическое обеспечение переименовали в программное обеспечение и не возражают против присутствие хотябы одной ошибки в любой программе . Несмотря на то что компиляторы основаны на сложных математический теориях они реализуют лишь конкретный частный случай этих теорий. Потому не стоит упрощать полиморфизм в программировании до полиморфизма в строгом математическом смысле. Это чревато заблуждениями и явными теоретическими ошибками.
И опыт будет говорить программисту со стажем, что это совершенно разные вещи несмотря на одинаковость математического определения. Как и получалось у вас А теоретическая подготовка будет говорить обратное — хоть убейся но нет принципиального отличия в определениях. Так же как и у вас но в другом посте
Здравствуйте, m e, Вы писали:
V>> Или ну его вообще этот полиморфизм который так галимо отражает наше естественное мышление ME>а может ну его вообще это галимое программирование, а?
Здравствуйте, Vaako, Вы писали:
V>Здравствуйте, Eye of Hell, Вы писали:
V>Наверно всетаки если бы параметризация была разновидностью Subtype polymorphism то это так бы и описали, но у математиков есть привычка называть объекты принципиально разными если их определения практически не отличаются друг от друга. Вы же не скажите, что Ad-hoc polymorphism во всех самых сложных ситуациях является не более чем Subtype polymorphism в каждом простом случае.
Я вообще не понял, откуда взялось предложение считать Ad-hoc разновидностью Subtype-а. Вроде как это твои фантазии.
Странно, что ты это обсуждаешь сам с собой, цитируя при этом Eye of Hell-а.
V>Если бы это было так. то механизмы поддерживающие эти концепции в языках программирования были бы одними и теми же, а это не так.
Это не так. Да и с чего быть одинаковыми механизмам, если один вид полиморфизма выполняется во время компиляции, а другой во время выполнения?
V>Наверно всетаки если бы параметризация была разновидностью Subtype polymorphism то это так бы и описали, но у математиков есть привычка называть объекты принципиально разными если их определения практически не отличаются друг от друга. Вы же не скажите, что Ad-hoc polymorphism во всех самых сложных ситуациях является не более чем Subtype polymorphism в каждом простом случае. Если бы это было так. то механизмы поддерживающие эти концепции в языках программирования были бы одними и теми же, а это не так. Нельзя забывать, например, что объединение разных концепций под одним названием "Полиморфизм" не является таким простым действием как нам бы того хотелось. Напомню историю с классификацией простых конечных групп.
Увы, программирование — достаточно молодая область, и хорошей, выверенной веками классификации у нас пока нема. Работаем с тем что есть (c).
V>Хочу сказать что программисту важнее знание механизмов чем математическое обоснование, когда программист думает про Ad-hoc polymorphism он учитывает правила преобразования типов и ограничения связанные с этим, когда программист думает про Subtype polymorphism он учитывает иерархию типов, ведь не любые два классы должны удовлетворять требованиям полиморфизма, когда программист думает про Parametric polymorphism то он должен помнить про нюансы value и reference типов. Значит опыт должен научить программиста воспринимать перегрузку и полиморфизм классов как совершенно разные задачи сопровождающиеся очень разными размышлениями. Даже в том случае если с математической точки зрения это все подвиды одного и того же математичексого понятия.
Мне кажется, что вы упускаете один важный нюанс. Программист не сразу идет бороть наследование в C++. Вначале у него стоит задача — есть какой-то код и есть разные объекты, один код должен оперировать этими объектами. Зная, что это задача для полиморфизма и что этого полиморфизма есть много разного, программист пырится на ассортимент и выбирает что ему лучше использовать в данном конкретном случае: перегрузку метода, или общий интерфейс для объектов сделать, или наследовать их от общего предка, или реализовать алгорим шаблоном. На мой взгляд, именно это понимаение "нафига полиморфизм нужен вообще" позволяет адекватно выбрать способ решения текущей задачи.
V>И опыт будет говорить программисту со стажем, что это совершенно разные вещи несмотря на одинаковость математического определения. Как и получалось у вас А теоретическая подготовка будет говорить обратное — хоть убейся но нет принципиального отличия в определениях. Так же как и у вас но в другом посте
Баланс между чистой теорией определений и практикой реализаций тех или иных костылей в конкретных языках программирования — наше усе. Я за баланс — чтобы и теория была — общее так сказать понимание, и практика — где какие таблицы виртуальных функций используются и как виртуальная машина пеготает.
1. Ad-hoc полиморфизм и subtype-полиморфизм являются частным случаем Parametric полиморфизма.
это можно показать следующим образом: допустим, что мы можем выполнять произвольные алгоритмы над кодом во время компиляции (в C++ это, в частности, возможно, но правда не ко всем данным уровня компиляции при этом есть доступ), тогда при параметрическом полиморфизме возможен следующий код (где compile-if это условие которое проверяется на уровне компиляции):
//parametric polymorphism
TItem[] Concat<TCollection, T>(T[] items1, TCollection items2) where TCollection:IEnumerable<T>
{
var result = new List<T>();
compile-if (TCollection is ICollection<T>)
{
result.Capacity = items1.Length + items2.Count;
}
else
{
result.Capacity = items1.Length;
}
result.AddRange(items1);
compile-if (TCollection is Array<T>)
{
result.AddRange(items2);
}
else
{
foreach (var item in items2)
result.Add(item);
}
return result.ToArray();
}
применив теорию категорий, видим, что этот код дает три варианта перегруженной реализации функции Concat
//ad-hoc polymorphism
T[] Concat<T>(T[] items1, T[] items2)
{
var result = new List<T>();
result.Capacity = items1.Length + items2.Count;
result.AddRange(items1);
result.AddRange(items2);
return result.ToArray();
}
T[] Concat<T>(T[] items1, ICollection<T> items2)
{
var result = new List<T>();
result.Capacity = items1.Length + items2.Count;
result.AddRange(items1);
foreach (var item in items2)
result.Add(item);
return result.ToArray();
}
T[] Concat<T>(T[] items1, IEnumerable<T> items2)
{
var result = new List<TItem>();
result.AddRange(items1);
foreach (var item in items2)
result.Add(item);
return result;
}
2. Subtype полиморфизм является частным случаем параметрического полиморфизма, если компилятору разрешено самостоятельно добавлять методы в виртуальную таблицу типов.
и subtype-полиморфизм появляется, если тип конкретных данных известен не полностью на этапе компиляции.
это можно увидеть на следующим примере:
введем вспомогательные функции
int[] F1()
{
return new[]{1, 4, 5};
}
IEnumerable<int> F2()
{
for (int i = 0; i < 5; ++i)
yield return i;
}
в следующем коде вся информация известна на уровне компиляции о реальном типе коллекции, которые хранятся в f1 и f2, и поэтому можно выбрать нужный вариант Concat на уровне компиляции
var s = new int[]{4, 6, 7};
var f1 = F1();
var f2 = F2();
var x1 = Concat(s, f1);//здесь выбирается функция для Arrayvar x2 = Concat(s, f2);//здесь для IEnumerable
но в следующем коде, реальный тип коллекции, хранящейся в f — уже неопределен на уровне компиляции, и окончательно становится определенным только в рантайме:
var f = new Random().Next() > 0.5 ? F1() : F2();
var x = Concat(s, f);
и есть три варианта:
1. подставить общий худший вариант (в данном случае — Concat для IEnumerable), но это не обеспечивает максимальной производительности
2. сгенерить Concat с проверками уровня рантайма, это лучше, но появляются затраты на проверку if-а
T[] Concat_Enumerable_Or_Array<T>(T[] items1, IEnumerable<T> items2)
{
if (items2 is T[])
return Concat(items1, (T[])items2);
return Concat(items1, items2);
}
и вставить вызов этой функции
var x = Concat_Enumerable_Or_Array(s, f);
3. добавить виртуальный метод V_Concat(T[] items1) в таблицу всех классов наследованных от IEnumerable<T>
тогда в массив добавится метод
зы V> Это же кошмар просто чтобы компилятор сам решал какой именно вариант полиморфизма должен использоваться Ad-hoc, Parametric или Subtype polymorphism.
компилятору как раз просто выбрать подходящий вариант, и я надеюсь показал каким способом.
а вот для человека удержать в голове все эти нюансы — вот это действительно кошмар.
Здравствуйте, DarkGray, Вы писали:
DG>1. Ad-hoc полиморфизм и subtype-полиморфизм являются частным случаем Parametric полиморфизма.
Если заглянуть в определения, то выяснится что параметрический и ad-hoc полиморфизмы противостоят друг другу в том как используется код для разных типов. Параметрический использует в точности один и тот же код, а ad-hoc различный для разных типов. Потому ad-hoc не может быть частным случаем параметрического.
DG>это можно показать следующим образом: допустим, что мы можем выполнять произвольные алгоритмы над кодом во время компиляции (в C++ это, в частности, возможно, но правда не ко всем данным уровня компиляции при этом есть доступ), тогда при параметрическом полиморфизме возможен следующий код (где compile-if это условие которое проверяется на уровне компиляции):
Если ты применить разные алгоритмы к коду во время компиляции, то ты получишь разный код для разных случаев. А значит — ad-hoc.
DG>
DG>//parametric polymorphism
DG>TItem[] Concat<TCollection, T>(T[] items1, TCollection items2) where TCollection:IEnumerable<T>
DG>{
DG> var result = new List<T>();
DG> compile-if (TCollection is ICollection<T>)
DG>
твой compile-if — это фактически как специализация шаблона в C++ (if (is_collection<TCollection>()) с последующим выкидыванием компилятора веток if-а. Т.е. пример нельзя отнести к чистому параметрическому полиморфизму.
DG>применив теорию категорий, видим, что этот код дает три варианта перегруженной реализации функции Concat
Можно развернуть для тех кто в танке причем тут теория категорий?
DG>2. Subtype полиморфизм является частным случаем параметрического полиморфизма, если компилятору разрешено самостоятельно добавлять методы в виртуальную таблицу типов.
Subtype полиморфизм имеет отношение к параметрическому уже потому что типы заменимы подтипами (это безотносительно принципа LSP, т.е. никакого переопределения поведения здесь еще нет).
Однако, в рамках OOP языков говоря о subtype подразумевают возможность переопределения методов для подтипов. А это есть ничто иное, как специализация, или ad-hoc, с той лишь разницей, что работает в рантайме.
DG>>1. Ad-hoc полиморфизм и subtype-полиморфизм являются частным случаем Parametric полиморфизма. S>Если заглянуть в определения, то выяснится что параметрический и ad-hoc полиморфизмы противостоят друг другу в том как используется код для разных типов. Параметрический использует в точности один и тот же код, а ad-hoc различный для разных типов. Потому ad-hoc не может быть частным случаем параметрического.
ты опять хочешь поделить мир только на черное и белое.
List<T> использует параметрический или ad-hoc полиморфизм?
для List<Control> и List<File> используется один и тот же код, а вот для List<int> уже второй, а для List<double> третий.
такое явление как использование одного кода или разного для исполнения есть, но к делению на parametric/ad-hoc polymorphism он никакого отношения не имеет.
DG>>применив теорию категорий, видим, что этот код дает три варианта перегруженной реализации функции Concat S>Можно развернуть для тех кто в танке причем тут теория категорий?
разбиение множества на непересекающие множества в зависимости от отношений между элементами — как раз теория категорий и занимается.
DG>>>1. Ad-hoc полиморфизм и subtype-полиморфизм являются частным случаем Parametric полиморфизма. S>>Если заглянуть в определения, то выяснится что параметрический и ad-hoc полиморфизмы противостоят друг другу в том как используется код для разных типов. Параметрический использует в точности один и тот же код, а ad-hoc различный для разных типов. Потому ad-hoc не может быть частным случаем параметрического.
DG>ты опять хочешь поделить мир только на черное и белое.
Это ты хочешь всех запутать.
DG>List<T> использует параметрический или ad-hoc полиморфизм?
Параметрический. DG>для List<Control> и List<File> используется один и тот же код, а вот для List<int> уже второй, а для List<double> третий.
Один код. Как и для std::vector, который тоже является образцом параметрического полиморфизма.
DG>такое явление как использование одного кода или разного для исполнения есть, но к делению на parametric/ad-hoc polymorphism он никакого отношения не имеет.
Конечно же имеет.
Using parametric polymorphism, a function or a data type can be written generically so that it can handle values identically without depending on their type. Such functions and data types are called generic functions and generic datatypes respectively and form the basis of generic programming.
Сходи так же по ссылке на generic programming, увидишь там List<T>.
ad-hoc polymorphism is a kind of polymorphism in which polymorphic functions can be applied to arguments of different types, because a polymorphic function can denote a number of distinct and potentially heterogeneous implementations depending on the type of argument(s) to which it is applied.
...
This is in contrast to parametric polymorphism, in which polymorphic functions are written without mention of any specific type, and can thus apply a single abstract implementation to any number of types in a transparent way. This classification was introduced by Christopher Strachey in 1967.
Обрати так же внимание, что эта классификация была введена в 67-м году и не нуждается в переизобретении 55 лет спустя.
DG>>>применив теорию категорий, видим, что этот код дает три варианта перегруженной реализации функции Concat S>>Можно развернуть для тех кто в танке причем тут теория категорий?
DG>разбиение множества на непересекающие множества в зависимости от отношений между элементами — как раз теория категорий и занимается.
Меня интересует, как именно ты применил теорию категорий, что конкретно из нее. Я просто подозреваю что ты применил не теорию категорий, а умное сочетание слов.
DG>>List<T> использует параметрический или ad-hoc полиморфизм? S>Параметрический. DG>>для List<Control> и List<File> используется один и тот же код, а вот для List<int> уже второй, а для List<double> третий. S>Один код.
ошибаешься
The interesting question is how does .NET compile the generic IL of the server to machine code. It turns out that the actual machine code produced depends on whether the specified types are value or reference type. If the client specifies a value type, then the JIT compiler replaces the generic type parameters in the IL with the specific value type, and compiles it to native code. However, the JIT compiler keeps track of type-specific server code it already generated. If the JIT compiler is asked to compile the generic server with a value type it has already compiled to machine code, it simply returns a reference to that server code. Because the JIT compiler uses the same value-type-specific server code in all further encounters, there is no code bloating.
If the client specifies a reference type, then the JIT compiler replaces the generic parameters in the server IL with Object, and compiles it into native code. That code will be used in any further request for a reference type instead of a generic type parameter. Note that this way the JIT compiler only reuses actual code. Instances are still allocated according to their size off the managed heap, and there is no casting.
S>Меня интересует, как именно ты применил теорию категорий, что конкретно из нее. Я просто подозреваю что ты применил не теорию категорий, а умное сочетание слов.
есть множество типов они связаны стрелкой is.
дальше есть стрелки:
IEnumerable<T> -> A
!IEnumerable<T> -> ()
ICollection<T> -> B
!ICollection<T> -> ()
Array<T> -> C1
!Array<T> -> C2
при этом A, B, C1, C2 независимые между собой элементы.
вопрос: насколько комбинаций A, B, C1, C2 множество типов разбивается, и какие они?
S>Сходи так же по ссылке на generic programming, увидишь там List<T>.
кроме знания теории необходимо ее еще уметь применять к практике.
в теории List<T> и std::vector<T> может быть и имеют один код, но в жестокой практике: List<T> в .net-е генерит разный код, а уж std::vector в C++ тем более.
Здравствуйте, DarkGray, Вы писали:
DG>The interesting question is how does .NET compile the generic IL of the server to machine code. It turns out that the actual machine code produced depends on whether the specified types are value or reference type.
DG>здесь тем более. C++ под каждый новый параметр шаблона генерит новый код.
Так речь же по идее должна идти об исходном коде, а не о том, что генерит компилятор. Он может хоть манную кашу генерить, на язык и систему типов это не влияет.
DG>>>List<T> использует параметрический или ad-hoc полиморфизм? S>>Параметрический. DG>>>для List<Control> и List<File> используется один и тот же код, а вот для List<int> уже второй, а для List<double> третий. S>>Один код.
DG>ошибаешься
DG>
DG>It turns out that the actual machine code produced depends on whether the specified types are value or reference type.
Т.е. ты решил соскочить с темы полиморфизма в языка программирования на полиморфизм инструкций исполнителя?
S>> Как и для std::vector, который тоже является образцом параметрического полиморфизма.
DG>здесь тем более. C++ под каждый новый параметр шаблона генерит новый код.
Генерит — да. Но контейнер написан без учета специальных знаний о типах. А значит параметрический.
Определение полиморфизма ведь не запрещает генерить разный код. Определение полиморфизма касается черт языка, а не черт генератора.
Здравствуйте, DarkGray, Вы писали:
S>>Меня интересует, как именно ты применил теорию категорий, что конкретно из нее. Я просто подозреваю что ты применил не теорию категорий, а умное сочетание слов.
DG>есть множество типов они связаны стрелкой is.
Что то мне подсказывает, что is не годится в качестве стрелки.
Здравствуйте, DarkGray, Вы писали:
S>>Сходи так же по ссылке на generic programming, увидишь там List<T>.
DG>кроме знания теории необходимо ее еще уметь применять к практике.
как ты?
DG>в теории List<T> и std::vector<T> может быть и имеют один код, но в жестокой практике: List<T> в .net-е генерит разный код, а уж std::vector в C++ тем более.
уже ответил.
DM>Так речь же по идее должна идти об исходном коде, а не о том, что генерит компилятор. Он может хоть манную кашу генерить, на язык и систему типов это не влияет.
что такое исходный код? и чем он отличается от не исходного?
вот это исходный код? он один или его много?
//parametric polymorphism
TItem[] Concat<TCollection, T>(T[] items1, TCollection items2) where TCollection:IEnumerable<T>
{
var result = new List<T>();
compile-if (TCollection is ICollection<T>)
{
result.Capacity = items1.Length + items2.Count;
}
else
{
result.Capacity = items1.Length;
}
result.AddRange(items1);
compile-if (TCollection is Array<T>)
{
result.AddRange(items2);
}
else
{
foreach (var item in items2)
result.Add(item);
}
return result.ToArray();
}
DM> на язык и систему типов это не влияет.
на какой язык? уровня компиляции? байт кода? маш кода? процессора?
опять же не влияет на систему типов уровня компиляции, виртуальной машины, процессора?
Здравствуйте, m e, Вы писали:
S>>Один код. Как и для std::vector, который тоже является образцом параметрического полиморфизма.
ME>немного не так
ME>на плюсах вообще нет чистого параметрического полиморфизма, а есть его эмуляция различной степени качественности
ME>gaperton когда писал свой знаменитый пост http://rsdn.ru/forum/philosophy/2853873.1.aspx
немного упростил ситуацию
ME>в частности, вектор из битов немного вываливается из стройной картины параметрического полиморфизма
да, согласен. Но мог бы и не вываливаться. Если std::vector<bool> вываливается через специализацию, то List<T> не вываливается совсем.
S>Но контейнер написан без учета специальных знаний о типах.
такое деление можно ввести. оно мало применимо на практике, но поиграться с ним можно.
тогда всякий полиморфизм можно разбить на две составляющие: parametric и ad-hoc.
функцию Concat можно представить как:
Здравствуйте, DarkGray, Вы писали:
S>>Но контейнер написан без учета специальных знаний о типах.
DG>такое деление можно ввести. оно мало применимо на практике, но поиграться с ним можно.
Ну-ну, 55 лет его очень мало применяли. Чаще наверное применяли твое деление Дашь ссылку на пример применения?
DG>тогда всякий полиморфизм можно разбить на две составляющие: parametric и ad-hoc.
Что значит всякий?
DG>функцию Concat можно представить как: DG>
DG>>>есть множество типов они связаны стрелкой is.
S>>Что то мне подсказывает, что is не годится в качестве стрелки.
DG>в честь чего это?
В честь определения категории
DG>>в честь чего это? S>В честь определения категории
вот и расскажи, почему множество типов не является малой категорией, а is не является стрелкой, хотя обоим аксиомам: ассоциативности и тождественности она удовлетворяет.
Здравствуйте, DarkGray, Вы писали:
DG>вот и расскажи, почему множество типов не является малой категорией, а is не является стрелкой, хотя обоим аксиомам: ассоциативности и тождественности она удовлетворяет.
Вообще-то я с теорией категорий не знаком. Но при поверхностном ознакомлении с базовыми концепциями вижу противоречие в выступлении is в качестве стрелки с unique-Type аксиомой, которая гласит
f: A -> B and f: A' -> B' => A = A' and B = B' // A Gentle Introduction to Category Theory
или
Each morphism f has a unique source object a and target object b where a and b are in ob(C).
S>Вообще-то я с теорией категорий не знаком. Но при поверхностном ознакомлении с базовыми концепциями вижу противоречие в выступлении is в качестве стрелки с unique-Type аксиомой, которая гласит
так очевидно, что в качестве конкретной стрелки из A в B берется не общий is, а каждый конкретный вариант A is B
S>>Вообще-то я с теорией категорий не знаком. Но при поверхностном ознакомлении с базовыми концепциями вижу противоречие в выступлении is в качестве стрелки с unique-Type аксиомой, которая гласит
DG>так очевидно, что в качестве конкретной стрелки из A в B берется не общий is, а каждый конкретный вариант A is B
Это не то что неочевидно, так еще я не понимаю, что это такое, конкретный вариант A is B.
Может ты о конкретно subtyping-е, так is это совершенно другое. К чему было is поминать?
S>Ad-hoc полиморфизм и subtype-полиморфизм являются частным случаем Parametric полиморфизма.
если запретить внутри parametric-полиморфизма делать вычисления уровня компиляции, то конечно не будет.
вот только такие запреты нужны только теоретикам, а на практике это нафиг не надо.
Здравствуйте, DarkGray, Вы писали:
S>>Это не то что неочевидно, так еще я не понимаю, что это такое, конкретный вариант A is B.
DG>A -> B есть A is B, или другими словами, из A в B есть стрелка, когда A is B == true DG>каждая такая стрелка (он же морфизм) имеет уникальные A и B.
У тебя другие слова обозначают совсем не то же самое, что A is B. Т.к. A is B это бинарное отношение.
S>>Ad-hoc полиморфизм и subtype-полиморфизм являются частным случаем Parametric полиморфизма.
DG>если запретить внутри parametric-полиморфизма делать вычисления уровня компиляции, то конечно не будет. DG>вот только такие запреты нужны только теоретикам, а на практике это нафиг не надо.
Причем тут вычисления уровня компиляции? Код ведь может и интерпретироваться в общем случае.
Речь идет о том, является ли твой код type-specific, или нет. Твой является, т.к. специальные типы обрабатывает специальным образом. Иными словами — ad-hoc.
DG>>если запретить внутри parametric-полиморфизма делать вычисления уровня компиляции, то конечно не будет. DG>>вот только такие запреты нужны только теоретикам, а на практике это нафиг не надо.
S>Причем тут вычисления уровня компиляции? Код ведь может и интерпретироваться в общем случае.
значит сначала будет интерпретироваться код над типами, а потом код над данными. в чем проблема?
S>Речь идет о том, является ли твой код type-specific, или нет.
необходимо обосновать уместность такого деления. а иначе это тоже самое, что целые числа поделить на числа меньше 3 и равных или больше 3, или там кратным 7 или не кратным, и т.д. это всё, конечно, верно и интересно, но практической ценности не представляет.
или другими словами: необходимо показать, что эти два класса обладают разными свойствами, и это можно использовать при решении тех или иных задач.
Здравствуйте, DarkGray, Вы писали:
S>>Речь идет о том, является ли твой код type-specific, или нет.
DG>необходимо обосновать уместность такого деления. а иначе это тоже самое, что целые числа поделить на числа меньше 3 и равных или больше 3, или там кратным 7 или не кратным, и т.д. это всё, конечно, верно и интересно, но практической ценности не представляет. DG>или другими словами: необходимо показать, что эти два класса обладают разными свойствами, и это можно использовать при решении тех или иных задач.
Твое деление отличается от общепринятого, ты и доказывай его полезность. А я тебе растолковываю то что написано в википедии.
S>У тебя другие слова обозначают совсем не то же самое, что A is B. Т.к. A is B это бинарное отношение.
мне кажется, что ты запутался в абстракциях.
вот есть множество типов Ts: (IEnumerable<T>, ICollection<T>, T[] и т.д.), поверх него определено бинарное отношение is, которое можно задать в табличном виде
IEnumerable<T> is IEnumerable<T> = true
ICollection<T> is IEnumerable<T> = true
T[] is IEnumerable<T> = true
IEnumerable<T> is ICollection<T> = false
ICollection<T> is ICollection<T> = true
T[] is ICollection<T> = true
IEnumerable<T> is T[] = false
ICollection<T> is T[] = false
T[] is T[] = true
это множество типов Ts и бинарное отношение is образует категорию C, где в качестве объектов берутся элементы множества Ts, а в качестве стрелок берутся true-шные строки из данной таблицы, что можно задать следующей таблицей:
S>Твое деление отличается от общепринятого, ты и доказывай его полезность. А я тебе растолковываю то что написано в википедии.
полезность я уже показывал ранее.
что на уровне описания кода можно обойтись одним parametric polymorphism-ом + код уровня компиляции, а всё остальное может сгенерить компилятор.
это упрощает жизнь программиста, не теряя при этом общности и эффективности при исполнении.
Здравствуйте, DarkGray, Вы писали:
S>>У тебя другие слова обозначают совсем не то же самое, что A is B. Т.к. A is B это бинарное отношение.
DG>мне кажется, что ты запутался в абстракциях.
DG>это множество типов Ts и бинарное отношение is образует категорию C, где в качестве объектов берутся элементы множества Ts, а в качестве стрелок берутся true-шные строки из данной таблицы, что можно задать следующей таблицей:
DG>соответственно, каждая строка является отдельным морфизмом(и объекты a и b сответственно уникальны) — о чем и шла речь ранее.
Я уже понял о чем речь, но протестую против того что бы is называть стрелкой. Строки таблицы называть стрелками — это допустимо.
S>>Твое деление отличается от общепринятого, ты и доказывай его полезность. А я тебе растолковываю то что написано в википедии.
DG>полезность я уже показывал ранее. DG>что на уровне описания кода можно обойтись одним parametric polymorphism-ом + код уровня компиляции, а всё остальное может сгенерить компилятор.
Ты показал что на уровне языка ты используешь ad-hoc полиморфизм и называешь его параметрическим.
DG>это упрощает жизнь программиста, не теряя при этом общности и эффективности при исполнении.
Твоя конструкция понятна и что-то подобное вовсю используется в C++ (если считать что if(is_collection<T>()) выкинется компилятором при специализации в { return false;}).
Беда в том, что ты перепутывашь терминологию и выдаешь это за какую-то пользу и упрощение жизни программиста. Специализация кода под типы всегда будет специализацией, будь то специализация шаблона или compile-if.
Перепутаешь ты что-то или нет, жизнь программистов от этого глобально не изменится. Но нафига путаница И твой пример необходимость этой путаницы не объясняет.
Здравствуйте, DarkGray, Вы писали:
DG>необходимо было сказать: DG>есть множество типов, они связаны набором стрелок, которые продуцируются true-подмножеством операции is.
DG>так?
точно
S>Беда в том, что ты перепутывашь терминологию и выдаешь это за какую-то пользу и упрощение жизни программиста. Специализация кода под типы всегда будет специализацией, будь то специализация шаблона или compile-if.
а числа делящиеся на 7 всегда будут числами делящимися на 7. и что из этого?
Здравствуйте, DarkGray, Вы писали:
S>>Беда в том, что ты перепутывашь терминологию и выдаешь это за какую-то пользу и упрощение жизни программиста. Специализация кода под типы всегда будет специализацией, будь то специализация шаблона или compile-if.
DG>а числа делящиеся на 7 всегда будут числами делящимися на 7. и что из этого?
Ничего, если не делать утверждения что числа, делящиеся на 7 есть частный случай чисел, делящихся на 3.
если не понятен пример с делением на 7, то можно взять понятие "указатель": и утверждение, что указатель всегда остается указателем.
вот только в современных языках — никто понятие "указатель" уже не использует, а используется лишь одно общее понятие ссылка. а с поинтерами разбираются только теоретики, и компиляторы где-то у себя внутри.
Здравствуйте, DarkGray, Вы писали:
DG>если не понятен пример с делением на 7, то можно взять понятие "указатель": и утверждение, что указатель всегда остается указателем.
DG>вот только в современных языках — никто понятие "указатель" уже не использует, а используется лишь одно общее понятие ссылка. а с поинтерами разбираются только теоретики, и компиляторы где-то у себя внутри.
Ты всплыл в этой теме с каким-то нелепым утверждением, которое подтверждаешь примером, который говорит о том что ты совершенно по-другому трактуешь категории полиморфизма, основываясь на кодогенерации и машинном коде.
Я попытался навести порядок.
В ответ получаю, что это все нормально, т.к. понятие "указатель" уже не используют.
Не используют и не используют. Зачем надо было влезать и использовать не так как все?
Уж лучше пойду посплю.
S> Зачем надо было влезать и использовать не так как все?
психология утверждает, что человеческое мышление часто ограничивается теми символами с помощью которых происходит общение.
соответственно, если человеку сказать, что вот были введены (условно) три различных полиморфизма: parametric, subtype и ad-hoc, то большинство будет мыслить, исходя из того, что эти полиморфизмы и в действительности являются различными, хотя это и не так.
в частности, человек перестает рассматривать варианты, когда одно и тоже можно представить с помощью разных полиморфизмов — ранее же сказали, что они различны, а значит такое представление невозможно.
Здравствуйте, DarkGray, Вы писали:
S>> Зачем надо было влезать и использовать не так как все?
DG>психология утверждает, что человеческое мышление часто ограничивается теми символами с помощью которых происходит общение. DG>соответственно, если человеку сказать, что вот были введены (условно) три различных полиморфизма: parametric, subtype и ad-hoc, то большинство будет мыслить, исходя из того, что эти полиморфизмы и в действительности являются различными, хотя это и не так.
Они действительно являются различными в том плане что обладают разными свойствами, что и описано в определениях.
DG>в частности, человек перестает рассматривать варианты, когда одно и тоже можно представить с помощью разных полиморфизмов — ранее же сказали, что они различны, а значит такое представление невозможно.
Предложением выше ты сказал что полиморфизмы в действительности не различаются, а в этом они у тебя снова разные.
Здравствуйте, DarkGray, Вы писали:
DM>>Так речь же по идее должна идти об исходном коде, а не о том, что генерит компилятор. Он может хоть манную кашу генерить, на язык и систему типов это не влияет.
DG>что такое исходный код? и чем он отличается от не исходного?
Есть некий язык, назовем его А. Есть его спецификация, определение, включающая в себя описание грамматики и семантики. Есть в нем система типов. Все эти вещи описаны людьми для людей, компилятора для языка может и вообще не существовать. Так вот, текст на этом языке (принадлежащий этому языку грамматически как минимум) — исходный код. А то, что производит некоторая программа (пусть и называемая компилятором), если оно не принадлежит описанному языку А, — не исходный код (на этом языке).
DG>вот это исходный код? он один или его много? ...
Если язык этого куска текста нигде не описан, то это не исходный код, это просто набор букв.
DM>> на язык и систему типов это не влияет.
DG>на какой язык? уровня компиляции? байт кода? маш кода? процессора?
Язык, данный нам спецификацией. Например, С++, Haskell, Shakespeare, Intercal... Байткод, машкод и пр. принадлежат уже совсем другим языкам. У этих языков могут быть совсем другие системы типов. Поэтому они в общем случае не влияют на систему типов языка, который в них компилируется.
Здравствуйте, Eye of Hell, Вы писали:
EOH>Увы, программирование — достаточно молодая область, и хорошей, выверенной веками классификации у нас пока нема. Работаем с тем что есть (c).
У меня подозрение, что дело не только в молодости. Фактически каждый программист интенсивно манипулирует разного рода абстракциями, понятиями и концепциями в своей практике так что время между созданием нового понятия, воплощением и выбрасыванием за ненадобностью в программировании самое короткое среди остальных областей интеллектуальной деятельности. В таком прессинге выживают только самые общие математические концепции.
EOH>Мне кажется, что вы упускаете один важный нюанс. Программист не сразу идет бороть наследование в C++. Вначале у него стоит задача — есть какой-то код и есть разные объекты, один код должен оперировать этими объектами. Зная, что это задача для полиморфизма и что этого полиморфизма есть много разного, программист пырится на ассортимент и выбирает что ему лучше использовать в данном конкретном случае: перегрузку метода, или общий интерфейс для объектов сделать, или наследовать их от общего предка, или реализовать алгорим шаблоном. На мой взгляд, именно это понимаение "нафига полиморфизм нужен вообще" позволяет адекватно выбрать способ решения текущей задачи.
Естественно без знания технических примочек никуда по поедешь, а без теории никуда не доедешь. Но не стоит переоценивать роль математики. Люблю цитировать Непейводу: Хаотическое управление
• Теория неформализуемых понятий
– Каждое действительно сложное и важное понятие активно сопротивляется формализации, порождая новую альтернативу, не учтенную ею
– Тем не менее эффективная деятельность возможна лишь на базе формализации понятий
– Необходимо четко понимать. что мы в огромном числе случаев формализуем неформализуемое.
– Любая формализация заводит в тупик, и тем быстрее и основательнее, чем более эффективна она на первых порах.
– Тупик образуется еще тогда, когда отказаться от формализации нет сил.
– Тупик становится намного труднее для выхода и основательнее, если с самого начала не позаботиться о том, чтобы осознать альтернативы существующей успешной формализации.
– Тупика можно избежать, если одновременно поддерживаются несколько несовместимых альтернатив.
EOH>Баланс между чистой теорией определений и практикой реализаций тех или иных костылей в конкретных языках программирования — наше усе. Я за баланс — чтобы и теория была — общее так сказать понимание, и практика — где какие таблицы виртуальных функций используются и как виртуальная машина пеготает.
Всетаки кроме практики и теории есть еще третий уровень как мне кажется. Я уже указывал на открытие многих приемов мышления которые пока ни в математике ни в программировании не получили отражения. Считаю что программист не думает в терминах объектов, программист просто думает об объектах и не более того. Объекты надо проектировать как и полиморфизм как и любые другие принципы ООП. Все они проектируются программистом, но не составляют суть и способ рассуждений программита и не имеют отношения к его способу мышления. Объекты, полиморфизм и все остальное это конечный итог рассуждений в процессе которых происходит проектирование с учетом многих тонкостей и нюансов. Программист не реализует в своей программе "полиморфизм вообще", он реализует вполне конкретный вид полиморфизма при условии что компилятор его поддерживает и это не конфликтует с остальными принимаемыми программистом решениями. Потому полиморфизм для программист это не более чем проектное решение, а значит полиморфизм в Дельфи нужно отличать от полиморфзма в C# даже если речь идет только про перегрузку функций.
Здравствуйте, samius, Вы писали:
S>Я вообще не понял, откуда взялось предложение считать Ad-hoc разновидностью Subtype-а. Вроде как это твои фантазии. S>Странно, что ты это обсуждаешь сам с собой, цитируя при этом Eye of Hell-а.
Да я такой
Но он отвечает как будто такое говорил — значит виновен по всем статьям
Здравствуйте, Vaako, Вы писали:
V>Программист не реализует в своей программе "полиморфизм вообще", он реализует вполне конкретный вид полиморфизма при условии что компилятор его поддерживает и это не конфликтует с остальными принимаемыми программистом решениями.
Полиморфизм — фича языка. Потому обычному программисту, который не занимается разработкой языка, сталкиваться с реализацией полиморфизма не приходится. Программист лишь использует полиморфизм, комбинирует различные его категории.
V>Потому полиморфизм для программист это не более чем проектное решение, а значит полиморфизм в Дельфи нужно отличать от полиморфзма в C# даже если речь идет только про перегрузку функций.
И чем же полиморфизм Дельфи отличается от полиморфизма в C# в отношении перегрузки функций?
DM>Есть некий язык, назовем его А. Есть его спецификация, определение, включающая в себя описание грамматики и семантики. Есть в нем система типов. Все эти вещи описаны людьми для людей, компилятора для языка может и вообще не существовать. Так вот, текст на этом языке (принадлежащий этому языку грамматически как минимум) — исходный код. А то, что производит некоторая программа (пусть и называемая компилятором), если оно не принадлежит описанному языку А, — не исходный код (на этом языке).
возьмем, твое же определение и препроцессор языка C++, и некий код C1
код C1 после обработки препроцессором превращается в код C2.
и код C1, и код C2 — являются кодом на языке C++.
из твоего же определения, выходит, что и C1 исходный код, и C2 — это тоже исходный код.
тоже самое можно сделать (и делается) с шаблонами, можно взять раскрыть шаблоны и получить код C3, который опять же будет записан на подмножестве языка C++.
в C# это еще более выражено, из-за того, что в нем много синтаксического сахара.
например, в нем явно расскрываются yield, foreach, using, extension-ы и т.д.
в итоге, это образует матрешку: С++ > C++(без инклюдов) > C++ (без макросов) > C++ (без макросов и без шаблонов) > С++ (без макросов и без шаблонов, без невиртуальных классов) и т.д.
при этом редуцируются как языковые конструкции, так и типы.
на определенном этапе, произойдет упор: например, из C++ нельзя выкинуть понятие виртуального объекта и vtable-а.
можно выкинуть конструкции, которые облегчают формирование vtable, но нельзя выкинуть само понятие vtable.
вот это означает, что мы натолкнулись на понятие уровня runtime-а для C++.
ps
рассматриваются только переходы, которые не ухудшают вычислительную сложность самой программы.
DM>>> на язык и систему типов это не влияет.
DG>>на какой язык? уровня компиляции? байт кода? маш кода? процессора?
DM>Язык, данный нам спецификацией. Например, С++, Haskell, Shakespeare, Intercal... Байткод, машкод и пр. принадлежат уже совсем другим языкам. У этих языков могут быть совсем другие системы типов. Поэтому они в общем случае не влияют на систему типов языка, который в них компилируется.
это тоже теория, а на практике не бывает, чтобы, например, int или float сильно отличались от int и float-а процессора, если нас, конечно, интересует практика (и в частности, вычислительная эффективность)
и кстати ATS должен быть дать понимание, что часть типов это чисто фишка компилятора, а часть переходит и в runtime.
соответственно, каждый реальный язык имеет, как минимум, два набора типов: уровня компиляции и уровня runtime-а.
DM>Если язык этого куска текста нигде не описан, то это не исходный код, это просто набор букв.
корректнее это утверждение формулируется как:
язык является языком — если есть алгоритм исполнения или/и алгоритм трансляции в более простой набор примитивов.
рассказать как вот это можно отранслировать в c#?
TItem[] Concat<TCollection, T>(T[] items1, TCollection items2) where TCollection:IEnumerable<T>
{
var result = new List<T>();
compile-if (TCollection is ICollection<T>)
{
Здравствуйте, DarkGray, Вы писали:
S>>Предложением выше ты сказал что полиморфизмы в действительности не различаются, а в этом они у тебя снова разные.
DG>утверждение, что свет одновременно и волна, и частица тебя, наверное, вообще должно на стуле переворачивать...
Так это двойственная природа света вдохновляет тебя городить фигню на форуме и не отвечать за нее?
DG>>кроме знания теории необходимо ее еще уметь применять к практике. S>как ты?
не, я теорий не знаю, я их только умею каждый раз заново сгенерить под конкретную задачу.
из-за того, что теории генеренные: с одной стороны — они лучше описывают конкретную задачу, с другой стороны — по понятиям и терминам они периодически не совпадают с классикой.
соответственно, с тобой, как с человеком, который достаточно хорошо знает классическую теорию, а так же требовательным к четкости терминологии, мне интересно что-то обсудить, пока я решаю задачу согласования своих понятий и терминов с классикой.
меня лишь расстраивает, что ряд сложных вещей (в частности, двойственность, неопределенность и т.д., топологию еще может быть) ты не знаешь, и не делаешь попыток понять что это такое, и зачем это надо.
DG>>>кроме знания теории необходимо ее еще уметь применять к практике. S>>как ты?
DG>не, я теорий не знаю, я их только умею каждый раз заново сгенерить под конкретную задачу. DG>из-за того, что теории генеренные: с одной стороны — они лучше описывают конкретную задачу, с другой стороны — по понятиям и терминам они периодически не совпадают с классикой.
Я так и предполагал. Спасибо за откровенность.
DG>соответственно, с тобой, как с человеком, который достаточно хорошо знает классическую теорию, а так же требовательным к четкости терминологии, мне интересно что-то обсудить, пока я решаю задачу согласования своих понятий и терминов с классикой.
Я не могу похвастаться хорошим знанием классической теории. Просто те вещи, которые ты пишешь интуитивно у меня в голове не укладываются. А когда я открываю википедию — то вижу что тобой написанное противоречит тому что в википедии, т.е. не только моим понятиям.
DG>меня лишь расстраивает, что ряд сложных вещей (в частности, двойственность, неопределенность и т.д., топологию еще может быть) ты не знаешь, и не делаешь попыток понять что это такое, и зачем это надо.
То, что мы обсуждаем не имеет никакой двойственности и неопределенности. Что бы в этом убедиться, достаточно заглянуть в википедию, и увидеть, например, что полиморфизм это фича ЯП а не исполнителя. Декларативность — это подход, а не свойство инструкций исполнителя. И т.п. Какая тут двойственность, неопределенность и может быть топология?
DG>>утверждение, что свет одновременно и волна, и частица тебя, наверное, вообще должно на стуле переворачивать... S>Так это двойственная природа света вдохновляет тебя городить фигню на форуме и не отвечать за нее?
вот смотри:
возьмем составное отношение F G, которое связывает два множества S и T.
дальше возьмем изоморфизм M над отношением F G, который переводит отношение F G в F1 G1(и обратно), при этом F1 G1 описывает такое же отношение S в T, как и исходное F G.
У отношения G при переходе к G1 часть свойств остается, а часть пропадает.
и соответственно, утверждается, что те свойства G, которые остаются при преобразовании являются существенными, а которые пропадают — не существенные, потому что с помощью изоморфизма M от них всегда можно избавиться.
например, в задачах связанных с реальностью такие свойства чисел, как делимость, "круглость" и т.д. часто не существенны, потому что такие задачи представимы как совокупность двух отношений: измерение(оцифровка) и задача-над-числами, при этом при измерении: точка отсчета, система счисления, единица измерения выбирается произвольно, и есть способ перейти от одного способа измерения к другому.
тоже самое и с кодом:
возьмем программу F которая переводит вход S в выход T.
и возьмем изоморфизм M, которые переводит программу F в программу F1 (и обратно), при этом F1 также преобразует S в T, как и исходный F.
часть свойств при переходе из F в F1 останется, часть пропадет.
те которые пропадают — они не существенные.
соответственно, я утверждаю, что деление полиморфизма на parametric, subtype и ad-hoc не существенно, потому что есть изоморфизмы, которые переводят одно в другое.
зы
на практике интересует изоморфизмы, которые не просто переводят S -> F -> T в аналогичный S -> F1 -> T, но и которые не ухудшают серьезно вычислительную сложность F1
соответственно, двойственность наличия свойства K (с одной стороны — оно есть, а с другой стороны — его нет) означает, что есть изоморфизм M, который преобразует код F со свойством K в код F1 без свойства K (и обратно)
Здравствуйте, DarkGray, Вы писали:
DG>рассказать как вот это можно отранслировать в c#?
Все-таки язык в котором реально существует аналог твоего "compile-if", а именно D с его static if
очень существенно от C# отличается в нем доступны такие возможности метапрограммирования,
которые в C# даже внешними препроцессорами тяжело достижимы и соответственно практические
приемы программирования на этих языках будут сильно отличатся.
FR>Все-таки язык в котором реально существует аналог твоего "compile-if", а именно D с его static if FR>очень существенно от C# отличается в нем доступны такие возможности метапрограммирования, FR>которые в C# даже внешними препроцессорами тяжело достижимы и соответственно практические FR>приемы программирования на этих языках будут сильно отличатся.
это потому что C# не полный в этом плане:
в нем нет возможности из параметрического полиморфизма вызвать ad-hoc полиморфизм.
также нет возможности задать параметры через "или".
в частности, на C# нельзя описать следующую конструкцию:
T Sum<T>(this IEnumerable<T> items) where T:int/double/string/decimal и т.д.
{
var res = Empty(T);
foreach (var item in items)
{
res = res + item;
}
return res;
}
FR>Все-таки язык в котором реально существует аналог твоего "compile-if"
кстати, я как раз утверждал обратное: что все эти деления на parametric, ad-hoc, subtype не существенны, если в языке есть возможность записать в произвольном месте произвольное условие над типами уровня компиляции.
Здравствуйте, DarkGray, Вы писали:
DG>кстати, я как раз утверждал обратное: что все эти деления на parametric, ad-hoc, subtype не существенны, если в языке есть возможность записать в произвольном месте произвольное условие над типами уровня компиляции.
D и есть такой язык.
Но я согласен с твоими оппонентами тебя заносит куда-то не туда.
Здравствуйте, DarkGray, Вы писали:
DG>возьмем, твое же определение и препроцессор языка C++, и некий код C1 DG>код C1 после обработки препроцессором превращается в код C2. DG>и код C1, и код C2 — являются кодом на языке C++. DG>из твоего же определения, выходит, что и C1 исходный код, и C2 — это тоже исходный код. ...
Да, с твоей цепочкой рассуждений я вполне согласен, только она ничего не меняет. Да, один и тот же логически код порой можно записать на одном языке по-разному, но на фичи системы типов это не влияет. Если какая-то фича в ней есть, то даже если можно то же самое выразить без нее, она все равно есть. Можно в C# раскрыть foraech и yield, но от этого язык их не потеряет, определение-то его не изменится. Если где-то можно один вид полиморфизма выразить через другой, первый вид не исчезнет.
DM>>>> на язык и систему типов это не влияет. DM>>Язык, данный нам спецификацией.
DG>это тоже теория, а на практике не бывает, чтобы, например, int или float сильно отличались от int и float-а процессора, если нас, конечно, интересует практика (и в частности, вычислительная эффективность)
Нет, в вопросах теории ЯП нас интересует теория.
DG>и кстати ATS должен быть дать понимание, что часть типов это чисто фишка компилятора, а часть переходит и в runtime. DG>соответственно, каждый реальный язык имеет, как минимум, два набора типов: уровня компиляции и уровня runtime-а.
Не стоит из отдельных примеров практики делать общие правила теории. Вот в Руби и Питоне где "набор типов уровня runtime"? Реальные языки.
Здравствуйте, DarkGray, Вы писали:
DM>>Если язык этого куска текста нигде не описан, то это не исходный код, это просто набор букв.
DG>корректнее это утверждение формулируется как: DG>язык является языком — если есть алгоритм исполнения или/и алгоритм трансляции в более простой набор примитивов.
Хочешь сказать, что для абсолютно любого языка всегда есть "более простой набор примитивов"? Это как минимум не доказано, не очевидно и контринтуитивно.
DG>рассказать как вот это можно отранслировать в c#?
Здравствуйте, DarkGray, Вы писали:
DG>это потому что C# не полный в этом плане: DG> в нем нет возможности из параметрического полиморфизма вызвать ad-hoc полиморфизм.
DG> также нет возможности задать параметры через "или".
А где есть?
DG>в частности, на C# нельзя описать следующую конструкцию: DG>
DG>T Sum<T>(this IEnumerable<T> items) where T:int/double/string/decimal и т.д.
DG>
Можно использовать subtype полиморфизм и передавать явно сумматор. Можно прийти к решению как с Comparer<T>.Default (Summator<T>.Default.Sum(a, b), где сумматоры для интересующих типов хардкодятся руками).
Решения есть, согласен что не слишком элегантные. Но ничего принципиально неразрешимого ты не назвал.
DG>>>утверждение, что свет одновременно и волна, и частица тебя, наверное, вообще должно на стуле переворачивать... S>>Так это двойственная природа света вдохновляет тебя городить фигню на форуме и не отвечать за нее?
DG>вот смотри: DG>возьмем составное отношение F G, которое связывает два множества S и T.
Давай разбираться. Под составным отношением ты подразумеваешь композицию отношений?
Если да, то не очень понятно. Допустим, FoG (o= композиция) определено на SxT (x — декартово произведение). Непонятно, где определены F и G, что их композиция стала определена на SxT.
DG>дальше возьмем изоморфизм M над отношением F G, который переводит отношение F G в F1 G1(и обратно), при этом F1 G1 описывает такое же отношение S в T, как и исходное F G.
не очень понимаю, о чем речь. Изоморфизм над отношением? Что есть объекты, что есть стрелки?
DG>У отношения G при переходе к G1 часть свойств остается, а часть пропадает.
О каких свойствах речь? DG>и соответственно, утверждается, что те свойства G, которые остаются при преобразовании являются существенными, а которые пропадают — не существенные, потому что с помощью изоморфизма M от них всегда можно избавиться.
Изоморфизм сохраняет структуру, если что.
DG>например, в задачах связанных с реальностью такие свойства чисел, как делимость, "круглость" и т.д. часто не существенны, потому что такие задачи представимы как совокупность двух отношений: измерение(оцифровка) и задача-над-числами, при этом при измерении: точка отсчета, система счисления, единица измерения выбирается произвольно, и есть способ перейти от одного способа измерения к другому.
Я не понимаю, к чему ты клонишь.
DG>тоже самое и с кодом: DG>возьмем программу F которая переводит вход S в выход T. DG>и возьмем изоморфизм M, которые переводит программу F в программу F1 (и обратно), при этом F1 также преобразует S в T, как и исходный F.
DG>часть свойств при переходе из F в F1 останется, часть пропадет. DG>те которые пропадают — они не существенные.
давай попроще, например к числам.
Да, можно множество целых положительных чисел отобразить в множество дробей вида 1/n и они перестанут быть целыми. Что из этого? Исходные целые положительные числа перестали быть целыми? Т.е. ты утверждаешь что "целость" числа это несущественное свойство, потому можно не обращать внимание, целое оно или нет?
DG>соответственно, я утверждаю, что деление полиморфизма на parametric, subtype и ad-hoc не существенно, потому что есть изоморфизмы, которые переводят одно в другое.
Вот тут нужен пример, который это подтвердит. Твой исходный не годится, его нельзя отнести к чисто параметрическому. Давай начнем с примера, который чистый ad-hoc (перегрузку функций) переведет в чисто параметрический, который будет соответствовать "written without mention of any specific type" согласно классификации 55-летней давности.
DG>зы DG>на практике интересует изоморфизмы, которые не просто переводят S -> F -> T в аналогичный S -> F1 -> T, но и которые не ухудшают серьезно вычислительную сложность F1
да, еще есть изоморфизмы, которые разбавляют код Thread.Sleep-ами
Здравствуйте, DarkGray, Вы писали:
DG>соответственно, двойственность наличия свойства K (с одной стороны — оно есть, а с другой стороны — его нет) означает, что есть изоморфизм M, который преобразует код F со свойством K в код F1 без свойства K (и обратно)
Я тут уже не очень понимаю, о чем ты пишешь. Судя по твоим открытиям, "целость" числа двойственна, "простота" тоже и недвойственные свойства надо еще поискать.
У меня такое ощущение, что ты о двойственности вспоминаешь когда всплывает несоотвествие определений придуманных тобой теорий с классическими.
DM>Хочешь сказать, что для абсолютно любого языка всегда есть "более простой набор примитивов"? Это как минимум не доказано, не очевидно и контринтуитивно.
автомат обладает более простым набором примитивов, не говоря уже про МТ.
при этом из тьюринга следует, что любой язык можно преобразовать в автомат.
Здравствуйте, DarkGray, Вы писали:
DG>автомат обладает более простым набором примитивов, не говоря уже про МТ. DG>при этом из тьюринга следует, что любой язык можно преобразовать в автомат.
Таким макаром мы придем к тому что все тьюринг полные языки ничем друг от друга не отличаются.
Интересно. Я правильно понимаю, что D как и C++ инстанциирует шаблоны во время компиляции? Т.е. фактически ничто кроме комитета не мешало бы сделать то же самое и в C++?
Здравствуйте, FR, Вы писали:
FR>Здравствуйте, DarkGray, Вы писали:
DG>>автомат обладает более простым набором примитивов, не говоря уже про МТ. DG>>при этом из тьюринга следует, что любой язык можно преобразовать в автомат.
FR>Таким макаром мы придем к тому что все тьюринг полные языки ничем друг от друга не отличаются.
Да, мы уже это проходили в теме про иммутабельный объект. Оказалось что все языки императивны вплоть до подмножества запросов SQL и регекспов именно по причине возможности выполнения их на МТ
S>Интересно. Я правильно понимаю, что D как и C++ инстанциирует шаблоны во время компиляции? Т.е. фактически ничто кроме комитета не мешало бы сделать то же самое и в C++?
Угу даже больше, этот самый комитет и зарубил это предложение (Concepts) при принятии нового стандарта.
DM> Если где-то можно один вид полиморфизма выразить через другой, первый вид не исчезнет.
он не исчезает, он просто перестает нас интересовать. также как, например, понятие указателя в языках C#/скриптах и т.д. никого не интересует.
DM>Нет, в вопросах теории ЯП нас интересует теория.
если мы хотим, что бы наш ЯП был только в теории, то — да.
если же интересует задача, чтобы ЯП использовался на практике, то кроме теории самого ЯП необходима еще теория:
построения эффективного компилятора, построение эффективного исполнителя, построение эффективной среды программирования, построение эффективного интерпретатора и т.д.
DG>>и кстати ATS должен быть дать понимание, что часть типов это чисто фишка компилятора, а часть переходит и в runtime. DG>>соответственно, каждый реальный язык имеет, как минимум, два набора типов: уровня компиляции и уровня runtime-а.
DM>Не стоит из отдельных примеров практики делать общие правила теории. Вот в Руби и Питоне где "набор типов уровня runtime"? Реальные языки.
как минимум есть типы int, string, массив и т.д.
в динамических языках как раз все типы являются типами runtime-а, и нет типов уровня компиляции
Здравствуйте, FR, Вы писали:
S>>Интересно. Я правильно понимаю, что D как и C++ инстанциирует шаблоны во время компиляции? Т.е. фактически ничто кроме комитета не мешало бы сделать то же самое и в C++?
FR>Угу даже больше, этот самый комитет и зарубил это предложение (Concepts) при принятии нового стандарта.
Точно, я читал о них немного когда их зарубили. Есть надежда, что их в действительности отложили.
А что делать с совместимостью с кодом, который работает без концептов? Оставить фичи темплейтов как есть (аки с небезопасным приведением типов)?
да, так записать можно, но не стоит: при этом дохнет проверка согласованности кода на компиляции, автоматический рефакторинг, intellisence и т.д.
DG>> также нет возможности задать параметры через "или". S>А где есть?
на C++ можно если извратнуться, если использовать аналоги для "или-на-шаблонах" из того же boost-а.
DG>>в частности, на C# нельзя описать следующую конструкцию: DG>>
DG>>T Sum<T>(this IEnumerable<T> items) where T:int/double/string/decimal и т.д.
DG>>
S>Можно использовать subtype полиморфизм и передавать явно сумматор. Можно прийти к решению как с Comparer<T>.Default (Summator<T>.Default.Sum(a, b), где сумматоры для интересующих типов хардкодятся руками). S>Решения есть, согласен что не слишком элегантные. Но ничего принципиально неразрешимого ты не назвал.
они не эквиваленты исходному. что-нибудь да отваливается: или эффективность исполнения, или проверка уровня компиляции, или возможность наращивать уже имеющийся код и т.д.
Здравствуйте, samius, Вы писали:
S>А что делать с совместимостью с кодом, который работает без концептов? Оставить фичи темплейтов как есть (аки с небезопасным приведением типов)?
Ну в D нормльно стыкуется, так же есть оба типа шаблонов, не всегда же жесткий контроль нужен.
Здравствуйте, DarkGray, Вы писали:
DG>да, так записать можно, но не стоит: при этом дохнет проверка согласованности кода на компиляции, автоматический рефакторинг, intellisence и т.д.
Я только опроверг твое утвреждение о том что на C# это сделать нельзя.
S>>Можно использовать subtype полиморфизм и передавать явно сумматор. Можно прийти к решению как с Comparer<T>.Default (Summator<T>.Default.Sum(a, b), где сумматоры для интересующих типов хардкодятся руками). S>>Решения есть, согласен что не слишком элегантные. Но ничего принципиально неразрешимого ты не назвал.
DG>они не эквиваленты исходному.
Если ты про оператор + для дженерика — то, да, неэквивалентны, т.к. придется использовать метод. В остальном — могут быть эквивалентны полностью. DG>что-нибудь да отваливается: или эффективность исполнения, или проверка уровня компиляции, или возможность наращивать уже имеющийся код и т.д.
Эффективность может быть на уровне выполнения оператора + если не использовать виртуальность. Проверено неоднократно.
Проверка уровня компиляции будет.
Возможность наращивать имеющийся код — это что? Если я верно предполагаю о чем ты, то придется заменить + на вызов метода. Да, неудобно. Но это несущественный недостаток, т.к. существует изоморфизм кода (ц) DG
S>Давай разбираться. Под составным отношением ты подразумеваешь композицию отношений?
да
S>Если да, то не очень понятно. Допустим, FoG (o= композиция) определено на SxT (x — декартово произведение). Непонятно, где определены F и G, что их композиция стала определена на SxT.
давай добавим промежуточное множество S-T, тогда F переводит S в S-T, а G из S-T в T.
F1 и G1 тоже преобразуют S в S-T и S-T в T соответственно.
DG>>дальше возьмем изоморфизм M над отношением F G, который переводит отношение F G в F1 G1(и обратно), при этом F1 G1 описывает такое же отношение S в T, как и исходное F G. S>не очень понимаю, о чем речь. Изоморфизм над отношением? Что есть объекты, что есть стрелки?
отношение — это объект
стрелка — это изменение этого отношения.
DG>>У отношения G при переходе к G1 часть свойств остается, а часть пропадает. S>О каких свойствах речь?
теми которыми обладает отношение G.
DG>>и соответственно, утверждается, что те свойства G, которые остаются при преобразовании являются существенными, а которые пропадают — не существенные, потому что с помощью изоморфизма M от них всегда можно избавиться. S>Изоморфизм сохраняет структуру, если что.
странное утверждение, как минимум необходимо зафиксировать структура чего сохраняется.
изоморфизм — это стрелка туда и обратно.
и верно как раз обратное, что то, что сохранилось — это и есть структура.
об этом и речь, что если есть изоморфизм, при котором свойство пропадает, то свойство не является определяющим структуру.
S>давай попроще, например к числам. S>Да, можно множество целых положительных чисел отобразить в множество дробей вида 1/n и они перестанут быть целыми. Что из этого? Исходные целые положительные числа перестали быть целыми? Т.е. ты утверждаешь что "целость" числа это несущественное свойство, потому можно не обращать внимание, целое оно или нет?
в этой задаче нет двух отношений, здесь рассматривается только одно отношение.
DG>>соответственно, я утверждаю, что деление полиморфизма на parametric, subtype и ad-hoc не существенно, потому что есть изоморфизмы, которые переводят одно в другое. S>Вот тут нужен пример, который это подтвердит. Твой исходный не годится, его нельзя отнести к чисто параметрическому. Давай начнем с примера, который чистый ad-hoc (перегрузку функций) переведет в чисто параметрический, который будет соответствовать "written without mention of any specific type" согласно классификации 55-летней давности.
вот только я утверждал, что достаточно "грязного" параметрического (а именно внутри которого можно написать произвольное выражение над типами) полиморфизма, и что соответственно чистый parametric, ad-hoc и subtype не нужны
FR>Таким макаром мы придем к тому что все тьюринг полные языки ничем друг от друга не отличаются.
при такой постановке — да.
поэтому интересует другая постановка задачи:
какой набор примитивов, свойств и т.д. является существенным при сохранении таких свойств кода как:
вычислительная сложность,
предсказуемость,
размер кода,
читабельность человеком
и т.д.
Здравствуйте, DarkGray, Вы писали:
DM>>Хочешь сказать, что для абсолютно любого языка всегда есть "более простой набор примитивов"? Это как минимум не доказано, не очевидно и контринтуитивно.
DG>автомат обладает более простым набором примитивов, не говоря уже про МТ. DG>при этом из тьюринга следует, что любой язык можно преобразовать в автомат.
МТ и др. автоматы — тоже языки, со своими правилами составления программ (грамматикой) и описанным механизмом работы (семантикой). Во что более простое их преобразовывать будешь? И вообще, определи сперва понятие "более простой". Что проще — МТ или лямбда-исчисление?
Здравствуйте, DarkGray, Вы писали:
DG>>>соответственно, каждый реальный язык имеет, как минимум, два набора типов: уровня компиляции и уровня runtime-а. DG>в динамических языках как раз все типы являются типами runtime-а, и нет типов уровня компиляции
Ну вот, а говорил "как минимум, два набора". А ведь в руби и питоне таки есть компиляция — в их байткод.
DG>>да, так записать можно, но не стоит: при этом дохнет проверка согласованности кода на компиляции, автоматический рефакторинг, intellisence и т.д. S>Я только опроверг твое утвреждение о том что на C# это сделать нельзя.
опять двадцатьпять — C# тьюринг полный язык, и сделать на нем можно всё что угодно.
и соответственно, фраза "сделать нельзя" означает, что нельзя сделать без потери каких-то существенных свойств кода, в данном случае, без потери статической проверяемости.
DG>>они не эквиваленты исходному.
если брать решение именно с отдельным сумматором, то отваливается автоматический вывод типов
var items = GetItems();
var s = Sum(items);//вот здесь придется явно указать тип сумматора
S> Возможность наращивать имеющийся код — это что?
кроме + необходимо полиморфность также и других операций: -, * и т.д.
соответственно для удобства обычно делают класс PolyOperation_Double, класс Matrix<T, TSummator> и выносят в библиотеку CoolOperations.
также делается какая-нибудь прикладная библиотека MegaMoving, которая во всю использует Matrix<double, PolyOperation_Double>
дальше вдруг выяснилось при написании библиотеки MySmartAirFly, что необходима еще полиморфная операция возведения в степень. при этом возможности и права изменения библиотеки CoolOperations часто нет, а без этого нельзя добавить эту функцию в PolyOperation_Double, можно лишь сделать PolyOperation_Double_MySmartAirFly отнаследованный от PolyOperation_Double.
в итоге библиотека MySmartAirFly во всю оперирует классом Matrix<double, PolyOperation_Double_MySmartAirFly> и всё вроде не плохо, кроме того, что матрицы из библиотеки MegaMoving нельзя использовать для передачи в функции библиотеки MySmartAirFly без преобразования (и соответствующей потери эффективности кода)
зы
в теории, эта проблема решается через partial(который действует и между библиотеками, а не только внутри) class-ы, которые собираются в один под именем PolyOperation_Double в момент запуска программы.
DM>МТ и др. автоматы — тоже языки, со своими правилами составления программ (грамматикой) и описанным механизмом работы (семантикой). Во что более простое их преобразовывать будешь?
а зачем это надо?
автомат я привел из-за того, что если хочется язык выполнить то все равно его придется тем или иным способом сводить к автомату.
отмечу, что несмотря на то, что языки алгорифмы маркова, лямбда-исчисление и т.д. с математической точки зрения автоматами не являются, исполняются они в любом случае автоматами.
DM> И вообще, определи сперва понятие "более простой". Что проще — МТ или лямбда-исчисление?
с точки зрения комбинирования алгоритмов: лямбда-исчисление проще, чем МТ — большая часть задач комбинирования решается за O(1)
или в более общем виде: есть ЯП, есть ряд требований требуемых от ЯП (часть я из них уже перечислял). для каждого ЯП каждое требование получается с помощью набора алгоритмов, чем меньше вычислительная сложность этих алгоритмов, тем проще ЯП.
как минимум есть еще процессор, а на уровне процессора никаких типов вида unicode-строка или ассоциативный массив — нет.
DM> А ведь в руби и питоне таки есть компиляция — в их байткод.
S> Да, неудобно. Но это несущественный недостаток, т.к. существует изоморфизм кода (ц) DG
тут все упирается в то, что не все морфизмы может выполнить человек за небольшое время.
например, морфизм переопределения символов сам по себе имеет низкую вычислительную сложность, но для человека он обладает высокой вычислительной сложностью (из-за особенности строения памяти человека).
соответственно, в этом и заключается теория создания ЯП:
выделить какие задачи и преобразования умеет делать быстро человек, а какие компьютер.
а дальше скомпоновать ЯП так, чтобы человеку приходилось в основном решать те задачи в которых он быстр, а компьютеру — остальные.
Здравствуйте, DarkGray, Вы писали:
S>>Давай разбираться. Под составным отношением ты подразумеваешь композицию отношений?
DG>да
S>>Если да, то не очень понятно. Допустим, FoG (o= композиция) определено на SxT (x — декартово произведение). Непонятно, где определены F и G, что их композиция стала определена на SxT.
DG>давай добавим промежуточное множество S-T, тогда F переводит S в S-T, а G из S-T в T. DG>F1 и G1 тоже преобразуют S в S-T и S-T в T соответственно.
Отношения ничего не переводят. Если ты говоришь об отношении F, то это тройка (S, S-T, X), где X подмножество SxS-T. Что куда переводится — неясно.
DG>>>дальше возьмем изоморфизм M над отношением F G, который переводит отношение F G в F1 G1(и обратно), при этом F1 G1 описывает такое же отношение S в T, как и исходное F G. S>>не очень понимаю, о чем речь. Изоморфизм над отношением? Что есть объекты, что есть стрелки?
DG>отношение — это объект DG>стрелка — это изменение этого отношения.
DG>>>У отношения G при переходе к G1 часть свойств остается, а часть пропадает. S>>О каких свойствах речь?
DG>теми которыми обладает отношение G.
Ты о каком-то конкретном отношении G?
DG>>>и соответственно, утверждается, что те свойства G, которые остаются при преобразовании являются существенными, а которые пропадают — не существенные, потому что с помощью изоморфизма M от них всегда можно избавиться. S>>Изоморфизм сохраняет структуру, если что.
DG>странное утверждение, как минимум необходимо зафиксировать структура чего сохраняется.
Категории. DG>изоморфизм — это стрелка туда и обратно. DG>и верно как раз обратное, что то, что сохранилось — это и есть структура. DG>об этом и речь, что если есть изоморфизм, при котором свойство пропадает, то свойство не является определяющим структуру.
Как стрелки определишь, такая и будет структура. Что-то ты чем дальше, тем глубже в лес.
S>>давай попроще, например к числам. S>>Да, можно множество целых положительных чисел отобразить в множество дробей вида 1/n и они перестанут быть целыми. Что из этого? Исходные целые положительные числа перестали быть целыми? Т.е. ты утверждаешь что "целость" числа это несущественное свойство, потому можно не обращать внимание, целое оно или нет?
DG>в этой задаче нет двух отношений, здесь рассматривается только одно отношение.
А для чего второе отношение?
S>>Вот тут нужен пример, который это подтвердит. Твой исходный не годится, его нельзя отнести к чисто параметрическому. Давай начнем с примера, который чистый ad-hoc (перегрузку функций) переведет в чисто параметрический, который будет соответствовать "written without mention of any specific type" согласно классификации 55-летней давности.
DG>вот только я утверждал, что достаточно "грязного" параметрического (а именно внутри которого можно написать произвольное выражение над типами) полиморфизма, и что соответственно чистый parametric, ad-hoc и subtype не нужны
Если ты хочешь внутри "грязного" параметрического написать a+b, то я не понимаю, как ты напишешь a+b не задействуя ad-hoc.
DG>>>да, так записать можно, но не стоит: при этом дохнет проверка согласованности кода на компиляции, автоматический рефакторинг, intellisence и т.д. S>>Я только опроверг твое утвреждение о том что на C# это сделать нельзя.
DG>опять двадцатьпять — C# тьюринг полный язык, и сделать на нем можно всё что угодно.
"все что угодно" — это слишком сильно для C# в частности и для тьюринг полноты в общем.
DG>и соответственно, фраза "сделать нельзя" означает, что нельзя сделать без потери каких-то существенных свойств кода, в данном случае, без потери статической проверяемости.
можешь написать диспетчеризацию руками, тогда тебе будет статическая проверяемость. Тут ты найдешь еще какое-то потеряное свойство, которое до сих пор не было в числе упомянутых тобой существенных
DG>>>они не эквиваленты исходному. DG>если брать решение именно с отдельным сумматором, то отваливается автоматический вывод типов
DG>
DG>var items = GetItems();
DG>var s = Sum(items);//вот здесь придется явно указать тип сумматора
DG>
Я же написал что можно не указывать, если пойти по пути Comparer<T>.Default и сделать сумматор для некоторого ограниченного набора типов.
S>> Возможность наращивать имеющийся код — это что?
DG>кроме + необходимо полиморфность также и других операций: -, * и т.д.
они уже полиморфны (ad-hoc).
Интуитивно я понимаю что ты хочешь, но ты настолько небрежно формулируешь свои мысли, что просто немогу удержаться от того что бы поправить.
DG>соответственно для удобства обычно делают класс PolyOperation_Double, класс Matrix<T, TSummator> и выносят в библиотеку CoolOperations.
DG>также делается какая-нибудь прикладная библиотека MegaMoving, которая во всю использует Matrix<double, PolyOperation_Double>
DG>дальше вдруг выяснилось при написании библиотеки MySmartAirFly, что необходима еще полиморфная операция возведения в степень. при этом возможности и права изменения библиотеки CoolOperations часто нет, а без этого нельзя добавить эту функцию в PolyOperation_Double, можно лишь сделать PolyOperation_Double_MySmartAirFly отнаследованный от PolyOperation_Double. DG>в итоге библиотека MySmartAirFly во всю оперирует классом Matrix<double, PolyOperation_Double_MySmartAirFly> и всё вроде не плохо, кроме того, что матрицы из библиотеки MegaMoving нельзя использовать для передачи в функции библиотеки MySmartAirFly без преобразования (и соответствующей потери эффективности кода)
Это проблемы теоретического характера. Матричные операции на С# и эффективность — слова из разных песен. Нужна эффективность в числорубке — сделай ее native.
DG>зы DG>в теории, эта проблема решается через partial(который действует и между библиотеками, а не только внутри) class-ы, которые собираются в один под именем PolyOperation_Double в момент запуска программы.
вижу, ты нашел еще одну категорию полиморфизма в ЯП — через управление набором исходников
Здравствуйте, DarkGray, Вы писали:
S>> Да, неудобно. Но это несущественный недостаток, т.к. существует изоморфизм кода (ц) DG
DG>тут все упирается в то, что не все морфизмы может выполнить человек за небольшое время.
Ты скажи, что за библиотеку ты собрался обобщать на C#? Уверяю тебя, что даже обобщить простенькую библиотеку обработки изображений на C++ может оказаться нетривиальной задачей. Вставить template и скобочки — тривиально, а получить качественный результат — уже нет.
DG>например, морфизм переопределения символов сам по себе имеет низкую вычислительную сложность, но для человека он обладает высокой вычислительной сложностью (из-за особенности строения памяти человека).
этим обычно занимаются не люди.
DG>соответственно, в этом и заключается теория создания ЯП: DG>выделить какие задачи и преобразования умеет делать быстро человек, а какие компьютер. DG>а дальше скомпоновать ЯП так, чтобы человеку приходилось в основном решать те задачи в которых он быстр, а компьютеру — остальные.
Реклама метапрограммирования? Да я не против. Только причем тут полиморфизм? Т.е. кроме того что мы можем написать программу, которая будет писать программу, в отношении полиморфизма ничего не меняется.
DG>>давай добавим промежуточное множество S-T, тогда F переводит S в S-T, а G из S-T в T. DG>>F1 и G1 тоже преобразуют S в S-T и S-T в T соответственно. S>Отношения ничего не переводят. Если ты говоришь об отношении F, то это тройка (S, S-T, X), где X подмножество SxS-T. Что куда переводится — неясно.
набор пар X как раз и определяет какой элемент из множества S переходит в какой элемент множества S-T (и наоборот).
если слово "переходит" не нравится, скажи каким другим одним словом это описывать. имхо, слово "относится" имеет какой-то другой смысл.
DG>>>>дальше возьмем изоморфизм M над отношением F G, который переводит отношение F G в F1 G1(и обратно), при этом F1 G1 описывает такое же отношение S в T, как и исходное F G. S>>>не очень понимаю, о чем речь. Изоморфизм над отношением? Что есть объекты, что есть стрелки?
DG>>отношение — это объект DG>>стрелка — это изменение этого отношения. S>
что не понятно? что такое изменение отношения? изменение набора пар множества X.
DG>>>>У отношения G при переходе к G1 часть свойств остается, а часть пропадает. S>>>О каких свойствах речь?
DG>>теми которыми обладает отношение G. S>Ты о каком-то конкретном отношении G?
в каждой конкретной задаче — оно конкретное, и имеет конкретный набор свойств K1, K2, K3, K4 и т.д.
S>Как стрелки определишь, такая и будет структура. Что-то ты чем дальше, тем глубже в лес.
я не очень понял зачем тебе понадобилась структура категории, когда речь шла про свойства кода, который является отдельными объектами внутри категории.
S>>>давай попроще, например к числам. S>>>Да, можно множество целых положительных чисел отобразить в множество дробей вида 1/n и они перестанут быть целыми. Что из этого? Исходные целые положительные числа перестали быть целыми? Т.е. ты утверждаешь что "целость" числа это несущественное свойство, потому можно не обращать внимание, целое оно или нет?
DG>>в этой задаче нет двух отношений, здесь рассматривается только одно отношение. S>А для чего второе отношение?
потому что сложные штуки становятся видными только на сложных конфигурациях.
с одной стороны: двойственности на одном отношении нет, с другой стороны: реальные задачи из одного отношения редко состоят.
S>Если ты хочешь внутри "грязного" параметрического написать a+b, то я не понимаю, как ты напишешь a+b не задействуя ad-hoc.
допустим вот так:
T Sum<T>(this IEnumerable<T> items)
{
var res = Empty(T);
foreach (var item in items)
{
compile-if(T.operators.contains(+=))
res += item;
else
res = Add(res, item);
}
return res;
}
partial T Add(T item1, T item2)
{
compile-if(T.operators.contains(+))
return item1 + item2;
elsif (T.methods.contains(Add(T)))
return item1.Add(item2);
}
partial T Add(T item1, T item2)
{
compile-if(T is TItem[])
return item1.Concat(item2).ToArray();
}
при этом partial означает, что это один и тот же метод, но разнесенный по коду
DG>>и соответственно, фраза "сделать нельзя" означает, что нельзя сделать без потери каких-то существенных свойств кода, в данном случае, без потери статической проверяемости. S>можешь написать диспетчеризацию руками, тогда тебе будет статическая проверяемость. Тут ты найдешь еще какое-то потеряное свойство, которое до сих пор не было в числе упомянутых тобой существенных
о чем речь?
DG>>>>они не эквиваленты исходному. DG>>если брать решение именно с отдельным сумматором, то отваливается автоматический вывод типов
DG>>
DG>>var items = GetItems();
DG>>var s = Sum(items);//вот здесь придется явно указать тип сумматора
DG>>
S>Я же написал что можно не указывать, если пойти по пути Comparer<T>.Default и сделать сумматор для некоторого ограниченного набора типов.
ты имеешь ввиду сделать?:
public class Summator<T>
{
public readonly static Func<T,T,T> Default = GenerateSummator<T>();
}
это, кстати, интересный подход. здесь, конечно, есть недостатки, но они локализованы в меньшем наборе кода.
и здесь даже можно обойти нерасширяемость, если в GenerateSummator запихнуть обход классов через reflection.
S>Это проблемы теоретического характера. Матричные операции на С# и эффективность — слова из разных песен. Нужна эффективность в
числорубке — сделай ее native.
спорно. например, если числомолотилка есть небольшая часть большего приложения. маршалинг в native может съесть всю эффективность, а писать всё приложение на native съест время разработки и устойчивость приложения.
Здравствуйте, DarkGray, Вы писали:
DG>>>давай добавим промежуточное множество S-T, тогда F переводит S в S-T, а G из S-T в T. DG>>>F1 и G1 тоже преобразуют S в S-T и S-T в T соответственно. S>>Отношения ничего не переводят. Если ты говоришь об отношении F, то это тройка (S, S-T, X), где X подмножество SxS-T. Что куда переводится — неясно.
DG>набор пар X как раз и определяет какой элемент из множества S переходит в какой элемент множества S-T (и наоборот).
Отношение и переходы — это что-то из разных опер. Пример — отношение (<). 0<1, 0<2, 0<3. Так куда переходит 0? DG>если слово "переходит" не нравится, скажи каким другим одним словом это описывать. имхо, слово "относится" имеет какой-то другой смысл.
Я пытаюсь понять, что ты описываешь.
DG>>>>>дальше возьмем изоморфизм M над отношением F G, который переводит отношение F G в F1 G1(и обратно), при этом F1 G1 описывает такое же отношение S в T, как и исходное F G. S>>>>не очень понимаю, о чем речь. Изоморфизм над отношением? Что есть объекты, что есть стрелки?
DG>>>отношение — это объект DG>>>стрелка — это изменение этого отношения. S>>
DG>что не понятно? что такое изменение отношения? изменение набора пар множества X.
Изменение отношения — непонятно. Изменение набора пар — непонятно. Что такое изменение?
Давай ближе к реальности, какие конкретно отношения ты рассматриваешь, и как изменяешь их пары?
DG>>>теми которыми обладает отношение G. S>>Ты о каком-то конкретном отношении G?
DG>в каждой конкретной задаче — оно конкретное, и имеет конкретный набор свойств K1, K2, K3, K4 и т.д.
Допустим, ты взял отношение порядка (<) и изменил набор пар. Ты получил что-то отличное от отношения порядка. И хочешь сказать что что-то нарушенное в отношении порядка оказалось несущественным? К чему вся эта кухня?
S>>Как стрелки определишь, такая и будет структура. Что-то ты чем дальше, тем глубже в лес.
DG>я не очень понял зачем тебе понадобилась структура категории, когда речь шла про свойства кода, который является отдельными объектами внутри категории.
Ты определил свойства кода как отношение? Шизею. Отношение чего к чему?
Допустим есть множество всех кодов C. То что код C1 из C декларативен, это отношение чего с чем? Куда тут стрелка? Что есть композиция отношений?
DG>>>в этой задаче нет двух отношений, здесь рассматривается только одно отношение. S>>А для чего второе отношение?
DG>потому что сложные штуки становятся видными только на сложных конфигурациях. DG>с одной стороны: двойственности на одном отношении нет, с другой стороны: реальные задачи из одного отношения редко состоят.
Нет никаких сложных конфигураций в отношении кода. Есть код. Он есть, он обладает свойствами. Все. Любое преобразование кода дает другой код с другими свойствами. Изменение набора пар свойств кода CxBool приведет лишь к тому, что определение свойств будет испорчено, но не изменит характеристики кода.
S>>Если ты хочешь внутри "грязного" параметрического написать a+b, то я не понимаю, как ты напишешь a+b не задействуя ad-hoc.
DG>допустим вот так: DG>
DG> compile-if(T.operators.contains(+=))
DG> res += item;
DG>
+= здесь уже ad-hoc. Ты от него не избавился. Ты его вовсю используешь.
DG>при этом partial означает, что это один и тот же метод, но разнесенный по коду
Да куда там partial!
+, += — это ad-hoc. Что ты не делай, но сложить два значения без специальных знаний о типе ты не можешь. Положить в контейнер — да. Сложить — нет.
S>Ты скажи, что за библиотеку ты собрался обобщать на C#? Уверяю тебя, что даже обобщить простенькую библиотеку обработки изображений на C++ может оказаться нетривиальной задачей. Вставить template и скобочки — тривиально, а получить качественный результат — уже нет.
Пределы обобщения на C# я знаю.
и C# я использую, в качестве, примера — потому что он достаточно сбалансирован по набору свойств: эффективность, надежность, поддержка IDE, статическая проверка и т.д.
DG>>например, морфизм переопределения символов сам по себе имеет низкую вычислительную сложность, но для человека он обладает высокой вычислительной сложностью (из-за особенности строения памяти человека). S>этим обычно занимаются не люди.
чтобы понять код вида
instance Applicative m => Applicative (SameT r m) where
pure = SameT . fmap Right . pure
(SameT m) <*> (SameT x) = SameT ((fmap h m) <*> x)
where
h (Left g) = const (Left g)
h (Right f) = either Left (Right . f)
необходимо восстановить, что такое m, h, x, f и т.д.
и они означают что-то другое, чем эти же буквы обозначали в соседнем куске кода.
Здравствуйте, DarkGray, Вы писали:
S>>можешь написать диспетчеризацию руками, тогда тебе будет статическая проверяемость. Тут ты найдешь еще какое-то потеряное свойство, которое до сих пор не было в числе упомянутых тобой существенных
DG>о чем речь?
if (t.GetType() == typeof(int))
S>>Я же написал что можно не указывать, если пойти по пути Comparer<T>.Default и сделать сумматор для некоторого ограниченного набора типов.
DG>ты имеешь ввиду сделать?: DG>
DG>public class Summator<T>
DG>{
DG> public readonly static Func<T,T,T> Default = GenerateSummator<T>();
DG>}
DG>
DG>это, кстати, интересный подход. здесь, конечно, есть недостатки, но они локализованы в меньшем наборе кода. DG>и здесь даже можно обойти нерасширяемость, если в GenerateSummator запихнуть обход классов через reflection.
Да, что-то вроде.
Но расширяемость будет хромая.
Подход совершенно не интересный. Расскажу почему: даже если предположить, что кто-то нагенерил таких сумматоров, минусаторов, умножаторов, и т.п. вплоть до операций сравнения, сдвига, возведения в степень и что в голову придет, то это ситуацию не изменит.
Нужны более широкие возможности. Допустим, я хочу суммировать float-ы в double-ах. Усе, приехали. Нужно Summator<A1,A2,R> или что-то в этом роде. Стоит просто подумать над такой тривиальной вещью, как сверткой на Bitmap<T> и все желание писать обобщенный код для этого на C# пропадает.
S>>Это проблемы теоретического характера. Матричные операции на С# и эффективность — слова из разных песен. Нужна эффективность в числорубке — сделай ее native.
DG>спорно. например, если числомолотилка есть небольшая часть большего приложения. маршалинг в native может съесть всю эффективность, а писать всё приложение на native съест время разработки и устойчивость приложения.
Ищи компромисс. В программировании вообще все не по рельсам. Например, маршалинг при обобщенной обработке Bitmap<T> в native наверняка оправдает.
DG>>>например, морфизм переопределения символов сам по себе имеет низкую вычислительную сложность, но для человека он обладает высокой вычислительной сложностью (из-за особенности строения памяти человека). S>>этим обычно занимаются не люди.
DG>чтобы понять код вида DG>
DG>instance Applicative m => Applicative (SameT r m) where
DG>
DG>необходимо восстановить, что такое m, h, x, f и т.д. DG>и они означают что-то другое, чем эти же буквы обозначали в соседнем куске кода.
а причем тут морфизм переопределения символов?
Кстати, по поводу m, h, x, f и т.д. — довольно понятно. И вообще все буквы знакомы. И общий смысл, если напрячься.
S>Отношение и переходы — это что-то из разных опер. Пример — отношение (<). 0<1, 0<2, 0<3. Так куда переходит 0?
во множество (1, 2, 3), а в 0 при этом не переходит (если отношение рассматривается в одну сторону)
S>Давай ближе к реальности, какие конкретно отношения ты рассматриваешь, и как изменяешь их пары?
давай возьмем задачу: есть плоскость, на плоскости есть две прямых, каждую прямую необходимо представить в виде уравнения x/a + y/b = 1 (координатную привязка общая и может выбираться произвольная)
также на плоскости есть три ориентира (три различных точки, не лежащих на одной прямой), и для каждой прямой известны три минимальных растояния от прямой до каждой точки
соответственно:
F — это линейное отображение исходной плоскости на координатную плоскость (каждой точке исходной плоскости ставится в соответствии точка на координатной плоскости)
G — это мультиотображение номера прямой в коэффициенты a,b уравнения x/a + y/b = 1 для данной координатной плоскости
при этом у G есть свойство, что для данной координатной плоскости не всякая прямая может быть представлена в виде x/a + y/b = 1
но в рамках композиции F G — это свойство является несущественным, потому что всегда можно подобрать такое отображение F, чтобы обе прямые были представимы.
S>>>можешь написать диспетчеризацию руками, тогда тебе будет статическая проверяемость. Тут ты найдешь еще какое-то потеряное свойство, которое до сих пор не было в числе упомянутых тобой существенных
DG>>о чем речь? S>if (t.GetType() == typeof(int))
если t имеет тип, для которых не определен способ сложения, то упадет оно в рантайме, т.е. здесь нет статической проверяемости.
S>Да, что-то вроде. S>Но расширяемость будет хромая. S>Подход совершенно не интересный.
пока шаблонный параметр один — подход еще достаточно хороший, потому что непроверяемая компилятором область растет линейно от кол-ва типов.
S> Нужно Summator<A1,A2,R> или что-то в этом роде.
да, такой вариант уже много хуже. если использовать тот же подход, то непроверяться уже будет квадратичная область.
S> Расскажу почему: даже если предположить, что кто-то нагенерил таких сумматоров, минусаторов, умножаторов, и т.п. вплоть до операций сравнения, сдвига, возведения в степень и что в голову придет, то это ситуацию не изменит. S>Нужны более широкие возможности.
какие например?
DG>>спорно. например, если числомолотилка есть небольшая часть большего приложения. маршалинг в native может съесть всю эффективность, а писать всё приложение на native съест время разработки и устойчивость приложения. S>Ищи компромисс. В программировании вообще все не по рельсам. Например, маршалинг при обобщенной обработке Bitmap<T> в native наверняка оправдает.
оправдает, если либа для обработки изображений готовая и ее не надо расширять.
если же ее необходимо писать самим, и еще дополнительно рассмотреть проблемы managment-а, что в команде должен появиться человек, который хорошо знает native, а также, что для загрузки этого специалиста должен быть достаточный набор native-задач, то окупаемость под вопросом.
S>Допустим есть множество всех кодов C. То что код C1 из C декларативен, это отношение чего с чем? Куда тут стрелка? Что есть композиция отношений?
стрелка из Ci в Cj есть, если известен алгоритм, который автоматически переводит Ci в Cj (и код Cj тем же образом преобразует вход в выход, что и код Ci)
и дальше утверждается, что если для данного кода C1 есть стрелка в C2, а из C2 есть стрелка в C1, при этом C1 декларативный, а C2 императивный, то свойство декларативности C1 и свойство императивности C2 являются не существенными.
S>Отношение и переходы — это что-то из разных опер. Пример — отношение (<). 0<1, 0<2, 0<3. Так куда переходит 0?
отношение F AxB задает в общем случае две частичных мультифункции Fab A=>B и Fba B=>A.
соответственно частичная мультифункция Fab отображает(переводит) подмножество A на подмножество B.
каждый элемент множества A при этом отображается в некое непустое подмножество B, если он входит в область определения Fab, или отображается в пустое подмножество B, если не входит в область определения Fab.
Здравствуйте, DarkGray, Вы писали:
S>>if (t.GetType() == typeof(int))
DG>если t имеет тип, для которых не определен способ сложения, то упадет оно в рантайме, т.е. здесь нет статической проверяемости.
Вот ты о чем. Это тоже лечится. Можно скрыть дженерики за недженериковым фасадом так, что алгоритм будет обобщенный, а способ к нему обратиться — только для фиксированных типов.
S>>Нужны более широкие возможности. DG>какие например?
Я написал сразу за той фразой.
DG>оправдает, если либа для обработки изображений готовая и ее не надо расширять. DG>если же ее необходимо писать самим, и еще дополнительно рассмотреть проблемы managment-а, что в команде должен появиться человек, который хорошо знает native, а также, что для загрузки этого специалиста должен быть достаточный набор native-задач, то окупаемость под вопросом.
Уверяю, одним языком ты все проблемы включая проблемы менеджмента не решишь. Будет у тебя супер-пупер язык, а разработчиков под него не будет. Получится что язык плох для решения проблем менеджмента
В общем, с этим уже надо в форум "работа" переходить. Полиморфизмом тут уже не пахнет.
Здравствуйте, DarkGray, Вы писали:
S>>Допустим есть множество всех кодов C. То что код C1 из C декларативен, это отношение чего с чем? Куда тут стрелка? Что есть композиция отношений?
DG>стрелка из Ci в Cj есть, если известен алгоритм, который автоматически переводит Ci в Cj (и код Cj тем же образом преобразует вход в выход, что и код Ci)
Допустим
DG>и дальше утверждается, что если для данного кода C1 есть стрелка в C2, а из C2 есть стрелка в C1, при этом C1 декларативный, а C2 императивный, то свойство декларативности C1 и свойство императивности C2 являются не существенными.
Предположим. И какие полезные выводы ты делаешь из этого? Что полезного в этой несущественности?
Что может быть полезного в несущественности таких свойств как делимость, непрерывность, интегрируемость, длина? Ты отменишь все теории, которые оперируют несущественными свойствами?
Здравствуйте, DarkGray, Вы писали:
S>>Отношение и переходы — это что-то из разных опер. Пример — отношение (<). 0<1, 0<2, 0<3. Так куда переходит 0?
DG>отношение F AxB задает в общем случае две частичных мультифункции Fab A=>B и Fba B=>A. DG>соответственно частичная мультифункция Fab отображает(переводит) подмножество A на подмножество B.
Этот бред мы уже обсуждали.
DG>каждый элемент множества A при этом отображается в некое непустое подмножество B, если он входит в область определения Fab, или отображается в пустое подмножество B, если не входит в область определения Fab.
Здесь у тебя точнее. Но при том что каждый элемент отображается в подмножество, подмножество элементов в подмножество не отобразится. Оно отобразится в множество подмножеств.
Т.е. можно сказать что отношение F AxB отображает A в множество подмножеств B, но не в подмножество B.
Здравствуйте, DarkGray, Вы писали:
S>>Отношение и переходы — это что-то из разных опер. Пример — отношение (<). 0<1, 0<2, 0<3. Так куда переходит 0?
DG>во множество (1, 2, 3), а в 0 при этом не переходит (если отношение рассматривается в одну сторону)
ок, элемент переводит во множество. Пусть так.
S>>Давай ближе к реальности, какие конкретно отношения ты рассматриваешь, и как изменяешь их пары?
DG>давай возьмем задачу: есть плоскость, на плоскости есть две прямых, каждую прямую необходимо представить в виде уравнения x/a + y/b = 1 (координатную привязка общая и может выбираться произвольная) DG>также на плоскости есть три ориентира (три различных точки, не лежащих на одной прямой), и для каждой прямой известны три минимальных растояния от прямой до каждой точки
И зачем эти ориентиры, если ты их не упомянул? Так, голову подзаморочить?
DG>соответственно: DG>F — это линейное отображение исходной плоскости на координатную плоскость (каждой точке исходной плоскости ставится в соответствии точка на координатной плоскости) DG>G — это мультиотображение номера прямой в коэффициенты a,b уравнения x/a + y/b = 1 для данной координатной плоскости
Т.е. не отображение на пару, а именно мультиотображение, что бы было интереснее дискутировать? Покажи, почему оно будет мультиотображением.
DG>при этом у G есть свойство, что для данной координатной плоскости не всякая прямая может быть представлена в виде x/a + y/b = 1 DG>но в рамках композиции F G — это свойство является несущественным, потому что всегда можно подобрать такое отображение F, чтобы обе прямые были представимы.
Все ясно. Извини, дальше нет никакого желания обсуждать твою несущественность и то как ты отображаешь отношения.
DG>>отношение F AxB задает в общем случае две частичных мультифункции Fab A=>B и Fba B=>A. DG>>соответственно частичная мультифункция Fab отображает(переводит) подмножество A на подмножество B. S>Этот бред мы уже обсуждали.
тогда была придирка, что вместо слова частичная мультифункция используется слово функция, сейчас всё верно.
DG>>каждый элемент множества A при этом отображается в некое непустое подмножество B, если он входит в область определения Fab, или отображается в пустое подмножество B, если не входит в область определения Fab. S>Здесь у тебя точнее. Но при том что каждый элемент отображается в подмножество, подмножество элементов в подмножество не отобразится. Оно отобразится в множество подмножеств. S>Т.е. можно сказать что отношение F AxB отображает A в множество подмножеств B, но не в подмножество B.
это однофигственно. есть изоморфизм, который однозначно переводит одно в другое.
в одну сторону необходимо: сгруппировать пары на основе левого элемента, затем правые элементы свернуть в множество, что для каждого A даст пару (элемент A, подмножество B).
в другую сторону — для каждого правого элемента пары (элемент A, подмножество B) образовать пару (левый элемент, правый элемент), все эти пары объединить — это даст частичную мультифункцию или отношение.
DG>>также на плоскости есть три ориентира (три различных точки, не лежащих на одной прямой), и для каждой прямой известны три минимальных растояния от прямой до каждой точки S>И зачем эти ориентиры, если ты их не упомянул? Так, голову подзаморочить?
это если от абстракций захочется к формулам перейти
DG>>соответственно: DG>>F — это линейное отображение исходной плоскости на координатную плоскость (каждой точке исходной плоскости ставится в соответствии точка на координатной плоскости) DG>>G — это мультиотображение номера прямой в коэффициенты a,b уравнения x/a + y/b = 1 для данной координатной плоскости S>Т.е. не отображение на пару, а именно мультиотображение, что бы было интереснее дискутировать? Покажи, почему оно будет мультиотображением.
S>Что может быть полезного в несущественности таких свойств как делимость, непрерывность, интегрируемость, длина?
несущественными они становятся в конкретных задачах (или на классах задач).
например, если в конкретной задаче объекты "бесконечно"-резиновые, то свойство длины конкретного объекта теряет смысл.
делимость несущественна на задачах, где точки отсчета берутся произвольно, но существенна в криптографии,
конечное отсутствие непрерывности несущественно если есть возможность непрерывное пространство отображать в кусочно-непрерывное и обратно.
для интегрируемости сейчас сходу не приведу изоморфизмов, которые позволяют его менять.
"объявление" какого-то свойства для класса задач несущественным, позволяет рассматривать только один общий вариант.
если есть возможность частично непрерывное пространство отобразить на непрерывное, то значит можно решить только вариант непрерывного пространства, а затем полученное решение отобразить на частично-непрерывное пространство.
S>Можно скрыть дженерики за недженериковым фасадом так, что алгоритм будет обобщенный, а способ к нему обратиться — только для фиксированных типов.
в ряде случаев так можно, но тогда нельзя будет написать обобщенную версию алгоритма, который использует данный алгоритм.
при разработке удобнее же считать, что, например, есть обобщенный алгоритм Sum<T>, Add<T> и т.д., с возможность проверки на этапе компиляции, что Sum<MyVector> мы уже использовали, но вот MyVector + MyVector еще не определили.
S>Что может быть полезного в несущественности таких свойств как делимость, непрерывность, интегрируемость, длина? Ты отменишь все теории, которые оперируют несущественными свойствами?
Двойственные свойства хороши тем:
1.что если они полезны, то их всегда можно создать, если они не полезны, то от них всегда можно избавиться.
2. если для задачи З1 свойство полезно, а для задачи З2 вредно, то для задачи З1 свойство можно создать, а для задачи З2 его можно убрать.
3. также если двойственность проявляется на всем множестве, то это позволяет рассматривать при необходимости только одну сторону медали. например, для любого кода можно считать, что он декларативный, или для любого полиморфизма можно считать что он является "грязным" параметрическим и т.д.
и это переводит к вопросам:
в чем положительные стороны(в каких задачах это помогает) parametric, ad-hoc, subtype полиморфизма? в каких задачах они мешают?
к тому что человек такое очень плохо воспринимает, и это сейчас в треде демонстрирует samius.
я уже давно явно отметил, что:
термин "переходит" в данном случае используется, как несуществующий термин "относит", который означает, что между множествами A и B задано отношение, и что рассматривается направление отношения из A в B (а не обратное).
и также заметил, что если такое переопределение слов для тебя трудно, то скажи каким одним словом это обозначить.
Здравствуйте, DarkGray, Вы писали:
S>>Этот бред мы уже обсуждали.
DG>тогда была придирка, что вместо слова частичная мультифункция используется слово функция, сейчас всё верно.
Сейчас все еще хуже. У тебя проблема с пониманием определений. Мультифункция это частный случай функции, который отображает подмножество в множество подмножеств, а не во множество.
DG>>>каждый элемент множества A при этом отображается в некое непустое подмножество B, если он входит в область определения Fab, или отображается в пустое подмножество B, если не входит в область определения Fab. S>>Здесь у тебя точнее. Но при том что каждый элемент отображается в подмножество, подмножество элементов в подмножество не отобразится. Оно отобразится в множество подмножеств. S>>Т.е. можно сказать что отношение F AxB отображает A в множество подмножеств B, но не в подмножество B.
DG>это однофигственно. есть изоморфизм, который однозначно переводит одно в другое.
Множество подмножеств во множество? ОДнозначно? Пудри мозги кому-нибудь еще. DG>в одну сторону необходимо: сгруппировать пары на основе левого элемента, затем правые элементы свернуть в множество, что для каждого A даст пару (элемент A, подмножество B).
Подмножество B!!! Подмножество! Элемент А -> подмножество B. Значит A в множество подмножеств B. Ау!
DG>в другую сторону — для каждого правого элемента пары (элемент A, подмножество B) образовать пару (левый элемент, правый элемент), все эти пары объединить — это даст частичную мультифункцию или отношение.
Обратно это значит что для любого непустого подмножества B ты должен указать A. Отношение это дает. А функцию — нет, т.к. ты не потребовал однозначности отношения.
Завязывай с этим уже. Множества и отображения явно не мой конек, но у тебя с ними еще скромнее.
Здравствуйте, DarkGray, Вы писали:
S>>И зачем эти ориентиры, если ты их не упомянул? Так, голову подзаморочить?
DG>это если от абстракций захочется к формулам перейти
нет, не захочется
S>>Что может быть полезного в несущественности таких свойств как делимость, непрерывность, интегрируемость, длина?
DG>несущественными они становятся в конкретных задачах (или на классах задач). DG>например, если в конкретной задаче объекты "бесконечно"-резиновые, то свойство длины конкретного объекта теряет смысл.
Может его просто не рассматривать? DG>делимость несущественна на задачах, где точки отсчета берутся произвольно, но существенна в криптографии,
DG>конечное отсутствие непрерывности несущественно если есть возможность непрерывное пространство отображать в кусочно-непрерывное и обратно.
О каком пространстве речь? О метрическом векторном? А разве оно может иметь разрывы?
DG>для интегрируемости сейчас сходу не приведу изоморфизмов, которые позволяют его менять.
композиция с функцией Дирихле
DG>"объявление" какого-то свойства для класса задач несущественным, позволяет рассматривать только один общий вариант. DG>если есть возможность частично непрерывное пространство отобразить на непрерывное, то значит можно решить только вариант непрерывного пространства, а затем полученное решение отобразить на частично-непрерывное пространство.
Что ты подразумеваешь под непрерывным пространством?
Здравствуйте, DarkGray, Вы писали:
S>>Можно скрыть дженерики за недженериковым фасадом так, что алгоритм будет обобщенный, а способ к нему обратиться — только для фиксированных типов.
DG>в ряде случаев так можно, но тогда нельзя будет написать обобщенную версию алгоритма, который использует данный алгоритм.
DG>при разработке удобнее же считать, что, например, есть обобщенный алгоритм Sum<T>, Add<T> и т.д., с возможность проверки на этапе компиляции, что Sum<MyVector> мы уже использовали, но вот MyVector + MyVector еще не определили.
Ну, тут тебе с дотнетом и разворачиванием дженериков в рантайме не повезло.
Зато это позволяет делать трюки с типами, которые в C++ невозможны в рантайме.
S>>Что может быть полезного в несущественности таких свойств как делимость, непрерывность, интегрируемость, длина? Ты отменишь все теории, которые оперируют несущественными свойствами?
DG>Двойственные свойства хороши тем: DG>1.что если они полезны, то их всегда можно создать, если они не полезны, то от них всегда можно избавиться.
Сомнительная полезность
DG>2. если для задачи З1 свойство полезно, а для задачи З2 вредно, то для задачи З1 свойство можно создать, а для задачи З2 его можно убрать.
Это не то же самое, что пункт 1?
DG>3. также если двойственность проявляется на всем множестве, то это позволяет рассматривать при необходимости только одну сторону медали. например, для любого кода можно считать, что он декларативный, или для любого полиморфизма можно считать что он является "грязным" параметрическим и т.д.
Чушь. См. определения.
DG>и это переводит к вопросам: DG>в чем положительные стороны(в каких задачах это помогает) parametric, ad-hoc, subtype полиморфизма? в каких задачах они мешают?
Нет, ты ошибаешься. Эти вопросы они сами по себе и ответы на них тривиальны, можно их увидеть в самих определениях и комментариях к ним. А твоя двойственность — сама по себе. И жил я до нее и буду дальше жить, и вопросы ставил, и отвечал на них. Уйти от полиморфизма я могу без твоей двойственности. А как подменить ad-hoc параметрическим, ты мне так глаза и не раскрыл. Да я и не надеялся.
S>Сейчас все еще хуже. У тебя проблема с пониманием определений. Мультифункция это частный случай функции, который отображает подмножество в множество подмножеств, а не во множество.
Здравствуйте, DarkGray, Вы писали:
S>>а причем тут морфизм переопределения символов?
DG>к тому что человек такое очень плохо воспринимает, и это сейчас в треде демонстрирует samius.
DG>я уже давно явно отметил, что: DG>термин "переходит" в данном случае используется, как несуществующий термин "относит", который означает, что между множествами A и B задано отношение, и что рассматривается направление отношения из A в B (а не обратное).
У отношения появилось направление? Расскажи подробнее.
DG>и также заметил, что если такое переопределение слов для тебя трудно, то скажи каким одним словом это обозначить.
Я ответил, что для того что бы подобрать слово, нужно понять, о чем ты. А я не понимаю.
Здравствуйте, DarkGray, Вы писали:
DM>>МТ и др. автоматы — тоже языки, со своими правилами составления программ (грамматикой) и описанным механизмом работы (семантикой). Во что более простое их преобразовывать будешь?
DG>а зачем это надо?
Да вот выше ты писал: DG>корректнее это утверждение формулируется как: DG>язык является языком — если есть алгоритм исполнения или/и алгоритм трансляции в более простой набор примитивов.
Это равносильно утверждению, что для любого языка есть более простой набор примитивов. Если же для каких-то это вдруг не так, то опять твое определение не годится.
DM>>Ну вот, а говорил "как минимум, два набора".
DG>как минимум есть еще процессор, а на уровне процессора никаких типов вида unicode-строка или ассоциативный массив — нет.
А еще есть в Киеве дядька. Система "типов" процессора не входит в определение языков вроде питона и руби. В качестве исполнителя программы можно взять не процессор, а группу красивых девушек. Имея спецификацию языка, они все отлично выполнят, никакой процессор и его типы не понадобятся.
DM>Да вот выше ты писал: DG>>корректнее это утверждение формулируется как: DG>>язык является языком — если есть алгоритм исполнения или/и алгоритм трансляции в более простой набор примитивов.
DM>Это равносильно утверждению, что для любого языка есть более простой набор примитивов. Если же для каких-то это вдруг не так, то опять твое определение не годится.
а логическая операция "или" там написана просто так? напомню, что для верности "или" достаточно верности только одной части утверждения.
DM>>>Ну вот, а говорил "как минимум, два набора".
DG>>как минимум есть еще процессор, а на уровне процессора никаких типов вида unicode-строка или ассоциативный массив — нет.
DM>А еще есть в Киеве дядька. Система "типов" процессора не входит в определение языков вроде питона и руби. В качестве исполнителя программы можно взять не процессор, а группу красивых девушек. Имея спецификацию языка, они все отлично выполнят, никакой процессор и его типы не понадобятся.
ты одного исполнителя "процессор" заменил на другой исполнителя "группа девушек".
эта "группа девушек" тоже обладает знанием каких-то своих типов: в частности: число, последовательность и т.д.
вот если бы ты сказал, что для исполнения питона достаточно "группы обезьян" тогда можно было бы поговорить о том, что нет системы типов уровня исполнения.
вот представь, что ты взял произвольную девушку и заставил ее исполнять питон.
скорее всего для этого понадобится инструкция.
а в этой инструкции ты будешь писать:
возьмите следующую строку программы-питона, если там написано x = .., выполните выражение, а результат значения запишите на листке бумаги под именем x.
в данном случае система типов исполнителя: последовательность + строка + ассоциативный массив. также он поддерживает операции: перейти на следующий элемент последовательности, поместить элемент в ассоциативный массив, найти элемент и т.д.
зачем это всё надо?
это необходимо если язык выбирается, изучается, разрабатывается и т.д. не просто для "сферического коня в вакууме", а и для того, чтобы исполнение программы было максимально эффективным.
в частности, например, есть интересный вопрос: какие языки лучше подходят для исполнения на js?
S>>набор пар X как раз и определяет какой элемент из множества S переходит в какой элемент множества S-T (и наоборот).
S>>нет.
DG>перепишем это как: DG>каждая пара из набора пар X — как раз и определяет какой элемент из множества S соотносится с каким элементом множества S-T
DG>так верно.
Нет. "Какой" подразумевает один. А может быть и не один элемент, который соотноситя с неким элементом из S-T.
DG>если не согласен, тогда запиши своим русским языком, что задает каждая пара (a, b).
Пара (a,b) указывает что элементы a и b состоят в отношении.
S>> У отношения появилось направление? Расскажи подробнее
DG>можно брать пары (a,b), а можно (b, a) — если не нравится термин "направление", опять же предложи свой
DG>
DG>a binary relation on a set A is a collection of ordered pairs of elements of A.
Там же дальше разжевано, что такое ordered pair. Это кортеж, не более чем. А у кортежа нет направления. То что в кортеже какой-то элемент первый — ну так это просто недостатки человеческой психики: прикладывать все что можно к линейке.
Главное — не путать, на каком месте в кортеже стоят элементы одного множества, на каком другого.
DG>>если не согласен, тогда запиши своим русским языком, что задает каждая пара (a, b). S>Пара (a,b) указывает что элементы a и b состоят в отношении.
а так можно?
Пара (a,b) указывает что элементы a и b соотносятся с друг другом.
S>>> У отношения появилось направление? Расскажи подробнее
DG>>можно брать пары (a,b), а можно (b, a) — если не нравится термин "направление", опять же предложи свой
DG>>
DG>>a binary relation on a set A is a collection of ordered pairs of elements of A.
S>Там же дальше разжевано, что такое ordered pair. Это кортеж, не более чем. А у кортежа нет направления. То что в кортеже какой-то элемент первый — ну так это просто недостатки человеческой психики: прикладывать все что можно к линейке.
у отношения лево и право есть?
слева на право и справа на лево — это разные направления или что?
Здравствуйте, DarkGray, Вы писали:
DG>(для X ((есть алгоритм исполнения) || (есть алгоритм трансляции в более простой набор примитивов) )) -> X является языком
Да, я там первую часть фразы пропустил по невнимательности, сорри. С обоими частями мне определение уже нравится.
DG>>перепишем это как: DG>>каждая пара из набора пар X — как раз и определяет какой элемент из множества S соотносится с каким элементом множества S-T
DG>>так верно. S>Нет. "Какой" подразумевает один.
каждая пара делает утверждение только про один элемент слева и про один элемент справа
это и написано.
Здравствуйте, DarkGray, Вы писали:
DM>>А еще есть в Киеве дядька. Система "типов" процессора не входит в определение языков вроде питона и руби. В качестве исполнителя программы можно взять не процессор, а группу красивых девушек. Имея спецификацию языка, они все отлично выполнят, никакой процессор и его типы не понадобятся.
DG>ты одного исполнителя "процессор" заменил на другой исполнителя "группа девушек". DG>эта "группа девушек" тоже обладает знанием каких-то своих типов: в частности: число, последовательность и т.д.
Фишка в том, что если действительно можно так просто поменять исполнителя и его систему типов, значит в определении языка они не зафиксированы, и в определение языка тот второй набор типов уже не входит, вот и все. Как не входят в язык ни уравнения Максвелла и Шредингера, работающие в процессоре, ни родной язык тех девушек.
Здравствуйте, DarkGray, Вы писали:
S>>Нет. "Какой" подразумевает один.
DG>пруфлинк или это твои тараканы.
Можешь считать это моими тараканами, но у меня есть повод считать что я более требователен к языку и выражениям, чем ты.
S>>Пара (a,b) указывает что элементы a и b состоят в отношении.
DG>а так можно? DG>Пара (a,b) указывает что элементы a и b соотносятся с друг другом.
разрешаю
S>>Там же дальше разжевано, что такое ordered pair. Это кортеж, не более чем. А у кортежа нет направления. То что в кортеже какой-то элемент первый — ну так это просто недостатки человеческой психики: прикладывать все что можно к линейке.
DG>у отношения лево и право есть?
Нет, конечно. Просто в форме записи "x is R-related to y" (xRy) x находится слева. Если ты это не напишешь, а произнесешь, то никакого лева уже не будет.
DG>слева на право и справа на лево — это разные направления или что?
Нет никаких направлений
DM>Фишка в том, что если действительно можно так просто поменять исполнителя и его систему типов, значит в определении языка они не зафиксированы, и в определение языка тот второй набор типов уже не входит, вот и все.
так речь же не о том, что входит в язык, а какие требования ЯП явно(или не явно) выдвигает к системе исполнения для своего эффективного исполнения.
большинство современных языков требуют типы:
число (нескольких видов), последовательность, стэк
в ряде случаев:
ассоциативный массив, виртуальный объект, bool, строка, массив и т.д.
требования чисто-функционального языка можно урезать до стэка и списка (или множества)
DG>>у отношения лево и право есть? S>Нет, конечно. Просто в форме записи "x is R-related to y" (xRy) x находится слева. Если ты это не напишешь, а произнесешь, то никакого лева уже не будет.
т.е. математики ничего не понимают, когда про отношение говорят?
(also called left-unique)
also called right-unique[1] or right-definite
left-total[1]: for all x in X there
Здравствуйте, DarkGray, Вы писали:
S>>Нет, конечно. Просто в форме записи "x is R-related to y" (xRy) x находится слева. Если ты это не напишешь, а произнесешь, то никакого лева уже не будет.
DG>т.е. математики ничего не понимают, когда про отношение говорят?
Они говорят не об направлении. left и right-ом они обозначают domain/codomain.
DG>>>слева на право и справа на лево — это разные направления или что? S>>Нет никаких направлений
DG>если нет направлений, то чем термин injective (left-unique) отличается от functional (right-unique)?
направлений нет. Но чем термины отличаются, смотри в википедии. А почему у них написано в скобках left/right — догадайся.
Ведь двоичное отношение это частный случай n-арного отношения. А как ты в n-арном отношении будешь обозначать 3-е, 4-е, 20-е множество? Верх/низ/зюйд-вест?
Здравствуйте, DarkGray, Вы писали:
DG>от того, что ты сделал замену слов ничего не поменялось. DG>все равно есть направление domain -> codomain и codomain -> domain.
Нет направления. Есть domain и codomain.
DG>спрошу более просто: DG>если тебе не нравится слово "направление", то что меняется при перестановке AxB => BxA, и каким это словом можно обозначить?
Тут хочется спросить тебя, а что ты надеялся получить при перестановке операндов декартова произведения?
Нам теперь придется элементы из A искать во втором элементе пары из BxA. И что из этого? Ты думаешь, что изменил природу отношения?
DG>>спрошу более просто: DG>>если тебе не нравится слово "направление", то что меняется при перестановке AxB => BxA, и каким это словом можно обозначить? S>Тут хочется спросить тебя, а что ты надеялся получить при перестановке операндов декартова произведения? S>Нам теперь придется элементы из A искать во втором элементе пары из BxA. И что из этого? Ты думаешь, что изменил природу отношения?
Здравствуйте, DarkGray, Вы писали:
DG>>>если тебе не нравится слово "направление", то что меняется при перестановке AxB => BxA, и каким это словом можно обозначить?
DG>ты не увиливай. ты на вопрос ответь.
Ответ на вопрос — ничего не меняется.
Здравствуйте, DarkGray, Вы писали:
DG>вообще понятие направления необходимо, для перехода от отношения к отображению.
Вообще-то отображение — это частный случай отношения. Если отношению направление не нужно, то и отображению тоже.
DG>если не вводит понятия направления (или аналога), то для отношения AxA вообще однозначно не перейдешь к отображению.
Что именно тебя смущает?
DG>>если не вводит понятия направления (или аналога), то для отношения AxA вообще однозначно не перейдешь к отображению. S>Что именно тебя смущает?
тем что в ряде случае при преобразовании отношения в "отображение": может получиться отображение, а в другом мультиотображение.
соответственно необходимо фиксировать берется вариант left-right или right-left.
зы
вообще, сейчас получается обратное.
сейчас я утверждаю, что понятие направления у несимметричной структуры(это как раз утверждается в комбинаторике графов) всегда есть (как ты мне до этого доказывал, что ad-hoc полиморфизм всегда есть), а ты утверждаешь что это свойство несущественное (потому что есть изоморфизм — "переворота" отношения)
но применение этого изоморфизма ограничено: пока отношение F AxA берется одно само по себе — этот изоморфизм применим.
если же взята композиция F AxA G AxA, то этот изоморфизм уже независимо к каждому F и G применить нельзя, а можно применить только одновременно ко всей композиции. И для данной композиции уже необходимо фиксировать: G по отношению к F взято как left-right(или как right-left), а F по отношению к G всято как left-right(или как right-left)
для закрепления материала можешь решить задачку:
сколько различных способов существует для композиции трех отношений Equality
сколько различных способов существует для композиции трех отношений Sqrt CxC (кажая пара имеет вид (c, sqrt c) для всего комплексного множества)
сколько различных способов существует для композиции трех произвольных отношений F CxC, G CxC, H CxC
S> Если отношению направление не нужно, то и отображению тоже.
не говори ереси.
отображение — это left-total right-unique relation. соответственно, если у тебя relation R имеет свойство left-total right-unique, но не имеет свойства right-total left-unique, то для данного отношения только вариант left-right можно перевести в отображение, вариант right-left в отображение перевести уже нельзя (необходима уже partial multifunction)
Здравствуйте, DarkGray, Вы писали:
S>>Что именно тебя смущает?
DG>тем что в ряде случае при преобразовании отношения в "отображение": может получиться отображение, а в другом мультиотображение. DG>соответственно необходимо фиксировать берется вариант left-right или right-left.
А какие направления ты выберешь для 3-отношения, для 5?
DG>зы DG>вообще, сейчас получается обратное. DG>сейчас я утверждаю, что понятие направления у несимметричной структуры(это как раз утверждается в комбинаторике графов) всегда есть (как ты мне до этого доказывал, что ad-hoc полиморфизм всегда есть), а ты утверждаешь что это свойство несущественное (потому что есть изоморфизм — "переворота" отношения)
Ты уже за меня начал тезисы выдавать. Так не пойдет.
DG>но применение этого изоморфизма ограничено: пока отношение F AxA берется одно само по себе — этот изоморфизм применим.
Какой изоморфизм? DG>если же взята композиция F AxA G AxA, то этот изоморфизм уже независимо к каждому F и G применить нельзя, а можно применить только одновременно ко всей композиции. И для данной композиции уже необходимо фиксировать: G по отношению к F взято как left-right(или как right-left), а F по отношению к G всято как left-right(или как right-left)
Ты что-то далеко убежал в дискуссии со мной, придумывая за меня ответы.
DG>для закрепления материала можешь решить задачку:
Я даже не понял, о чем ты, куда там закреплять.
Здравствуйте, DarkGray, Вы писали:
S>> Если отношению направление не нужно, то и отображению тоже.
DG>не говори ереси. DG> отображение — это left-total right-unique relation.
Не дури. left-total и right-unique не имеют отношения к направлению отношения. У отношения нет направления. Можешь заглянуть на руссую вики. Там функция вводится без left/right.
S>Не дури. left-total и right-unique не имеют отношения к направлению отношения. У отношения нет направления. Можешь заглянуть на руссую вики. Там функция вводится без left/right.