-
> Тимохов (26.08.2008 2:13:47) [47]
Тебя не обманывали, это в России сбывали остатки. Правда потом все равно обманули, глядя на Россию Борланд напечатал дополнительный тираж.
-
После того как выйдет SP1 (или 2) можно будет глянуть :) поэтому пока посидим на 7, Турбо...
-
> [56] ketmar © (26.08.08 07:45)
ну это уже в порядке вещей. GUI это цветочки, куда больше проблем с другими новшествами висты.
-
Анонимные методы ддо конца не понял - и так ведь работало с процедурными типами. Правда объектные / необъектные различались.
-
> Анонимные методы ддо конца не понял - и так ведь работало > с процедурными типами
Действительно кто то может дать толковое объяснение, чем отличаются?
-
>[64] Tricky (2008-08-26 17:56:00)не надо заводить идентификатор для каждого чиха. ну, и я так понимаю, что можно будет делать такое: Sort (a, b, function (i0, i1: xxx) begin return i0<i1; end); ну, надеюсь, что можно. %-) --- Understanding is not required. Only obedience.
-
> не надо заводить идентификатор для каждого чиха. ну, и я > так понимаю, что можно будет делать такое: > Sort (a, b, function (i0, i1: xxx) begin return i0<i1; end) > ; > ну, надеюсь, что можно. %-)
Скачал преальфу, действительно можно, правда без return :)
type
TMyFunc = reference to function(): string;
...
procedure TForm4.Button1Click(Sender: TObject);
begin
CallMe(function (): string begin Result := 'hello'; end)
end;
procedure TForm4.CallMe(F: TMyFunc);
begin
ShowMessage(F());
end; В общем, впечатления от среды положительные, хоть я и далеко не грубоко профессиональный разработчик. Сделали удобное переключение Debug/Release и возможность ставить опции проекта для обоих режимов сразу. Правда, подсказки по коду иногда порождают ошибки (довольно часто ему не нравится Result, особенно если его использовать как переменную цикла), но это спишем на недоальфу. С generic'ами вот только непонятно. Дабы опробовать этот инструмент, хотел написать самую очевидную вещь - список. TList<T> = class
private
FItems: array of T;
public
function IndexOf(Item: T): Integer;
end;
function TList<T>.IndexOf(Item: T): Integer;
var
LCount: Integer;
begin
LCount := FCount;
for Result := 0 to LCount - 1 do
if FItems[Result] = Item then
Exit;
Result := -1;
end; Вот тут на строчке с if'ом я и был послан: [Pascal Error] uGenerics.pas(213): E2015 Operator not applicable to this operand typeТо есть, оператор "=" для типа T не определен :(. Как красиво обойти данный неприятный казус я пока не придумал. Можно конечно заставить использующего класс вручать нам функцию для сравнения двух элементов списка (благо теперь есть эти анонимные методы или как их правильно называть), но очень не хотелось бы его обременять такой ерундой, так как для всех простых типов "=" вполне подойдет (а для record'ов его можно определить, жаль для классов вне дот нета все еще нельзя), и вроде логично было бы его использовать "по умолчанию". Если у кого-нибудь есть идеи, как красиво разрешить данную ситуацию, буду рад услышать. Эхх, еще бы доку нормальную по всем новым возможностям. Пока несбыточные мечты :).
-
Посмотри реализацию их TList<T>. Подключи generics.Collections. Опиши результат здесь.
-
Хотя http://www.xakep.ru/post/44864/default.asp?print=true+ Еще всплывают новые факты например запрещено использовать шаблоны в обычных процедурах и функциях.Я бы им поставил два с минусом за реализацию шаблонов. Передрать идеалогию с .NET. Что своих мозгов что ли нет! Запрет на использование оператора при работе с параметризованным параметром вызван ограничением IL набора, у которого инструкция ceq и ей подобные ограничены только определенными типами. int, F, & и O. оно и понятно поскольку неизвестно какую обертку оператора подставлять для сравнения типа. Например как сравнивать value типы и им подобные. Конечно есть способы, но они выбрали такой способ. Но здесь нет байкода. Все известно во время компиляции. Если это так. То просто огромный НЕЗАЧЕТ. Уж взяли бы идеалогию template из С++. Я в шоке и расстроен. НО здесь нет
-
Посмотрел. У них используется следующий интерфейс: IComparer<T> = interface
function Compare(const Left, Right: T): Integer;
end; Соответственно, при создании списка вы можете передать ему в конструкторе этот IComparer<T>, а можете и не передать. Если этот сравниватель не указан, то берется умолчательный: if FComparer = nil then
FComparer := TComparer<T>.Default; В этом самом Default вся woodoo magic и заключается. class function TComparer<T>.Default: IComparer<T>;
begin
Result := IComparer<T>(_LookupVtableInfo(giComparer, TypeInfo(T), SizeOf(T)));
end;
type
TDefaultGenericInterface = (giComparer, giEqualityComparer);
function _LookupVtableInfo(intf: TDefaultGenericInterface; info: PTypeInfo; size: Integer): Pointer;
var
pinfo: PVtableInfo;
begin
if info <> nil then
begin
pinfo := @VtableInfo[intf, info^.Kind];
Result := pinfo^.Data;
if ifSelector in pinfo^.Flags then
Result := TTypeInfoSelector(Result)(info, size);
if ifVariableSize in pinfo^.Flags then
Result := MakeInstance(Result, size);
end
else
begin
case intf of
giComparer: Result := Comparer_Selector_Binary(info, size);
giEqualityComparer: Result := EqualityComparer_Selector_Binary(info, size);
else
System.Error(reRangeError);
Result := nil;
end;
end;
end;
Чтобы пост влез в разумные рамки, я не стал здесь приводить всех используемых типов и констант, их тут целый ворох. В кратце получается так - для неизвестного типа в Generic'е можно вызвать TypeInfo(T) и получить о нем информацию. Далее, проанализировав эту информацию, можно для каждого типа написать свой сравниватель, что там и сделано. Если еще посчелкать с Ctrl+Click'ом, то можно найти и сами функции сравнения (указатели на них закопаны глубоко в константном массиве VtableInfo), вот например: function Compare_U1(Inst: Pointer; const Left, Right: Byte): Integer;
begin
if Left < Right then
Result := -1
else if Left > Right then
Result := 1
else
Result := 0;
end;
function Compare_U2(Inst: Pointer; const Left, Right: Word): Integer;
begin
if Left < Right then
Result := -1
else if Left > Right then
Result := 1
else
Result := 0;
end; Резюме такое: Code Gear это уже за нас написал, и хотя вариант с нормальной поддержкой оператора "=" для классов, и его использования в этой ситуации по мне был бы ничуть не хуже, я вполне удовлетворен. В моем случае "самопального" TList, я должен просто вызвать уже написанный TComparer<T>.Default, и не изобретать страшных велосипедов, а лучше дать возможность пользователю класса этот самый IComparer указать самому, если он того возжелает.
-
> В этом самом Default вся woodoo magic и заключается.
Да это их любимые выкрутасы. Но зачем? Я так понимаю, они хотят унифицировать x86 код для любых object типов. То есть фактически будет использован тот же код, если параметризованный параметр будет object типа. А различный код для value типов. Все как в .NET.
Это что же получается для того, чтобы сравнить элементы они во первых должны быть одного и того же типа. А во вторых, чтобы сделать такую ничтожную операцию как сравнение нужно вызвать внешний код через таблицу VMT интерфейса, вместо того чтобы сделать просто inline кода сравнения для известного типа. Это, чтобы пробежаться по коллекции
Поэтому от сюда правила. Следуют избегать их неэффективные выкрутасы. А делать прямое сравнение. Например
List<T>.Items[5]=5, что будет эффективней.
Понятно? :)
-
Теперь понятно зачем они ввели виртуальный метод в Tobject под названием equals.
-
Servy © (26.08.08 23:22) [69]
Посмотри пожалуйста перечисление с giComparer, такие они еще туда операции вставили?
_LookupVtableInfo такого небыло раньше в system.pas
Что же смотрю интроспекция расширяется, значит будет что расковырять в ближайшее время(хоть это радует).
-
Кстати еще одна мелкая но приятная фишка - подсказки (в случае, если они не разваливаются с ощибками ^_^) при использовании generic класса сразу показывают подставляемый тип, что довольно удобно (в студии от майкрософта, где как вы написали IndexOf(Item: T) так и увидите свое T в IntelSence). Вот скриншот, а то непонятно наверное :) http://www.valar.ru/upload/jpg/0808/1219776625_screen.htm > Еще всплывают новые факты например запрещено использовать > > шаблоны в обычных процедурах и функциях.
Ну, может и нельзя, мне не попадалось таких по крайней мере. Однако, никто не может запретить использовать то же решение, что и сами Code Gear использовали со своим Compare'ом: TFuncWrapper<T> = class
class function MyFunc(Param: T);
end;
И использовать: TFuncWrapper<string>.MyFunc('Привет!'); Не слишком коротко, да и класс нужно объявлять, но меня на данный момент вполне устроит, тем более широкого применения функциям с template'ами я не вижу. Ах да, ну и Char теперь действительно 2 байта, чудо свершилось :).
-
> _LookupVtableInfo такого небыло раньше в system.pas
Оно в Generics.Defaults > Посмотри пожалуйста перечисление с giComparer, такие они > еще туда операции вставили?
Вот вам самые эти занимательные модули (Generics.Collections и Generics.Defaults) http://slil.ru/26091378 (12 Кб). Смотрите на здоровье, потому как ваш вопрос был мною непонят :)
-
> Servy © (26.08.08 23:44) [73] > Кстати еще одна мелкая но приятная фишка - подсказки
Я думаю это так и должно быть. Что еще можно по другому? :)
-
> Servy © (26.08.08 23:50) [74]
Спасибо. Я скачал prerelease но требует от меня какую то лиценцию на Ribbon controls, вообщем зашел на microsoft, там им нужно что то отправить чтобы они тебе прислали лицензию. Вообщем я послал их ... Есть способ проще? Ты откуда слил?
-
> Ты откуда слил?
С упомянутого здесь торрентс ру.
-
TDefaultGenericInterface = (giComparer, giEqualityComparer);
Направление их мысли мне понятно. Вычленение набора операций в отдельную сущность. Хотя их де факто две giComparer, giEqualityComparer.
Теперь вопрос на один миллион долларов как быть с остальными операторами + - и т.д. :))))))))))))
-
> Я думаю это так и должно быть. Что еще можно по другому? > :)
А в Microsoft Visual Studio, с которой мне приходиться иметь дело на работе, не так. Все-таки есть разница между скрином в [73] и http://www.valar.ru/upload/jpg/0808/1219778614_screen2.htm (аналогичная подсказка в MVS). Хотя, все это само собой мелочи. > Теперь вопрос на один миллион долларов как быть с остальными > операторами + - и т.д. :))))))))))))
Видимо, нам придется обойтись без оных. Правда, темплейты явно теряют часть своей привлекательности... Но хоть теперь есть готовые и (я надеюсь) отлаженные list и map (тут они его вроде dictionary назвали), в которые можно без зазрения совести пихать record'ы, и не мучиться с созданием/убийством обекътов там, где они не нужны. А также без необходимости тип приводить руками при каждом обращении, либо наследника от TList писать для каждого чиха. Нет, все таки наш арсенал немного возрос, а скорость компиляции вроде не пострадала, что ни может не радовать.
|