Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[107.21.176.63] |
|
Страницы: (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> ? Ни один из приведенных , типом voices является dynamic array constants или я хз какой он там на самом деле (в переводе по гугл транслейту это константы динамического массива ) Если я пишу следущее то ошибка компиляции 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 - никто не хотел отдельно от |