Delphi vs C++ vs C#
, ну и Java немножко, где-то ближе к старшему байту номеров страниц
![]() |
Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
|
| ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
| [216.73.216.156] |
|
|
Правила раздела:
| Страницы: (495) « Первая ... 341 342 [343] 344 345 ... 494 495 ( Перейти к последнему сообщению ) |
Delphi vs C++ vs C#
, ну и Java немножко, где-то ближе к старшему байту номеров страниц
|
Сообщ.
#5131
,
|
|
|
|
Цитата D_KEY @ А чего ты хотел? Перегрузка функций теоретически действительно скорее трындец, чем что-то хорошее, хотя бы потому, что вводит два "объекта" с одинаковыми именами но разными типами, а это вообще-то противоречит остальной части системы типов большинства языков. Я думаю, что это проблема "остальных языков", а вовсе не перегрузки функций ![]() Именно ![]() Ах, да, D_KEY, надо было SFINAE показать и включение/выключение функций с помощью enable_if |
|
Сообщ.
#5132
,
|
|
|
|
![]() ![]() interface NumC<A> { A add(A y); A mul(A y); A sub(A y); } interface FractionalC<A> extends NumC<A> { A div(A y); } class Probability implements FractionalC<Probability> { public final double value; public Probability(double val) { value = (val < 0.0) ? 0.0 : (val > 1.0) ? 1.0 : val; } public Probability add(Probability y) { return new Probability(value + y.value); } public Probability mul(Probability y) { return new Probability(value * y.value); } public Probability sub(Probability y) { return new Probability(value - y.value); } public Probability div(Probability y) { return new Probability(value / y.value); } } ![]() ![]() class NumC a where add :: a -> a -> a mul :: a -> a -> a sub :: a -> a -> a class NumC a => FractionalC a where div :: a -> a -> a data Probability = Probability { value :: Double } deriving (Show, Read, Eq) newProbability val | val < 0.0 = Probability 0.0 | val > 1.0 = Probability 1.0 | otherwise = Probability val instance NumC Probability where add x y = newProbability $ value x + value y mul x y = newProbability $ value x * value y sub x y = newProbability $ value x - value y instance FractionalC Probability where div x y = newProbability $ value x / value y отличия сугубо синтаксические. |
|
Сообщ.
#5133
,
|
|
|
|
Цитата MyNameIsIgor @ D_KEY, надо было SFINAE показать и включение/выключение функций с помощью enable_if ![]() Рано |
|
Сообщ.
#5134
,
|
|
|
|
Цитата MyNameIsIgor @ Вы, похоже, выделяете какой-то "главный шаблон с именем A". А такого не существует. Все специализации в общем-то равноправны. я выделяю шаблон как осязаемую сущность включенную в систему типов, как что-то строгое. но теперь я вижу, что это не так. в C++ по крайней мере. почему же? наоборот, это распространенное мнение. ничего оригинального =) |
|
Сообщ.
#5135
,
|
|
|
|
korvin, здесь ты скорее показываешь эмуляцию тайпкастов в Java через интерфейсы и дженерики, чем наоборот
Добавлено Цитата korvin @ я выделяю шаблон как осязаемую сущность включенную в систему типов, как что-то строгое. Это средство создания типов и функций. Цитата в C++ по крайней мере. Где-то еще есть шаблоны? Цитата наоборот, это распространенное мнение. ничего оригинального =) Какие причины для запрета перегрузки функций в языке, где функции не являются объектами? |
|
Сообщ.
#5136
,
|
|
|
|
Цитата D_KEY @ korvin, здесь ты скорее показываешь эмуляцию тайпкастов в Java через интерфейсы и дженерики, чем наоборот ![]() эм... нет. вполне обычное, распространенное использование дженериков. и так же вполне обыденное использование тайпклассов. как две капли воды. если в жабе убрать наследование классов, то будет вообще хаскелл-like =) Добавлено Цитата D_KEY @ Это средство создания типов и функций. Где-то еще есть шаблоны? в некотором смысле можно взять макросы (не сишные =)). кстати надо попробовать макросы в Typed Racket =) |
|
Сообщ.
#5137
,
|
|
|
|
Цитата korvin @ эм... нет. вполне обычное, распространенное использование дженериков. и так же вполне обыденное использование тайпклассов. как две капли воды. Тут скорее показана работа интерфейсов, чем дженериков Добавлено Цитата korvin @ в некотором смысле можно взять макросы (не сишные =)). Нельзя, ибо как я уже говорил, обработка шаблонов не выделяется в отдельную стадию даже на концептуальном уровне - это все происходит во время компиляции, что показывают примеры с перегрузкой функций, что приводил я, и с поиском имен, что приводил Qraizer. |
|
Сообщ.
#5138
,
|
|
|
|
Цитата D_KEY @ Где-то еще есть шаблоны? D же |
|
Сообщ.
#5139
,
|
|
|
|
Цитата MyNameIsIgor @ Цитата D_KEY @ Где-то еще есть шаблоны? D же ![]() Кстати, как он решает обсуждаемые вопросы? |
|
Сообщ.
#5140
,
|
|
|
|
Цитата D_KEY @ Кстати, как он решает обсуждаемые вопросы? Эммм?... А что здесь решать? ![]() Вообще, на сколько я знакомился с докой, там плюсовые шаблоны. |
|
Сообщ.
#5141
,
|
|
|
|
Цитата D_KEY @ Тут скорее показана работа интерфейсов, чем дженериков ![]() да ну? не хватает ключевого слова "generic"? ну так можно NumC и FractionalC переименовать в GenericNum и GenericFractional соответственно Добавлено Цитата D_KEY @ Нельзя, ибо как я уже говорил, обработка шаблонов не выделяется в отдельную стадию даже на концептуальном уровне - это все происходит во время компиляции а какая разница? впрочем макросы CL тоже обрабатываются во время компиляции, никаких отдельных стадий =) Добавлено Цитата korvin @ кстати надо попробовать макросы в Typed Racket =) гыгы ![]() ![]() (define-syntax template (syntax-rules (struct) ((_ name (typevar ...) (struct (typev field) ...)) (define-syntax name (syntax-rules () ((_ struct-name typevar ...) (struct: struct-name ((field : typev) ...)))))))) (template tfoo (T S) (struct (T x) (S y))) (tfoo foo Integer Float) (define f (foo 1 2.0)) ![]() ![]() > f - : foo #<foo> > foo - : (Integer Float -> foo) #<procedure:foo> > |
|
Сообщ.
#5142
,
|
|
|
|
Эх, что-то вас не в ту степь понесло.
korvin, шаблоны - это не(пробел)законченный тип. Законченным он получается только после подстановки всех параметров в точке использования. В этом-то и драма отношений между библиотеками и их пользователями - авторам нужно предоставить возможность пользователям доопределеять свойства и аттрибуты шаблона, но при этом обезопаситься от случайностей сайд-эффектов. Шаблонные сущности не оперируют типами и/или значениями, вместо этого они оперируют свойствами и аттрибутами типов и/или значений. Шаблону пофиг на тип объектов x и y; если ему нужно их сравнить, он может просто сделать x<y, т.е. он полагается на тот факт, что x и y умеют сравниваться оператором <. Если это не так, то этот тип не подходит, вот и всё; и ошибка компиляции тут будет закономерной. (Эх, ещё б концепты сюда ). А пользователь, увидев эту ошибку, может просто перегрузить operator<() (хотя было бы лучше, конечно, если б он заранее прочёл требования, предъявляемые к типу x и y в документации) и повторить попытку, теперь она будет успешной.С другой стороны, завышенные требования нежелательны, ибо сужают множество подходящих кандидатур. Неподходящие часто можно сделать таковыми, но это дополнительная работа для пользователя шаблона. И особенно обидная, если эта дополнительная работа так и не будет восстребована, а будет нужна только для компилябельности. Типичный пример - шаблон смарт-поинтеров, которые имеют у себя не только перегруженный operator* для разыменования указателя на объект, но и operator-> для разыменования указателя на классовый элемент (элемент структуры, если угодно). Когда смарт-поинтер юзается для класса, этот оператор полезен, но если шаблонным параметром в смарт-поинтер идёт не структурный тип, а к примеру массив, operator-> для него не просто не нужен, он невозможен, иначе будет семантическая ошибка, ибо для массивов он не определён грамматикой. Что делать? Правильно - определить в шаблоне смарт-поинтера "на всякий случай", но не использовать в программе. Последнее несложно - пользователь шаблона, в отличе от автора шаблона, знает его параметры, а значит и знает, какие операции могут над ним применяться, какие нет. Естественно, если читает мануалы. korvin, рассматривай "опциональные" методы интерфейса шаблонного класса как статический эквивалент абстрактных методов из динамического полиморфизма. Чистые методы всегда реализованы (не всегда програмистом, конечно), но пока не вызваны, программа корректна. Тут то же самое. Я не обязан реализовывать для типа объетов x и y оператор <, если не буду использовать часть шаблонной сущности, которой требуется их сравнивать. Но это я знаю и я учитываю, потому что я (а не автор шаблона) знаю конкретные свойства типа, который передаю параметром в используюмую шаблонную сущность, и я знаю, что из его интерфейса я собираюсь использовать, а что нет. В примере D_KEY-я, который он выше цитировал из книжки, не пользователю шаблона "повезло", что он не вызвал нереализованный элемент стратегии. Он её намерено не вызвал ввиду ненадобности, а шаблон и язык ему такую возможность дали, не обязывая реализовывать невосстребованные интерфейсы параметрического типа. В динамике ты обязан реализывать методы абстрактных классов просто тупо для того, чтобы скомпилилось. Будет ли перекрытое восстребовано, никого не интересует. |
|
Сообщ.
#5143
,
|
|
|
|
Цитата Qraizer @ В примере D_KEY-я, который он выше цитировал из книжки, не пользователю шаблона "повезло", что он не вызвал нереализованный элемент стратегии. Он её намерено не вызвал ввиду ненадобности, а шаблон и язык ему такую возможность дали, не обязывая реализовывать невосстребованные интерфейсы параметрического типа. да с автором класса все понятно, но что делать сторонним пользователям? писать наследников/обертки? Добавлено Цитата Qraizer @ В динамике ты обязан реализывать методы абстрактных классов просто тупо для того, чтобы скомпилилось. Будет ли перекрытое восстребовано, никого не интересует. да при чем тут динамика? я могу и в динамике сделать необязательность реализации, а в статичном хаскелле требуется _полностью_ инстанциировать тайпкласс для типа. иначе не скомпилится |
|
Сообщ.
#5144
,
|
|
|
|
Цитата korvin @ да с автором класса все понятно, но что делать сторонним пользователям? писать наследников/обертки? Зачем? Для чего? Какие обёртки? |
|
Сообщ.
#5145
,
|
|
|
|
Цитата MyNameIsIgor @ Зачем? Для чего? Какие обёртки? затем, что пользователь может хотеть пользоваться вашим классом как C<?>, а не как C<T> |