На главную
ПРАВИЛА FAQ Помощь Участники Календарь Избранное DigiMania RSS
msm.ru
! ПРАВИЛА РАЗДЕЛА · FAQ раздела Delphi · Книги по Delphi
Пожалуйста, выделяйте текст программы тегом [сode=pas] ... [/сode]. Для этого используйте кнопку [code=pas] в форме ответа или комбобокс, если нужно вставить код на языке, отличном от Дельфи/Паскаля.
Следующие вопросы задаются очень часто, подробно разобраны в FAQ и, поэтому, будут безжалостно удаляться:
1. Преобразовать переменную типа String в тип PChar (PAnsiChar)
2. Как "свернуть" программу в трей.
3. Как "скрыться" от Ctrl + Alt + Del (заблокировать их и т.п.)
4. Как прочитать список файлов, поддиректорий в директории?
5. Как запустить программу/файл?
... (продолжение следует) ...

Вопросы, подробно описанные во встроенной справочной системе Delphi, не несут полезной тематической нагрузки, поэтому будут удаляться.
Запрещается создавать темы с просьбой выполнить какую-то работу за автора темы. Форум является средством общения и общего поиска решения. Вашу работу за Вас никто выполнять не будет.


Внимание
Попытки открытия обсуждений реализации вредоносного ПО, включая различные интерпретации спам-ботов, наказывается предупреждением на 30 дней.
Повторная попытка - 60 дней. Последующие попытки бан.
Мат в разделе - бан на три месяца...
Модераторы: jack128, D[u]fa, Shaggy, Rouse_
  
