Delphi vs C++ vs C#
, ну и Java немножко, где-то ближе к старшему байту номеров страниц
![]() |
Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
|
| ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
| [216.73.216.192] |
|
|
Правила раздела:
| Страницы: (495) « Первая ... 423 424 [425] 426 427 ... 494 495 ( Перейти к последнему сообщению ) |
Delphi vs C++ vs C#
, ну и Java немножко, где-то ближе к старшему байту номеров страниц
|
Сообщ.
#6361
,
|
|
|
|
Да решает же. Дженерик выполняет роль проверяющего, что мы получаем списки одного типа, т.е. одинаковой длины. А затирание типа спасает от бесконечного инстанцирования - как и в хаскеле. P.S. Уважаемый товарищ, который будет одобрять сей пост, мне долго ещё на премоде париться то? Вроде как уже давно должен был кончиться. |
|
Сообщ.
#6362
,
|
|
|
|
Цитата MyNameIsIgor @ Дженерик выполняет роль проверяющего, что мы получаем списки одного типа Т.е.: ![]() ![]() _main(n-1, i+1, new Cons<A>(2*i+1,first), new Cons<Cons<A>>(i*i, new Cons<A>(i, second))); Не скомпилируется? |
|
Сообщ.
#6363
,
|
|
|
|
Цитата D_KEY @ Не скомпилируется? Нет. Компилятор на входе дженерика проверит совпадение типов. |
|
Сообщ.
#6364
,
|
|
|
|
Проверил в mono, не компилируется.
Пойду думать на тему того, что до сих пор до конца не понимал дженерики |
|
Сообщ.
#6365
,
|
|
|
|
Цитата MyNameIsIgor @ А в Haskell'е не так что ли? Там так же конструирование списка происходит симметрично. Это лишь для примера. Можно и несимметрично создать два списка одинаковой длины. Цитата MyNameIsIgor @ Если я не прав, то скажите, какого типа будет список длиной, введённой пользователем? Как написать этот тип в программе? Естественно компилятор никак не может проверить данные, введенные извне. Однако, если пойти дальше, к зависимым типам (MLTT), компилятор в таких случаях просто будет требовать наличия проверки равенства длины и соответственно в ветке успешной проверки позволять производить нужные действия (без кастов, afaik). Это Примерно как в джаве (ну или в IDEA) компилятор выдает предупреждение при отсутствии проверки перед кастом: ![]() ![]() Object x; SomeObject y; x = new SomeObject(); y = (SomeObject) x; и рекомендует вставить проверку: ![]() ![]() Object x; SomeObject y; x = new SomeObject(); if (x instanceof SomeObject) { y = (SomeObject) x; } Только в джаве это лишь предупреждение, для специального случая, причем иногда плохо совмещаемое с дженериками. |
|
Сообщ.
#6366
,
|
|
|
|
Цитата korvin @ Можно и несимметрично создать два списка одинаковой длины. Ok. Какой тип будет у списка, длина которого вводится пользователем? |
|
Сообщ.
#6367
,
|
|
|
|
Цитата D_KEY @ Т.е.: ![]() ![]() _main(n-1, i+1, new Cons<A>(2*i+1,first), new Cons<Cons<A>>(i*i, new Cons<A>(i, second))); Не скомпилируется? Дык A != Cons<A>, потому и не компилируется. В дженериках же параметры типа должны быть эквивалентны: ![]() ![]() class Foo<A> { public static void foo (A x, A y); } типы параметров x и y должны быть эквивалентны или являться субтипами A. Но ведь в нашей задаче субтипирования нет (Cons<Cons<A>> не является субтипом Cons<A>). Или я чего-то не понимаю? Кстати в C# же вроде типы не стираются. |
|
Сообщ.
#6368
,
|
|
|
|
В общем, код с c# в дельфи вроде перенесся: ![]() ![]() type TScalarProduct<T> = class function ScalarProduct(Second: T): Integer; virtual; abstract; end; TNil = class(TScalarProduct<TNil>) public function ScalarProduct(Second: TNil): Integer; override; end; TCons<T: TScalarProduct<T>> = class(TScalarProduct<TCons<T>>) private FValue: Integer; FTail: T; public constructor Create(Value: Integer; Tail: T); function ScalarProduct(Second: TCons<T>): Integer; override; property Value: Integer read FValue write FValue; property Tail: T read FTail write FTail; end; TTest<T: TScalarProduct<T>> = class public class function Main(n, i: Integer; First, Second: T): Integer; end; { TNil } function TNil.ScalarProduct(Second: TNil): Integer; begin Result := 0; end; { TCons<T> } constructor TCons<T>.Create(Value: Integer; Tail: T); begin FValue := Value; FTail := Tail; end; function TCons<T>.ScalarProduct(Second: TCons<T>): Integer; begin Result := Value * Second.Value + Tail.ScalarProduct(Second.Tail); end; { TTest<T> } class function TTest<T>.Main(n, i: Integer; First, Second: T): Integer; begin if n = 0 then Result := First.ScalarProduct(Second) else begin Result := TTest<TCons<T>>.Main(n - 1, i + 1, TCons<T>.Create(2 * i + 1, First), TCons<T>.Create(i * i, Second)); // Works //Result := TTest<TCons<T>>._Main(n - 1, i + 1, First, // TCons<T>.Create(i * i, Second)); // Doesn't work end; end; |
|
Сообщ.
#6369
,
|
|
|
|
Все нет времени написать давно обещанный код через абстрактные классы. В общем суть в том, что сама рекурсивная функция принимает экземпляры абстрактных классов, а вот при очередном вызове вновь сконструированные списки проверяются на равентсов типов.
Сразу скажите, если что не так |
|
Сообщ.
#6370
,
|
|
|
|
Цитата korvin @ Это Примерно как в джаве (ну или в IDEA) компилятор выдает предупреждение при отсутствии проверки перед кастом: в Kotlin это будет в язык встроено: ![]() ![]() fun getStringLength(obj : Any) : Int? { // Any - это Object if (obj is String) return obj.length // no cast to String is needed return null } |
|
Сообщ.
#6371
,
|
|
|
|
Цитата MyNameIsIgor @ Ok. Какой тип будет у списка, длина которого вводится пользователем? Несимметрично != вводится пользователем Добавлено Цитата jack128 @ в Kotlin это будет в язык встроено: ![]() ![]() fun getStringLength(obj : Any) : Int? { // Any - это Object if (obj is String) return obj.length // no cast to String is needed return null } Да, я знаю, в Kotlin'е много чего хорошего. |
|
Сообщ.
#6372
,
|
|
|
|
Цитата korvin @ Цитата MyNameIsIgor @ Ok. Какой тип будет у списка, длина которого вводится пользователем? Несимметрично != вводится пользователем Ну то есть проверить на соответствие все-равно не получится? Т.е. на практике польза просто нулевая? |
|
Сообщ.
#6373
,
|
|
|
|
Цитата D_KEY @ Ну то есть проверить на соответствие все-равно не получится? Т.е. на практике польза просто нулевая? Всмысле? Ты о чем? Добавлено Польза ровно в том же, в чем и статической типизации. |
|
Сообщ.
#6374
,
|
|
|
|
Цитата korvin @ Цитата D_KEY @ Ну то есть проверить на соответствие все-равно не получится? Т.е. на практике польза просто нулевая? Всмысле? Ты о чем? Я хотел бы посмотреть на независимое конструирование списков с сохранением возможности проверки соответствия типов. Мне показалось, ты сказал, что это возможно. Добавлено Цитата korvin @ Польза ровно в том же, в чем и статической типизации. Я не увидел пользы в примере с двумя списками. |
|
Сообщ.
#6375
,
|
|
|
|
Цитата D_KEY @ Я хотел бы посмотреть на независимое конструирование списков с сохранением возможности проверки соответствия типов. Мне показалось, ты сказал, что это возможно. Да пожалуйста: ![]() ![]() xs = Cons 1 $ Cons 2 $ Cons 3 Nil ys = Cons 1 $ Cons 2 Nil списки построены независимо, при этом имеют разные типы, поэтому не пройдут в (scalarProduct xs ys) еще на этапе компиляции Добавлено Цитата D_KEY @ Я не увидел пользы в примере с двумя списками. Почему? Попробуй абстрагироваться от способа создания списков. Суть в том, что сигнатура функции test' (и scalarProduct) не позволит применить ее к двум спискам разной длины, на этапе компиляции. |