
![]() |
Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
|
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[216.73.216.207] |
![]() |
|
Страницы: (2) 1 [2] все ( Перейти к последнему сообщению ) |
Сообщ.
#16
,
|
|
|
На апдейтовом делфи рио, приведеный там код с TDictionary пашет. По моему примеру я немного ошибся с терминологией по массивам уже больно запутано в делфи ![]() Ща сек все разберу по полочкам... Итак давайте разберем их на моем примере. Есть статические и динамческие массивы: ![]() ![]() type TVoices = array [1..3] of IVoice; begin // dynamic array var voices:= TArray<IVoice>.Create(TDog.Create, TCat.Create, TDog.Create); // static array var voices: TVoices; voices[1] := TDog.Create; voices[2] := TCat.Create; voices[3] := TDog.Create; .... а также есть так называемые открытые массивы, они существуют только как параметры, например array of T в функции Map: ![]() ![]() class function TArrayHelper.Map<T, R>(const Values: array of T; //<-- open array parameter AProc: TMapProc<T, R>): TArray<R>; в него можно передать как статик так и динамик массив ![]() ![]() var funcs := TArray.Map<IVoice, TFunc<string>>(voices, //<-- dynamic or static array ..... У меня же по коду идет ни тот ни другой ![]() Какой? На новых делфи (не знаю с какой точно версии), но в Рио можно делать такую шутку: ![]() ![]() var voices:= [TDog.Create, TCat.Create, TDog.Create]; это объявление динамического массива констант (dynamic array constant), не путайте с array of const. array of const - это особый тип открытого массива, который задается как параметр функции, пример тому знаменитая функция Format ![]() Так вот я передаю динамический массив констант voices в функцию Map, которая ждет либо динамический либо статический массив, наш же имеет другой тип! Чтобы решить траблу можно сделать как я привел выше в примере, т.е указать явно тип переменой и уже потом инициализировть массив ![]() ![]() var voices: TArray<IVoice> := [TDog.Create, TCat.Create, TDog.Create]; ... или сразу создать динамич. массив через TArray<T>.Create ![]() ![]() var voices:= TArray<IVoice>.Create(TDog.Create, TCat.Create, TDog.Create); ... |
![]() |
Сообщ.
#17
,
|
|
Цитата Cfon @ У меня же по коду идет ни тот ни другой Какой? На новых делфи (не знаю с какой точно версии), но в Рио можно делать такую шутку: var voices:= [TDog.Create, TCat.Create, TDog.Create]; это объявление динамического массива констант (dynamic array constant) У меня нету Rio, не могу проверить. Сразу возникает вопрос, какой тип у переменной voices? TArray<TVarRec>? TArray<TObject>? TArray<IVoice> ? Где нить описана логика вывода типа массива? Термин "dynamic array constant" не разу не слышал. |
Сообщ.
#18
,
|
|
|
Цитата jack128 @ У меня нету Rio, не могу проверить. Сразу возникает вопрос, какой тип у переменной voices? TArray<TVarRec>? TArray<TObject>? TArray<IVoice> ? Ни один из приведенных ![]() ![]() ![]() Если я пишу следущее то ошибка компиляции ![]() ![]() var voices:= [TDog.Create, TCat.Create, TDog.Create]; var funcs := TArray.Map<IVoice, TFunc<string>>(voices, //<-- вот на эту строчку function (v: IVoice; i: integer): TFunc<string> begin .. end); // [dcc32 Error]: E2010 Incompatible types: 'array of IVoice' and 'Dynamic array' Что тут 'array of IVoice' а что 'Dynamic array' я хз ![]() по идее voices это 'Dynamic array', а параметр функции это 'array of IVoice' Цитата jack128 @ Где нить описана логика вывода типа массива? Термин "dynamic array constant" не разу не слышал. Вот тут я нашел про них http://rvelthuis.de/articles/articles-openarr.html Да еще забыл упомянуть про конструкторы открытого массива (open array constructor) они напоминают форму dynamic array constants, но передаются сразу как параметры функции, моем случае будет так ![]() ![]() var funcs := TArray.Map<IVoice, TFunc<string>>([TDog.Create, TCat.Create, TDog.Create], //<-- open array constructor function (v: IVoice; i: integer): TFunc<string> begin .... end); В такой форме код компилица. А не стоп, не только как параметр функции, но и вот тут вроде как тоже open array constructor ![]() ![]() ![]() var voices: TArray<IVoice> := [TDog.Create, TCat.Create, TDog.Create]; //<-- open array constructor Самое не понятное для меня было следущее: Я поначалу не сразу просек про параметр открытый массив (open array parameter) ![]() ![]() class function TArrayHelper.Map<T, R>(const Values: array of T; //<-- open array parameter AProc: TMapProc<T, R>): TArray<R>; ... я думал что это одно и тоже что и ![]() ![]() class function TArrayHelper.Map<T, R>(const Values: TArray<T>; //<-- dynamic array parameter AProc: TMapProc<T, R>): TArray<R>; ... поскольку TArray<T> описан как ![]() ![]() type TArray<T> = array of T но приведенный выше пример является динамич. массивом, а не открытым массивом. Разница их в том как я уже писал выше в открытый массив можно передать и статич.массив и динамич.массив и конструктор открытого массива! Ой *бать замутили ![]() ![]() |
![]() |
Сообщ.
#19
,
|
|
Цитата Cfon @ Где нить описана логика вывода типа массива? Термин "dynamic array constant" не разу не слышал. Вот тут я нашел про них http://rvelthuis.de/articles/articles-openarr.html в примере из статьи как раз все понятно, там явно указан тип переменной: ![]() ![]() var MyDynArray: array of Integer; // безымянный дин массив интов begin MyDynArray := [17, 325, 11]; В твоем случае ж случае тип переменной как то выводится компилятором, вот мне и интересно как. Цитата Cfon @ типом voices является dynamic array constants Забьем пока на тип массива, хотя бы с типом элемента массива разобраться бы. ![]() ![]() var voices:= [TDog.Create, TCat.Create, TDog.Create]; voices[0].Free; // компилируется ?? voices[1]._AddRef(); // компилируется? var x := voices[1000]; // компилируется ? |
Сообщ.
#20
,
|
|
|
Цитата jack128 @ Забьем пока на тип массива, хотя бы с типом элемента массива разобраться бы. ![]() ![]() var voices:= [TDog.Create, TCat.Create, TDog.Create]; voices[0].Free; // компилируется ?? voices[1]._AddRef(); // компилируется? var x := voices[1000]; // компилируется ? ![]() ![]() voices[0].Free; // компилируется ?? да voices[1]._AddRef(); // компилируется? нет [dcc32 Error]: E2003 Undeclared identifier: '_AddRef' var x := voices[1000]; // компилируется ? да все кроме второго компиляца и без рантайм ошибок. Если посмотреть на список Code Insight для voices[i], то он напоминает TObject, но если я передаю voices в процедуру: ![]() ![]() procedure Test(A: TArray<TObject>); begin end; begin var voices:=[TDog.Create, TCat.Create, TDog.Create]; Test(voices); end; // [dcc32 Error]: E2010 Incompatible types: 'System.TArray<System.TObject>' and 'Dynamic array' Ради интереса посмотрел в простом цикле ![]() ![]() var voices:=[TDog.Create, TCat.Create, TDog.Create]; for var I := 0 to High(voices) do begin Writeln(voices[i].ClassName); end; // Output: // TDog // TCat // TDog Пробую привести к IVoice ошибка пишет что voice[i] - TObject ![]() ![]() ![]() var voices:=[TDog.Create, TCat.Create, TDog.Create]; for var I := 0 to High(voices) do begin Writeln(IVoice(voices[i]).Voice); end; // [dcc32 Error]: E2010 Incompatible types: 'IVoice' and 'TObject' Прокатило если определить открытый массив TObject ![]() ![]() ![]() procedure Test(A: array of TObject); begin for var I := 0 to High(A) do begin Writeln(A[i].ClassName); end; end; begin Test(voices); // Output: // TDog // TCat // TDog end. Какие выводы? voices это array of TObject ![]() |
Сообщ.
#21
,
|
|
|
А теперь хардкор
![]() Предлагаю вашему вниманию версию примера с функцией Reduce. Добавляем поддержку Reduce к нашему TArrayHelper. Что делает Reduce? Она обрабатывает исходный массив и сводит (reduce) к другому типу потенциально любому типу! Давайте посмотрим как это выглядит: ![]() ![]() type TForEachProc<T> = reference to procedure (Value: T; Index: Integer); TMapProc<T, R> = reference to function (Value: T; Index: Integer): R; TReduceProc<T, R> = reference to function (Accumulator: R; Value: T): R; TArrayHelper = class helper for TArray class procedure ForEach<T>(const Values: array of T; AProc: TForEachProc<T>); static; class function Map<T, R>(const Values: array of T; AProc: TMapProc<T, R>): TArray<R>; static; class function Reduce<T, R>(const Values: array of T; AProc: TReduceProc<T, R>; InitValue: R): R; static; end; { TArrayHelper } .... class function TArrayHelper.Reduce<T, R>(const Values: array of T; AProc: TReduceProc<T, R>; InitValue: R): R; begin Result := InitValue; for var I := 0 to High(Values) do Result := AProc(Result, Values[i]); end; begin var voices:= TArray<IVoice>.Create(TDog.Create, TCat.Create, TDog.Create); var funcs := TArray.Reduce<IVoice, TArray<TFunc<string>>>(voices, function (accum: TArray<TFunc<string>>; value: IVoice): TArray<TFunc<string>> begin Result:= accum + [function: string begin Result := value.Voice end]; end, []); // test for var fn in funcs do Writeln(fn()); Readln; end. Результат тот же, но пришлось моск изрядно напрячь, код явно не для слабонервных ![]() Хотя для хакселистов он покажется простым ![]() Понятно что данную задачу Map решает проще, но сам по себе Reduce пригодиться во многих других задачах где Map будет бессилен. А Reduce это такой швейцарски нож решит любую задачу. |
Сообщ.
#23
,
|
|
|
Вообще насчет адресов методов и прочего, вот как вариант
![]() ![]() var voices: TArray<IVoice>; m: TMethod; ob: TObject; begin ob := voices[0] as TAnimal; m.Data := (ob); m.Code := (ob).MethodAddress('Voice'); memLog.Lines.Add(TFuncOfObj<string>(m)()); TMethod самодостаточный (содержит как адрес метода, так и адрес самого объекта). Единственное, что у меня почему-то MethodAddress возвращает nil даже со включенным RTTI, хотя нигде нет упоминаний, что этой функции вообще требуются какие-то условия. Вот тут инфа с примерами https://stackoverflow.com/questions/4186458...red-in-a-string |
Сообщ.
#24
,
|
|
|
Я ее давно скачал, чтобы в перспективе поюзать DI container ![]() Функционал енумератора Spring4D смотрел.. пока туман ![]() Доков нет плохо, как я понял там Select аналог Map? Цитата Fr0sT @ Вообще насчет адресов методов и прочего, вот как вариант Что то мудрено, через анонимку то изичи ![]() |
Сообщ.
#25
,
|
|
|
Варик на Spring4D
![]() ![]() ![]() uses Spring.Collections; begin var voices := TArray<IVoice>.Create(TDog.Create, TCat.Create, TDog.Create); var funcs := TEnumerable.Select<IVoice, TFunc<string>>( TCollections.CreateList<IVoice>(voices), function (v: IVoice): TFunc<string> begin Result:= function: string begin Result := v.Voice; end; end); // test for var fn in funcs do Writeln(fn()); Readln; end. |
Сообщ.
#26
,
|
|
|
Цитата Cfon @ Функционал енумератора Spring4D смотрел.. пока туман ![]() Доков нет плохо, как я понял там Select аналог Map? А все нашел примеры, это шарповый LINQ Enumerable один в один ![]() https://docs.microsoft.com/en-us/dotnet/api/system.linq.enumerable?view=netframework-4.7.2 Скомуниздили из линка энумератор спринги ![]() |
Сообщ.
#27
,
|
|
|
А зачем, собственно, сохранять методы в отрыве от объектов?
|
![]() |
Сообщ.
#28
,
|
|
Цитата Fr0sT @ А зачем, собственно, сохранять методы в отрыве от объектов? Какие методы от каких объектов? |
Сообщ.
#29
,
|
|
|
Voice. От созданных
|
![]() |
Сообщ.
#30
,
|
|
Цитата Fr0sT @ Voice. От созданных Э-э-э, я думал мы про Enumerable шарповский уже говорим. По поводу Voice - никто не хотел отдельно от |