> Непонятки
    Туплю! :whistle:
    непойму как сохранить адреса виртуальных фунций. Выбрасывает ошибку 'Incompatible types: 'System.SysUtils.TFunc<System.TFunc<System.string>' and 'string''
    ExpandedWrap disabled
      type
        IVoice = interface
          function Voice: string;
        end;
       
        TAnimal = class abstract (TInterfacedObject)
        private
          FName: string;
        public
          property Name: string read FName write FName;
        end;
       
       
        TDog = class(TAnimal, IVoice)
        public
          function Voice: string;
        end;
       
        TCat = class(TAnimal, IVoice)
        public
          function Voice: string;
        end;
       
      { TDog }
       
      function TDog.Voice: string;
      begin
        Result:= 'Arf-Arf!';
      end;
       
      { TCat }
       
      function TCat.Voice: string;
      begin
        Result:= 'Meow-Meow!';
      end;
       
      var
        voices: TArray<IVoice>;
        funcs: TArray<TFunc<string>>;
        I: Integer;
      begin
        voices:= [TDog.Create, TCat.Create, TDog.Create];
        SetLength(funcs, Length(voices));
       
        for I := 0 to High(voices) do
          funcs[i]:= voices[i].Voice;  //<--- это вызов, а надо сохранить адрес функции    
        Readln;
      end.

    Хелп плз! :whistle:
    "What I cannot create, I don't understand" Richard Feynman.
    https://github.com/Cfon/
    :D
      А вот если убрать интерфейс IVoice и заюзать абстрактный класс TAnimal то все пашет, адреса сохраняются! :wall:
      ExpandedWrap disabled
        type
          TAnimal = class abstract
          private
            FName: string;
          public
            function Voice: string; virtual; abstract;
            property Name: string read FName write FName;
          end;
         
         
          TDog = class(TAnimal)
          public
            function Voice: string; override;
          end;
         
          TCat = class(TAnimal)
          public
            function Voice: string; override;
          end;
         
        { TDog }
         
        function TDog.Voice: string;
        begin
          Result:= 'Arf-Arf!';
        end;
         
        { TCat }
         
        function TCat.Voice: string;
        begin
          Result:= 'Meow-Meow!';
        end;
         
        var
          animals: TArray<TAnimal>;
          funcs: TArray<TFunc<string>>;
          I: Integer;
        begin
          animals:= [TDog.Create, TCat.Create, TDog.Create];
          SetLength(funcs, Length(animals));
         
          for I := 0 to High(animals) do
            funcs[i]:= animals[i].Voice; //<--- а вот так все пучком!
         
          // тест
          for I := 0 to High(funcs) do
            Writeln(funcs[i]());
         
          Readln;
        end.

      Я в непонятках :wall:
      Где я не доучил Объект Паскаль? :wacko:
      Кстати учу по книжке моего кента Марко Кента :lool:
      Сообщение отредактировано: Cfon -
      "What I cannot create, I don't understand" Richard Feynman.
      https://github.com/Cfon/
      :D
        Cfon
        Это косяк эмбаркодеров. Они толком не за документировали и как следствие толком не закодировали.
        Правильный обед должен состоять из 5 блюд приготовленных из 33 ингредиентов.
          Цитата Pavia @
          Cfon
          Это косяк эмбаркодеров. Они толком не за документировали и как следствие толком не закодировали.

          Решил их косяк через анонимку :D
          ExpandedWrap disabled
            begin
              voices:= [TDog.Create, TCat.Create, TDog.Create];
              SetLength(funcs, Length(voices));
             
              for I := 0 to High(voices) do
                (procedure (i: integer)  //<--- iife
                  funcs[i]:= function: string //<--- anonimous function
                  begin
                    Result := voices[i].Voice;
                  end;
                end)(i);
             
              for I := 0 to High(funcs) do
                Writeln(funcs[i]());
             
              Readln;
            end.



          в JS стиле :D
          ExpandedWrap disabled
            begin
              var voices: TArray<IVoice>:= [TDog.Create, TCat.Create, TDog.Create];
              var funcs: TArray<TFunc<string>>;
             
              SetLength(funcs, Length(voices));
             
              for var I := 0 to High(voices) do
                (procedure (i: integer)
                 begin
                  funcs[i]:= function: string
                    begin
                      Result := voices[i].Voice;
                    end;
                 end)(i);
             
              for var I := 0 to High(funcs) do
                Writeln(funcs[i]());
             
              Readln;
            end.

          похоже тока в JS не надо указывать типы :D
          да и память не надо в ручную выделять :D

          ПС. Меня за уши теперь от Делфи не отянуть :lool:
          Формочки набиваются на раз два + код паскаля простой, легко читаемый, это просто мечта прогера :D
          Сообщение отредактировано: Cfon -
          "What I cannot create, I don't understand" Richard Feynman.
          https://github.com/Cfon/
          :D
            ExpandedWrap disabled
              for var I := 0 to High(voices) do
                  (procedure (i: integer)  //<--- iife
                    funcs[i]:= function: string //<--- anonimous function
                    begin
                      Result := voices[i].Voice;
                    end;
                  end)(i);

            Отдельно хочу пояснить про iife (самовызываемая функция) во втором цикле for, она создает локальную область видимости. Зачем? Затем чтобы анонимная функция сохранила переменную i в ней!
            Я хз почему, но анонимка не замыкает локальную переменную i цикла for! Мои эксперементы с ней показали что она удалятся после цикла :whistle:
            В итоге если не создать вручную локалку мы имеем эксепшен при доступе к массиву funcs. Наверно очередной косяк Эмбаркадэро :wacko:

            А вот на JS найди отличия :D
            ExpandedWrap disabled
              for (var i=0; i < voices.length; i++)
                  (function (i) { //<--- iife
                    funcs.push( function () { //<--- anonimous function
                      return voices[i].Voice;
                    }
                  })(i);
            Сообщение отредактировано: Cfon -
            "What I cannot create, I don't understand" Richard Feynman.
            https://github.com/Cfon/
            :D
              Цитата Cfon @
              Мои эксперементы с ней показали что она удалятся после цикла
              В итоге если не создать вручную локалку мы имеем эксепшен при доступе к массиву funcs.

              Тикет qc создал надеюсь? Я б проголосовал.
              Не каждая серая масса имеет что-то общее с мозгом (с) Станислав Ежи Лец
                Цитата jack128 @
                Цитата Cfon @
                Мои эксперементы с ней показали что она удалятся после цикла
                В итоге если не создать вручную локалку мы имеем эксепшен при доступе к массиву funcs.

                Тикет qc создал надеюсь? Я б проголосовал.

                Упс, пардон ми :D
                Я поспешил с выводами переменная i не удалятся, замыкание есть, но все 3 вызова в цикле захватывают одну и туже i и итоге при обращении у массиву функций идет обращение по индексу i=3 что ведет к эксепшену обращение за пределы массива. Похожая ситуация есть в JS тока там var i определенная в цикле имеет глобальную область действия, а в Delphi она локальная. Короче тут все без косяков, это просто фича цикла for и анонимок. Переменные захватываются по ссылке, а не по значению, чтобы решить траблу надо заюзать iife создавая на каждой итерации новую локалку. В JS ввели let для определения локальной переменной, как она работает я не разбрал, кажись анонимки захватывают ее по значению точно не помню, потому в JS можно решить это так :)
                ExpandedWrap disabled
                  for (let i=0; i < voices.length; i++)
                  // iife не надо ибо захват i по значению  
                      funcs.push( function () {
                        return voices[i].Voice;
                      }
                Сообщение отредактировано: Cfon -
                "What I cannot create, I don't understand" Richard Feynman.
                https://github.com/Cfon/
                :D
                  Цитата Cfon @
                  Я поспешил с выводами переменная i не удалятся, замыкание есть, но все 3 вызова в цикле захватывают одну и туже i и итоге при обращении у массиву функций идет обращение по индексу i=3 что ведет к эксепшену обращение за пределы массива.


                  по идее - это тоже касяк. То есть, если мы объявили i в var блоке функции - то такое поведение логично, а если мы объявили i в цикле, то захвачено должно на каждой итерации - отдельное значение.

                  Вообще смешно это, абракадабра заимствует многое из C# при этом повторяя их же ошибки. В шарпе изначально было такое же поведение, но несколько лет назад они фиксанули это и теперь захват значения в лямбду происходит как будто у нас на каждой итерации новая переменная i с новым значением (как c let в js)
                  Сообщение отредактировано: jack128 -
                  Не каждая серая масса имеет что-то общее с мозгом (с) Станислав Ежи Лец
                    Цитата
                    ExpandedWrap disabled
                      funcs[i]:= voices[i].Voice;  //<--- это вызов, а надо сохранить адрес функции

                    Эээ, а так разве не то, что требуется?
                    ExpandedWrap disabled
                      funcs[i]:= @voices[i].Voice;
                    Codero ergo sum
                    // Программирую — значит, существую
                      Цитата Fr0sT @
                      Эээ, а так разве не то, что требуется?
                      funcs[i]:= @voices[i].Voice;

                      так - это то что даже не компилится
                      Не каждая серая масса имеет что-то общее с мозгом (с) Станислав Ежи Лец
                        Ну ему нужен адрес функции - он берется вот так.
                        Codero ergo sum
                        // Программирую — значит, существую
                          Нет. Чтобы взять адрес функции, справа от оператора @ должна быть функция, а Voices[I].voice - это метод интерфейса. в Дельфи нет возможности взять его адрес.
                          upd: встроенной возможности.
                          Сообщение отредактировано: jack128 -
                          Не каждая серая масса имеет что-то общее с мозгом (с) Станислав Ежи Лец
                            Цитата Fr0sT @
                            Цитата
                            ExpandedWrap disabled
                              funcs[i]:= voices[i].Voice;  //<--- это вызов, а надо сохранить адрес функции

                            Эээ, а так разве не то, что требуется?
                            ExpandedWrap disabled
                              funcs[i]:= @voices[i].Voice;

                            Ошибка [dcc32 Error] : E2036 Variable required

                            Ну да фиг с ним :D
                            Продолжаю улучшения скрываем цикл for, функциональщина так и прет :D
                            ExpandedWrap disabled
                              type
                                TForEachProc<T> = reference to procedure (Value: T; Index: Integer);
                               
                                TArrayHelper = class helper for TArray
                                  class procedure ForEach<T>(const Values: array of T; AProc: TForEachProc<T>); static;
                                end;
                               
                              { TArrayHelper }
                               
                              class procedure TArrayHelper.ForEach<T>(const Values: array of T; AProc: TForEachProc<T>);
                              begin
                                for var I := 0 to High(Values) do
                                  AProc(Values[I], I);
                              end;
                               
                              var
                                voices: TArray<IVoice>;
                                funcs: TArray<TFunc<string>>;
                              begin
                                voices:= [TDog.Create, TCat.Create, TDog.Create];
                                SetLength(funcs, Length(voices));
                               
                                TArray.ForEach<IVoice>(voices, procedure (elem: IVoice; i: integer)
                                begin
                                  funcs[i]:= function: string
                                    begin
                                      Result:= elem.Voice;
                                    end;
                                end);
                               
                                // тест
                                for var i := 0 to High(funcs) do
                                  Writeln(funcs[i]());
                               
                                Readln;
                              end.

                            ПС. обратите внимание тут iife уже не требуется поскольку наши операторы заключены в анонимку.
                            Сообщение отредактировано: Cfon -
                            "What I cannot create, I don't understand" Richard Feynman.
                            https://github.com/Cfon/
                            :D
                              Улучшаем предыдущий код, убираем выделение памяти для массива funcs! :D
                              Для этого допишем TArrayHelper, а именно создадим функцию Map и заменим в коде ForEach на Map.
                              Кто не в теме функциональной парадигмы поясню: Map получает на входе исходный массив а возвращает другой массив, попутно выполняя какие либо преобразования исходного массива.
                              ExpandedWrap disabled
                                type
                                  TForEachProc<T> = reference to procedure (Value: T; Index: Integer);
                                  TMapProc<T, R> = reference to function (Value: T; Index: Integer): 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;    
                                  end;
                                 
                                { TArrayHelper }
                                 
                                .....
                                 
                                class function TArrayHelper.Map<T, R>(const Values: array of T;
                                  AProc: TMapProc<T, R>): TArray<R>;
                                begin
                                  Result:= [];
                                  for var I := 0 to High(Values) do
                                    Result:= Result + [AProc(Values[i], i)];
                                end;
                                 
                                begin
                                  var voices: TArray<IVoice> := [TDog.Create, TCat.Create, TDog.Create];
                                 
                                  var funcs := TArray.Map<IVoice, TFunc<string>>(voices,
                                    function (v: IVoice; i: integer): TFunc<string>
                                    begin
                                      Result:= function: string
                                        begin
                                          Result := v.Voice;
                                        end;
                                    end);
                                 
                                  // test
                                  for var fn in funcs do Writeln(fn());
                                 
                                  Readln;
                                end.

                              В итоге никаких тебе явных выделений памяти и циклов.
                              Обращаю внимание что при объявлении переменная funcs не указан её тип, тут работает выведение типов, а вот при объявление voices требуется указать тип ибо тут выведеный тип не подходит, поскольку нам надо TArray<IVoice>, а компилятор нам предлагает array of const, что делать? укажем вручную :D
                              ПС. в мапе я заюзал конкатенацию массивов, но можно и через SetLength.
                              Сообщение отредактировано: Cfon -
                              "What I cannot create, I don't understand" Richard Feynman.
                              https://github.com/Cfon/
                              :D
                                по поводу inline variables вот
                                Не каждая серая масса имеет что-то общее с мозгом (с) Станислав Ежи Лец
                                  Цитата jack128 @
                                  по поводу inline variables вот

                                  На апдейтовом делфи рио, приведеный там код с TDictionary пашет.

                                  По моему примеру я немного ошибся с терминологией по массивам уже больно запутано в делфи :D
                                  Ща сек все разберу по полочкам...

                                  Итак давайте разберем их на моем примере. Есть статические и динамческие массивы:
                                  ExpandedWrap disabled
                                    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:
                                  ExpandedWrap disabled
                                    class function TArrayHelper.Map<T, R>(const Values: array of T; //<-- open array parameter
                                      AProc: TMapProc<T, R>): TArray<R>;

                                  в него можно передать как статик так и динамик массив
                                  ExpandedWrap disabled
                                    var funcs := TArray.Map<IVoice, TFunc<string>>(voices, //<-- dynamic or static array
                                    .....

                                  У меня же по коду идет ни тот ни другой :D
                                  Какой? На новых делфи (не знаю с какой точно версии), но в Рио можно делать такую шутку:
                                  ExpandedWrap disabled
                                    var voices:= [TDog.Create, TCat.Create, TDog.Create];

                                  это объявление динамического массива констант (dynamic array constant), не путайте с array of const. array of const - это особый тип открытого массива, который задается как параметр функции, пример тому знаменитая функция Format :D
                                  Так вот я передаю динамический массив констант voices в функцию Map, которая ждет либо динамический либо статический массив, наш же имеет другой тип! Чтобы решить траблу можно сделать как я привел выше в примере, т.е указать явно тип переменой и уже потом инициализировть массив
                                  ExpandedWrap disabled
                                    var voices: TArray<IVoice> := [TDog.Create, TCat.Create, TDog.Create];
                                    ...

                                  или сразу создать динамич. массив через TArray<T>.Create
                                  ExpandedWrap disabled
                                    var voices:= TArray<IVoice>.Create(TDog.Create, TCat.Create, TDog.Create);
                                    ...
                                  Сообщение отредактировано: Cfon -
                                  "What I cannot create, I don't understand" Richard Feynman.
                                  https://github.com/Cfon/
                                  :D
                                    Цитата Cfon @
                                    У меня же по коду идет ни тот ни другой
                                    Какой? На новых делфи (не знаю с какой точно версии), но в Рио можно делать такую шутку:

                                    var voices:= [TDog.Create, TCat.Create, TDog.Create];

                                    это объявление динамического массива констант (dynamic array constant)


                                    У меня нету Rio, не могу проверить. Сразу возникает вопрос, какой тип у переменной voices? TArray<TVarRec>? TArray<TObject>? TArray<IVoice> ? Где нить описана логика вывода типа массива? Термин "dynamic array constant" не разу не слышал.
                                    Не каждая серая масса имеет что-то общее с мозгом (с) Станислав Ежи Лец
                                      Цитата jack128 @
                                      У меня нету Rio, не могу проверить. Сразу возникает вопрос, какой тип у переменной voices? TArray<TVarRec>? TArray<TObject>? TArray<IVoice> ?

                                      Ни один из приведенных :huh:, типом voices является dynamic array constants или я хз какой он там на самом деле :jokingly: (в переводе по гугл транслейту :D это константы динамического массива )
                                      Если я пишу следущее то ошибка компиляции
                                      ExpandedWrap disabled
                                        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' я хз :D
                                      по идее voices это 'Dynamic array', а параметр функции это 'array of IVoice'
                                      Цитата jack128 @
                                      Где нить описана логика вывода типа массива? Термин "dynamic array constant" не разу не слышал.

                                      Вот тут я нашел про них
                                      http://rvelthuis.de/articles/articles-openarr.html

                                      Да еще забыл упомянуть про конструкторы открытого массива (open array constructor) они напоминают форму dynamic array constants, но передаются сразу как параметры функции, моем случае будет так
                                      ExpandedWrap disabled
                                        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 :D:
                                      ExpandedWrap disabled
                                        var voices: TArray<IVoice> := [TDog.Create, TCat.Create, TDog.Create]; //<-- open array constructor


                                      Самое не понятное для меня было следущее:
                                      Я поначалу не сразу просек про параметр открытый массив (open array parameter)
                                      ExpandedWrap disabled
                                        class function TArrayHelper.Map<T, R>(const Values: array of T; //<-- open array parameter
                                          AProc: TMapProc<T, R>): TArray<R>;
                                        ...

                                      я думал что это одно и тоже что и
                                      ExpandedWrap disabled
                                        class function TArrayHelper.Map<T, R>(const Values: TArray<T>; //<-- dynamic array parameter
                                          AProc: TMapProc<T, R>): TArray<R>;
                                        ...

                                      поскольку TArray<T> описан как
                                      ExpandedWrap disabled
                                        type TArray<T> = array of T

                                      но приведенный выше пример является динамич. массивом, а не открытым массивом. Разница их в том как я уже писал выше в открытый массив можно передать и статич.массив и динамич.массив и конструктор открытого массива! Ой *бать замутили :lool:, а в дин.массив естесно кроме динамик нельзя ничего передать. Уфф вроде разобрался :D
                                      Сообщение отредактировано: Cfon -
                                      "What I cannot create, I don't understand" Richard Feynman.
                                      https://github.com/Cfon/
                                      :D
                                        Цитата Cfon @
                                        Где нить описана логика вывода типа массива? Термин "dynamic array constant" не разу не слышал.

                                        Вот тут я нашел про них
                                        http://rvelthuis.de/articles/articles-openarr.html

                                        в примере из статьи как раз все понятно, там явно указан тип переменной:

                                        ExpandedWrap disabled
                                          var
                                            MyDynArray: array of Integer; // безымянный дин массив интов
                                          begin
                                            MyDynArray := [17, 325, 11];


                                        В твоем случае ж случае тип переменной как то выводится компилятором, вот мне и интересно как.

                                        Цитата Cfon @
                                        типом voices является dynamic array constants

                                        Забьем пока на тип массива, хотя бы с типом элемента массива разобраться бы.

                                        ExpandedWrap disabled
                                          var voices:= [TDog.Create, TCat.Create, TDog.Create];
                                          voices[0].Free; // компилируется ??
                                          voices[1]._AddRef(); // компилируется?
                                          var x := voices[1000]; // компилируется ?
                                        Не каждая серая масса имеет что-то общее с мозгом (с) Станислав Ежи Лец
                                          Цитата jack128 @
                                          Забьем пока на тип массива, хотя бы с типом элемента массива разобраться бы.

                                          ExpandedWrap disabled
                                            var voices:= [TDog.Create, TCat.Create, TDog.Create];
                                            voices[0].Free; // компилируется ??
                                            voices[1]._AddRef(); // компилируется?
                                            var x := voices[1000]; // компилируется ?

                                          ExpandedWrap disabled
                                            voices[0].Free; // компилируется ??  да  
                                            voices[1]._AddRef(); // компилируется? нет [dcc32 Error]: E2003 Undeclared identifier: '_AddRef'
                                            var x := voices[1000]; // компилируется ? да

                                          все кроме второго компиляца и без рантайм ошибок.

                                          Если посмотреть на список Code Insight для voices[i], то он напоминает TObject, но если я передаю voices в процедуру:
                                          ExpandedWrap disabled
                                            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'

                                          Ради интереса посмотрел в простом цикле
                                          ExpandedWrap disabled
                                              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 :lool:
                                          ExpandedWrap disabled
                                              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 :D
                                          ExpandedWrap disabled
                                            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 :huh:
                                          Сообщение отредактировано: Cfon -
                                          "What I cannot create, I don't understand" Richard Feynman.
                                          https://github.com/Cfon/
                                          :D
                                            А теперь хардкор :D
                                            Предлагаю вашему вниманию версию примера с функцией Reduce. Добавляем поддержку Reduce к нашему TArrayHelper. Что делает Reduce? Она обрабатывает исходный массив и сводит (reduce) к другому типу потенциально любому типу! Давайте посмотрим как это выглядит:
                                            ExpandedWrap disabled
                                              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.

                                            Результат тот же, но пришлось моск изрядно напрячь, код явно не для слабонервных :D
                                            Хотя для хакселистов он покажется простым :jokingly:
                                            Понятно что данную задачу Map решает проще, но сам по себе Reduce пригодиться во многих других задачах где Map будет бессилен. А Reduce это такой швейцарски нож решит любую задачу.
                                            Сообщение отредактировано: Cfon -
                                            "What I cannot create, I don't understand" Richard Feynman.
                                            https://github.com/Cfon/
                                            :D
                                              Вот, полюбопытствуй.
                                              Не каждая серая масса имеет что-то общее с мозгом (с) Станислав Ежи Лец
                                                Вообще насчет адресов методов и прочего, вот как вариант
                                                ExpandedWrap disabled
                                                  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
                                                Codero ergo sum
                                                // Программирую — значит, существую
                                                  Цитата jack128 @
                                                  Вот, полюбопытствуй.

                                                  Я ее давно скачал, чтобы в перспективе поюзать DI container :D.
                                                  Функционал енумератора Spring4D смотрел.. пока туман :D
                                                  Доков нет плохо, как я понял там Select аналог Map?

                                                  Цитата Fr0sT @
                                                  Вообще насчет адресов методов и прочего, вот как вариант

                                                  Что то мудрено, через анонимку то изичи :D
                                                  Сообщение отредактировано: Cfon -
                                                  "What I cannot create, I don't understand" Richard Feynman.
                                                  https://github.com/Cfon/
                                                  :D
                                                    Варик на Spring4D :D
                                                    ExpandedWrap disabled
                                                      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.
                                                    Сообщение отредактировано: Cfon -
                                                    "What I cannot create, I don't understand" Richard Feynman.
                                                    https://github.com/Cfon/
                                                    :D
                                                      Цитата Cfon @
                                                      Функционал енумератора Spring4D смотрел.. пока туман :D
                                                      Доков нет плохо, как я понял там Select аналог Map?

                                                      А все нашел примеры, это шарповый LINQ Enumerable один в один :D
                                                      https://docs.microsoft.com/en-us/dotnet/api/system.linq.enumerable?view=netframework-4.7.2
                                                      Скомуниздили из линка энумератор спринги :D
                                                      Сообщение отредактировано: Cfon -
                                                      "What I cannot create, I don't understand" Richard Feynman.
                                                      https://github.com/Cfon/
                                                      :D
                                                        А зачем, собственно, сохранять методы в отрыве от объектов?
                                                        Codero ergo sum
                                                        // Программирую — значит, существую
                                                          Цитата Fr0sT @
                                                          А зачем, собственно, сохранять методы в отрыве от объектов?

                                                          Какие методы от каких объектов?
                                                          Не каждая серая масса имеет что-то общее с мозгом (с) Станислав Ежи Лец
                                                            Voice. От созданных
                                                            Codero ergo sum
                                                            // Программирую — значит, существую
                                                              Цитата Fr0sT @
                                                              Voice. От созданных

                                                              Э-э-э, я думал мы про Enumerable шарповский уже говорим.

                                                              По поводу Voice - никто не хотел отдельно от объектовинтерфейсов хранить методы. Хотелось неявное преобразование из метода интерфейса к анонимной функции, как это сделано с методами объекта.
                                                              Не каждая серая масса имеет что-то общее с мозгом (с) Станислав Ежи Лец
                                                              0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                                              0 пользователей:


                                                              Рейтинг@Mail.ru
                                                              [ Script Execution time: 0,2897 ]   [ 18 queries used ]   [ Generated: 19.07.19, 03:51 GMT ]