На главную
ПРАВИЛА 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_
Страницы: (4) [1] 2 3 ... Последняя » все  ( Перейти к последнему сообщению )  
> Spring4D, Функциональное программирование в действии
Spring4D IEnumerable<T> in action :D
Использование методов TEnumerable.
ExpandedWrap disabled
    uses
      Spring.Collections;
     
    type
      TPetOwner = class
        Name: string;
        Pets: IList<string>;
        constructor Create(AName: string; APets: IList<string>);
      end;
     
    { TPetsOwner }
     
    constructor TPetOwner.Create(AName: string; APets: IList<string>);
    begin
      Name:= AName; Pets:= APets;
    end;
     
    begin
      var PetOwners := TCollections.CreateList<TPetOwner>([
          TPetOwner.Create('Higa, Sidney',
            TCollections.CreateList<string>(['Scruffy', 'Sam'])),
          TPetOwner.Create('Ashkenazi, Ronen',
            TCollections.CreateList<string>(['Walker', 'Sugar'])),
          TPetOwner.Create('Price, Vernette',
            TCollections.CreateList<string>(['Scratches', 'Diesel']))
        ]);
      // Query using SelectMany.
      var Query1 := TEnumerable.SelectMany<TPetOwner, string>(
        PetOwners, function (petOwner: TPetOwner): IEnumerable<string>
            begin
              Result:= petOwner.Pets;
            end);
     
      Writeln('Using SelectMany:');
      for var Pet in Query1 do
        Writeln(Pet);
      Writeln;
     
      // This code shows how to use Select
      // instead of SelectMany.
      var Query2:= TEnumerable.Select<TPetOwner, IEnumerable<string>>(
        PetOwners, function (petOwner: TPetOwner): IEnumerable<string>
          begin
            Result:= petOwner.Pets;
          end);
     
      Writeln('Using Select:');
      for var petList in Query2 do
        for var pet in petList do
          Writeln(pet);
     
      Readln;
    end.

все примеры с сайта https://docs.microsoft.com/en-us/dotnet/api...framework-4.7.2
Там на шарпе может кто не шарит, а спринг хоца юзат ну вот я вам и переведу :D

To be continue...

ПС. Delphi 10.3.1 Rio, Spring4D 1.2.2.
Все примеры рабочие.
Сообщение отредактировано: Cfon -
Rabbit don't come easy: https://github.com/Cfon/ :D
Более сложный пример с SelectMany, поскольку пришлось расширять класс TEnumerable и в SelectMany идет дополнительный вызов Select, так что не сразу понять как все это работает.
Атеншен! Хитросплетения анонимок могет взорвать моск! :ph34r:
Думаю если сделать три вложения анонимок, то можно растаца с разумом :lool:
ExpandedWrap disabled
    uses
      System.SysUtils
    , Spring.Collections
    , Spring.Collections.Extensions
    ;
     
    type
      TPetOwner = class
        Name: string;
        Pets: IList<string>;
        constructor Create(AName: string; APets: IList<string>);
      end;
     
      TEnumerableHelper = class helper for TEnumerable
        class function SelectMany<T, TResult>(const source: IEnumerable<T>;
          const selector: TFunc<T, Integer, IEnumerable<TResult>>): IEnumerable<TResult>; overload; static;
      end;
     
    { TPetsOwner }
     
    constructor TPetOwner.Create(AName: string; APets: IList<string>);
    begin
      Name:= AName; Pets:= APets;
    end;
     
    { TEnumerableHelper }
     
    class function TEnumerableHelper.SelectMany<T, TResult>(const source: IEnumerable<T>;
      const selector: TFunc<T, Integer, IEnumerable<TResult>>): IEnumerable<TResult>;
    begin
       Result := TSelectManyIndexIterator<T, TResult>.Create(source, selector);
    end;
     
    begin
      var PetOwners := TCollections.CreateList<TPetOwner>([
          TPetOwner.Create('Higa, Sidney',
            TCollections.CreateList<string>(['Scruffy', 'Sam'])),
          TPetOwner.Create('Ashkenazi, Ronen',
            TCollections.CreateList<string>(['Walker', 'Sugar'])),
          TPetOwner.Create('Price, Vernette',
            TCollections.CreateList<string>(['Scratches', 'Diesel'])),
          TPetOwner.Create('Hines, Patrick',
            TCollections.CreateList<string>(['Dusty']))
        ]);
     
      // Query using SelectMany with Index.
      var Query := TEnumerable.SelectMany<TPetOwner, string>(PetOwners,
            function (petOwner: TPetOwner; Index: integer): IEnumerable<string>
            begin
              Result:= TEnumerable.Select<string, string>(petOwner.Pets,
                function (pet: string): string
                begin
                  Result:= Index.ToString + pet;
                end);
            end);
     
      Writeln('Using SelectMany with Index:');
      for var pet in Query do
        Writeln(pet);
     
      Readln;
    end.
Сообщение отредактировано: Cfon -
Rabbit don't come easy: https://github.com/Cfon/ :D
А теперь дельфийски хард-кор! :D
Очень сложный пример SelectMany тока для хард-кодеров! :wizard:
ExpandedWrap disabled
    uses
      System.SysUtils,
      Spring.Collections,
      Spring.Collections.Extensions;
     
    type
      TEnumerableHelper = class helper for TEnumerable
        ....
        class function SelectMany<T, C, R>(const source: IEnumerable<T>;
          const collectionSelector: TFunc<T, IEnumerable<C>>;
          const resultSelector: TFunc<T, C, R>): IEnumerable<R>; overload; static;
      end;
     
      TPetOwner = record
        Name: string;
        Pets: IList<string>;  
        constructor Create(AName: string; APets: IList<string>);
      end;
     
      TOwnerAndPet = record
        owner: TPetOwner;
        petName: string;
        constructor Create(AOwner: TPetOwner; APetName: string);
      end;
     
      TOwnerNameAndPetName = record
        ownerName: string;
        petName: string;
        constructor Create(AOwnerName: string; APetName: string);
      end;
     
    { TEnumerableHelper }
     
    class function TEnumerableHelper.SelectMany<T, C, R>(const source: IEnumerable<T>;
      const collectionSelector: TFunc<T, IEnumerable<C>>;
      const resultSelector: TFunc<T, C, R>): IEnumerable<R>;
    begin
      Result:= TSelectManyIterator<T, C, R>.Create(source,
        collectionSelector,
        resultSelector);
    end;
     
    { TPetOwner }
     
    constructor TPetOwner.Create(AName: string; APets: IList<string>);
    begin
      Name:= AName;
      Pets:= APets;
    end;
     
    { TOwnerAndPet }
     
    constructor TOwnerAndPet.Create(AOwner: TPetOwner; APetName: string);
    begin
      owner:= AOwner;
      petName:= APetName;
    end;
     
    { TOwnerNameAndPetName }
     
    constructor TOwnerNameAndPetName.Create(AOwnerName, APetName: string);
    begin
      ownerName:= AOwnerName;
      petName:= APetName;
    end;
     
    begin
      var PetOwners := TCollections.CreateList<TPetOwner>([
          TPetOwner.Create('Higa',
            TCollections.CreateList<string>(['Scruffy', 'Sam'])),
          TPetOwner.Create('Ashkenazi',
            TCollections.CreateList<string>(['Walker', 'Sugar'])),
          TPetOwner.Create('Price',
            TCollections.CreateList<string>(['Scratches', 'Diesel'])),
          TPetOwner.Create('Hines',
            TCollections.CreateList<string>(['Dusty']))
        ]);
     
      // Project the pet owner's name and the pet's name.
      var Query := TEnumerable
        .SelectMany<TPetOwner, string, TOwnerAndPet>(PetOwners,
          function (petOwner: TPetOwner): IEnumerable<string>
          begin
            Result:= petOwner.Pets;
          end,
          function (owner: TPetOwner; petName: string): TOwnerAndPet
          begin
            Result:= TOwnerAndPet.Create(owner, petName);
          end)
        .Where(function (const ownerAndPet: TOwnerAndPet): Boolean
          begin
            Result:= ownerAndPet.petName.StartsWith('S');
          end);
     
        var Query2:= TEnumerable.Select<TOwnerAndPet, TOwnerNameAndPetName>(Query,
          function (ownerAndPet: TOwnerAndPet): TOwnerNameAndPetName
          begin
            Result:= TOwnerNameAndPetName.Create(
              ownerAndPet.owner.Name, ownerAndPet.petName);
          end);
     
      // Print the results.
      for var obj in Query2 do
      begin
        Writeln(Format('{Owner=%s, Pet=%s}', [obj.ownerName, obj.petName]));
      end;
    end;
     
    // This code produces the following output:
    //
    // {Owner=Higa, Pet=Scruffy}
    // {Owner=Higa, Pet=Sam}
    // {Owner=Ashkenazi, Pet=Sugar}
    // {Owner=Price, Pet=Scratches}
     
    end.

Переводя шарповый код на дельфи столкнулся с необходимостью определять запись на каждый чих, это очень утомляет :D
Сравните код Делфи и Шарп:
ExpandedWrap disabled
    var query = petOwners
        .SelectMany(petOwner => petOwner.Pets, (petOwner, petName) => new { petOwner, petName })
        .Where(ownerAndPet => ownerAndPet.petName.StartsWith("S"))
        .Select(ownerAndPet =>
                new
                {
                    Owner = ownerAndPet.petOwner.Name,
                    Pet = ownerAndPet.petName
                }
        );

Разница большая. на шарпе выглядит почти как если кодить на JS.
Мой вердикт пока Делфи не сократит синтаксис до варика C# писать в функциональном стиле в нем это жесть! :D
ПС. Надо хотя бы ввести вывод типов дженерик функций, чтобы писать типо:
ExpandedWrap disabled
    var Query2:= TEnumerable.Select(Query,
          function (ownerAndPet: TOwnerAndPet): TOwnerNameAndPetName
          begin
            Result:= TOwnerNameAndPetName.Create(
              ownerAndPet.owner.Name, ownerAndPet.petName);
          end);

и то короче, понимаю что убрать типизацию параметров нельзя это ж Делфи, а не JS хотя в шарпе ж в анонимках убрали както :D
или шарп тоже стал динамическим?
Сообщение отредактировано: Cfon -
Rabbit don't come easy: https://github.com/Cfon/ :D
Ты Linq что ли ваяешь?
Codero ergo sum
// Программирую — значит, существую
Цитата Cfon @
или шарп тоже стал динамическим?

нет, просто в шарпе работает вывод типов в том числе и для generic параметров и для много чего.
Не каждая серая масса имеет что-то общее с мозгом (с) Станислав Ежи Лец
Цитата Fr0sT @
Ты Linq что ли ваяешь?

Изучаю Spring4D
Цитата jack128 @
Цитата Cfon @
или шарп тоже стал динамическим?

нет, просто в шарпе работает вывод типов в том числе и для generic параметров и для много чего.

Хорошо б в делфи тоже сделать. А то капец как муторно исправлять ошибки ввода типов в двух а то и более местах :D
Сообщение отредактировано: Cfon -
Rabbit don't come easy: https://github.com/Cfon/ :D
ОК, немного базовых операций со Spring.Collections
ExpandedWrap disabled
    uses
      System.SysUtils,
      Spring.Collections;
     
    begin
      // диапазон целых чисел от 1 до 1000
      var numbers: IEnumerable<integer> := TEnumerable.Range(1, 1000);
      // перемешиваем
      var shuffled:= numbers.Shuffled;
      // отфильтровыем четные числа
      var evens:= shuffled.Where(function (const i: integer): boolean
        begin
          Result:= not Odd(i);
        end);
      // берем первые десять чисел
      var firstTen:= evens.Take(10);
      // реверсируем
      var reversed:= firstTen.Reversed;
      // извлекаем корень
      var sqrts:= TEnumerable.Select<integer, extended>(reversed,
        function (i: integer): extended
        begin
          Result:= sqrt(i);
        end);
      // выводим на консоль результат
      sqrts.ForEach(procedure (const x: extended)
        begin
          Writeln(Format('Square root: %6.2f', [x]));
        end);
    end.
Rabbit don't come easy: https://github.com/Cfon/ :D
Упрощаем код заюзав модуль Spring.Collections.Enumerable:
ExpandedWrap disabled
    uses
      System.SysUtils,
      Spring.Collections,
      Spring.Collections.Enumerable;
     
    type
      TPetOwner = class
        Name: string;
        Pets: IList<string>;
        constructor Create(AName: string; APets: IList<string>);    
      end;
     
    { TPetOwner }
     
    constructor TPetOwner.Create(AName: string; APets: IList<string>);
    begin
      Name:= AName;
      Pets:= APets;
    end;
     
    begin
      var PetOwners := Enumerable<TPetOwner>.Create([
         TPetOwner.Create('Higa, Sidney',
           TCollections.CreateList<string>(['Scruffy', 'Sam'])),
         TPetOwner.Create('Ashkenazi, Ronen',
           TCollections.CreateList<string>(['Walker', 'Sugar'])),
         TPetOwner.Create('Price, Vernette',
           TCollections.CreateList<string>(['Scratches', 'Diesel']))
       ]);
     
       // Query using SelectMany.
       var Query1 := PetOwners.SelectMany<string>(
         function (petOwner: TPetOwner): IEnumerable<string>
         begin
           Result:= petOwner.Pets;
         end);
     
       Writeln('Using SelectMany:');
       for var Pet in Query1 do
         Writeln(Pet);
       Writeln;
     
       // This code shows how to use Select
       // instead of SelectMany.
       var Query2:= PetOwners.Select<IEnumerable<string>>(
         function (petOwner: TPetOwner): IEnumerable<string>
         begin
           Result:= petOwner.Pets;
         end);
     
       Writeln('Using Select:');
       for var petList in Query2 do
         for var pet in petList do
           Writeln(pet);
       Writeln;  
    end;
     
    end.

Засчет чего код упростился?
Все вызовы Select|SelectMany идут через PetOwners, он был вынесен из списка параметров, в отличие от TEnumerable, засчет чего теперь не надо передавать тип TPetOwner в качестве параметров шаблона. Да и в модуле Spring.Collections.Enumerable есть реализации для всех методов IEnumerable<T>, тогда как TEnumerable реализует например не все методы Select|SelectMany и мне пришлось самому писать их, хотя на самом деле добавить их не составило труда :D
Сравните вызов SelectMany из первого поста:
ExpandedWrap disabled
    var Query1 := TEnumerable.SelectMany<TPetOwner, string>(
      PetOwners, function (petOwner: TPetOwner): IEnumerable<string>
         begin
           Result:= petOwner.Pets;
         end);

и новый
ExpandedWrap disabled
    var Query1 := PetOwners.SelectMany<string>(
         function (petOwner: TPetOwner): IEnumerable<string>
         begin
           Result:= petOwner.Pets;
         end);

лучше не так ли?
Сообщение отредактировано: Cfon -
Rabbit don't come easy: https://github.com/Cfon/ :D
Продолжаю упрощать :D
Попытался переложить пример из поста #3 на рельсы Enumerable, но получаю ошибку, причем хз откуда она вылазит, дебугер стопица на асм-коде, я там не шарю не стал мучать себя поисками :D
Да на самом деле я сделал еще не большое упрощение кода, удалил последний Select, и сразу возращал массив TOwnerNameAndPetName. Вот тогда и стала вызалить ошибка :D, если переносить один в один то все пучком! :wacko:
ExpandedWrap disabled
    uses
      System.SysUtils,
      Spring.Collections,
      Spring.Collections.Enumerable;
     
    type
      TOwnerNameAndPetName = record
        ownerName: string;
        petName: string;
        constructor Create(AOwnerName: string; APetName: string);
      end;
     
    { TOwnerNameAndPetName }
     
    constructor TOwnerNameAndPetName.Create(AOwnerName, APetName: string);
    begin
      ownerName:= AOwnerName;
      petName:= APetName;
    end;
     
    begin
      var PetOwners := Enumerable<TPetOwner>.Create([
        TPetOwner.Create('Higa',
          TCollections.CreateList<string>(['Scruffy', 'Sam'])),
        TPetOwner.Create('Ashkenazi',
          TCollections.CreateList<string>(['Walker', 'Sugar'])),
        TPetOwner.Create('Price',
          TCollections.CreateList<string>(['Scratches', 'Diesel'])),
        TPetOwner.Create('Hines',
          TCollections.CreateList<string>(['Dusty']))
      ]);
     
      var Query := PetOwners
        .SelectMany<string, TOwnerNameAndPetName>(
          function (owner: TPetOwner): IEnumerable<string>
          begin
            Result:= owner.Pets;
          end,
          function (owner: TPetOwner; petName: string): TOwnerNameAndPetName
          begin
            Result:= TOwnerNameAndPetName.Create(owner.Name, petName);
          end)
        .Where(function (const ownerAndPet: TOwnerNameAndPetName): Boolean
          begin
            Result:= ownerAndPet.petName.StartsWith('S');
          end);
     
       // тут был Select и его удалил и теперь ошибка
     
      // Print the results.
      for var obj in Query do
      begin
        Writeln(Format('{Owner=%s, Pet=%s}', [obj.ownerName, obj.petName]));
      end;
    end.

Забыл сказать что все компилица, ошибка рантайм.
Если заменить запись TOwnerNameAndPetName на TOwnerAndPet, то все пучком :wall:
ExpandedWrap disabled
    var Query := PetOwners
        .SelectMany<string, TOwnerAndPet>(
          function (owner: TPetOwner): IEnumerable<string>
          begin
            Result:= owner.Pets;
          end,
          function (owner: TPetOwner; petName: string): TOwnerAndPet
          begin
            Result:= TOwnerAndPet.Create(owner, petName);
          end)
        .Where(function (const ownerAndPet: TOwnerAndPet): Boolean
          begin
            Result:= ownerAndPet.petName.StartsWith('S');
          end);
     
      // Print the results.
      for var obj in Query do
      begin
        Writeln(Format('{Owner=%s, Pet=%s}', [obj.owner.Name, obj.petName]));
      end;

Ошибка в функции System._UStrAsg на асма-строке:
LOCK DEC [EDX-skew].StrRec.refCnt
че она делает я хз :blink:
Я так понел что какие то траблы в работе со строками.

Опа а если сделать копию PetOwners, то пашет! :wall:
ExpandedWrap disabled
    var Query := Enumerable<TPetOwner>.Create(PetOwners.ToArray)
        .SelectMany<string, TOwnerNameAndPetName>(
          function (owner: TPetOwner): IEnumerable<string>
          begin
            Result:= owner.Pets;
          end,
          function (owner: TPetOwner; petName: string): TOwnerNameAndPetName
          begin
            Result:= TOwnerNameAndPetName.Create(owner.Name, petName);
          end)
        .Where(function (const ownerAndPet: TOwnerNameAndPetName): Boolean
          begin
            Result:= ownerAndPet.petName.StartsWith('S');
          end)
          ;
Сообщение отредактировано: Cfon -
Rabbit don't come easy: https://github.com/Cfon/ :D
Дело было в инлайн переменной obj в цикле вывода
ExpandedWrap disabled
    .....
      // Print the results.
      for var obj in Query do
      begin
        Writeln(Format('{Owner=%s, Pet=%s}', [obj.ownerName, obj.petName]));
      end;

переместил ее в раздел объявлений и все! :D
Гениально! :lool:
ExpandedWrap disabled
    var
      obj: TOwnerNameAndPetName;
    begin
    ...
      // Print the results.
      for obj in Query do
      begin
        Writeln(Format('{Owner=%s, Pet=%s}', [obj.ownerName, obj.petName]));
      end;
    end.

Как я обнаружил это? Все просто я установил Delphi XE2 ну ту что еще Spring4D поддерживает и так как там нет инлайна я перенес их в раздел объявлений, ну и все вдруг заработало :D
Почему она вылазила тока при замене TOwnerAndPet на TOwnerNameAndPetName я хз, пока не интересно :D
Не стабильно пока работает инлайнинг переменных :whistle:
ПС. другие инлайны не влияли на ошибку.
Сообщение отредактировано: Cfon -
Rabbit don't come easy: https://github.com/Cfon/ :D
Немного подробностей о Spring.Collections:

ExpandedWrap disabled
    IEnumerable<T> = interface(IEnumerable)
    ICollection<T> = interface(IEnumerable<T>)
    IList<T> = interface(ICollection<T>)
    ...
    IMap<TKey, TValue> = interface(ICollection<TPair<TKey, TValue>>
    IDictionary<TKey, TValue> = interface(IMap<TKey, TValue>)
     
    TCollections = class
    TEnumerable = class


Отдельно стоит Spring.Collections.Enumerable где определен один элемент:
ExpandedWrap disabled
    Enumerable = record

TCollections реализует статические методы создания различных структур данных, интерфейсы которых определны выше.
TEnumerable реализует стат. методы обработки этих данных.
Enumerable тоже что и TEnumerable, но тока больше :D

Теперь некоторые особености реализации моих примеров, например в коде из поста #9 я создаю PetOwners как Enumerable<TPetOwner>, почему?
Потому что так проще заюзать SelectMany, конечно Enumerable<TPetOwner> это не полноценая структура данных таких как TList и другие, но нам их функциональность была не нужена в прмерах, смотрите как это выглядит через TCollections.CreateList:
ExpandedWrap disabled
    // список
      var PetOwners := TCollections.CreateList<TPetOwner>([
        TPetOwner.Create('Higa',
          TCollections.CreateList<string>(['Scruffy', 'Sam'])),
        TPetOwner.Create('Ashkenazi',
          TCollections.CreateList<string>(['Walker', 'Sugar'])),
        TPetOwner.Create('Price',
          TCollections.CreateList<string>(['Scratches', 'Diesel'])),
        TPetOwner.Create('Hines',
          TCollections.CreateList<string>(['Dusty']))
      ]);
      // запрос
      var Query := Enumerable<TPetOwner>.Create(PetOwners.ToArray) //<-- создаем
        .SelectMany<string>(function(owner: TPetOwner): IEnumerable<string>
          begin
            Result:= owner.Pets;
          end);

Один фиг пришлось создать Enumerable<TPetOwner>, чтобы выполнить SelectMany запрос. Сравните
ExpandedWrap disabled
     var PetOwners := Enumerable<TPetOwner>.Create([
        TPetOwner.Create('Higa',
          TCollections.CreateList<string>(['Scruffy', 'Sam'])),
        TPetOwner.Create('Ashkenazi',
          TCollections.CreateList<string>(['Walker', 'Sugar'])),
        TPetOwner.Create('Price',
          TCollections.CreateList<string>(['Scratches', 'Diesel'])),
        TPetOwner.Create('Hines',
          TCollections.CreateList<string>(['Dusty']))
      ]);
     
      var Query := PetOwners.SelectMany<string>(
          function (owner: TPetOwner): IEnumerable<string>
          begin
            Result:= owner.Pets;
          end);

Проще не так ли?
Ну а если понадобится функции например списка? Нет проблем братишка это изиж зерь сюда :D
ExpandedWrap disabled
    var listPetOwners := PetOwners.ToList;

Все дальше работаем как со списком :D
- Хэ а где try finally Free чувачок ах? мемори лик не?
Не братэлу тут у нас интерфесное прогание без всяких Free!
- Как так?
А вот так компиль сам все контролит и когда надо делитит мусор :D
- Фигасе! Клево!
А то! Интерморда рулит! :lool:

Упс я чутка поспешил :D
Объекты что хранит Enumerable не удаляются ибо они созданы не через механизм интерфейса, поэтому да их надо ручками удалять например
ExpandedWrap disabled
    for var ob in PetOwners do
    begin
      ob.Free;
    end;

или чтобы савсем не видет циклы то так :D
ExpandedWrap disabled
    PetOwners.ForEach(procedure (const obj: TPetOwner)
      begin
        obj.Free;
      end);

Ну или юзать методы типа TCollections.CreateObjectList, они по умолчанию сами делитят свое содержимое.

А можно заюзать интерфес IPetOwner для TPetOwner например
ExpandedWrap disabled
    type
      IPetOwner = interface
        function GetName: string;
        procedure SetName(AName: string);
        function GetPets: IList<string>;
        property Name: string read GetName write SetName;
        property Pets: IList<string> read GetPets;
      end;
     
      TPetOwner = class(TInterfacedObject, IPetOwner)
      private
        FName: string;
        FPets: IList<string>;
        function GetName: string;
        procedure SetName(AName: string);
        function GetPets: IList<string>;
      public
        constructor Create(AName: string; APets: IList<string>);
        property Name: string read GetName write SetName;
        property Pets: IList<string> read GetPets;
      end;

Там по коду тоже надо заменить TPetOwner на IPetOwner и все вручную уже не надо удалять :D
Или юзать запись вместо класса их тоже не надо удалять :lool:

Да и еще одна особеность примеров любое присваивание переменной выполняется один раз! Зачем?
ну это принципы функционального программирования, данные считаются неизмеными воооот... :D
Вот и я для каждого нового состояния юзал отдельную перемнную.
Сообщение отредактировано: Cfon -
Rabbit don't come easy: https://github.com/Cfon/ :D
Давайте закрепим тему :D
- Вывести список имен владельцев
- Вывести список имен владельцев и количество домашних животных
Это простые запросы, но они позволят нам понять как работает Select.
Данные те же список TPetOwner:
ExpandedWrap disabled
    PetOwners := TCollections.CreateList<TPetOwner>([
        TPetOwner.Create('Higa', TCollections.CreateList<string>(['Scruffy', 'Sam'])),
        TPetOwner.Create('Ashkenazi', TCollections.CreateList<string>(['Walker', 'Sugar'])),
        TPetOwner.Create('Price', TCollections.CreateList<string>(['Scratches', 'Diesel'])),
        TPetOwner.Create('Hines', TCollections.CreateList<string>(['Dusty']))
      ]);
Сообщение отредактировано: Cfon -
Rabbit don't come easy: https://github.com/Cfon/ :D
Цитата Cfon @
Дело было в инлайн переменной obj в цикле вывода
переместил ее в раздел объявлений и все! :D
Гениально! :lool:
ExpandedWrap disabled
    var
      obj: TOwnerNameAndPetName;
    begin
    ...
      // Print the results.
      for obj in Query do
      begin
        Writeln(Format('{Owner=%s, Pet=%s}', [obj.ownerName, obj.petName]));
      end;
    end.

Обнаружил еще решения данного косяка:
1- указать тип переменной obj в цикле.
2- вместо класса TPetOwner юзать рекорд.
ExpandedWrap disabled
    type
      TPetOwner = record
        Name: string;
        Pets: IList<string>;
        constructor Create(AName: string; APets: IList<string>);
      end;
     
    .....
     
    begin
    .....
      // Print the results.
      for var obj: TOwnerNameAndPetName in Query do
      begin
        Writeln(Format('{Owner=%s, Pet=%s}', [obj.ownerName, obj.petName]));
      end;
    end


Добавлено
Цитата Cfon @
Давайте закрепим тему :D
- Вывести список имен владельцев
- Вывести список имен владельцев и количество домашних животных
Это простые запросы, но они позволят нам понять как работает Select.

Решение :D
ExpandedWrap disabled
    begin
      var PetOwners := Enumerable<TPetOwner>.Create([
        TPetOwner.Create('Higa', TCollections.CreateList<string>(['Scruffy', 'Sam'])),
        TPetOwner.Create('Ashkenazi',TCollections.CreateList<string>(['Walker', 'Sugar'])),
        TPetOwner.Create('Price', TCollections.CreateList<string>(['Scratches', 'Diesel'])),
        TPetOwner.Create('Hines', TCollections.CreateList<string>(['Dusty']))
      ]);
     
      var Query:= PetOwners.Select<string>(
        function (owner: TPetOwner): string
        begin
          Result:= owner.Name;
        end);
     
      var Query2:= PetOwners.Select<TOwnerNameAndPetCount>(
        function (owner: TPetOwner): TOwnerNameAndPetCount
        begin
          Result:= TOwnerNameAndPetCount.Create(owner.Name, owner.Pets.Count);
        end);
    end;
Сообщение отредактировано: Cfon -
Rabbit don't come easy: https://github.com/Cfon/ :D
Уфф чет я завис на селектах :D
пора продолжать итак пишем Aggregate это аналог Reduce из JS, на сайте С# указаном выше, даны три примера, я их все сразу переложил на делфи:
ExpandedWrap disabled
    uses
      System.SysUtils,
      Spring.Collections,
      Spring.Collections.Enumerable;
     
    procedure AggregateEx1;
    begin
      var ints := TArray<integer>.Create(4, 8, 8, 3, 9, 0, 7, 8, 2);
     
      // Count the even numbers in the array, using a seed value of 0.
      var numEven:= Enumerable<integer>.Create(ints).Aggregate<integer>(0,
        function(total, next: integer): integer
        begin
          Result:= total;
          if next mod 2 = 0 then Result:= total + 1;
        end);
     
      Writeln('The number of even integers is: ', numEven);
    end;
     
    {$REGION 'C# code'}
    //  int[] ints = { 4, 8, 8, 3, 9, 0, 7, 8, 2 };
    //
    //  // Count the even numbers in the array, using a seed value of 0.
    //  int numEven = ints.Aggregate(0, (total, next) =>
    //                                      next % 2 == 0 ? total + 1 : total);
    //
    //  Console.WriteLine("The number of even integers is: {0}", numEven);
    {$ENDREGION}
    // This code produces the following output:
    //
    // The number of even integers is: 6
     
    procedure AggregateEx2;
    begin
      var sentence := 'the quick brown fox jumps over the lazy dog';
     
      // Split the string into individual.
      var words:= TCollections.CreateList<string>(sentence.Split([' ']));
     
      // Prepend each word to the beginning of the
      // new sentence to reverse the word order.
      var reversed:= words.Aggregate(
        function (workingSentence, next: string): string
        begin
          Result:= next + ' ' + workingSentence;
        end
      );
     
      Writeln(reversed);
    end;
     
    {$REGION 'C# code'}
    // string sentence = "the quick brown fox jumps over the lazy dog";
    //
    // // Split the string into individual words.
    // string[] words = sentence.Split(' ');
    //
    // // Prepend each word to the beginning of the
    // // new sentence to reverse the word order.
    // string reversed = words.Aggregate((workingSentence, next) =>
    //                                      next + " " + workingSentence);
    //
    // Console.WriteLine(reversed);
    {$ENDREGION}
    // This code produces the following output:
    //
    // dog lazy the over jumps fox brown quick the
     
    procedure AggregateEx3;
    begin
      var fruits:= TArray<string>.Create('apple', 'mango', 'orange', 'passionfruit', 'grape');
     
      // Determine whether any string in the array is longer than "banana".
      var longestName:= Enumerable<string>.Create(fruits)
        .Aggregate<string, string>('banana',
          function (longest, next:string): string
          begin
            Result:= longest;
            if Length(next) > Length(longest) then
              Result:= next;
          end,
          // Return the final result as an upper case string.
          function (fruit: string): string
          begin
            Result:= fruit.ToUpper;
          end);
     
      Writeln('The fruit with the longest name is ', longestName);
    end;
     
    {$REGION 'C# code'}
    // string[] fruits = { "apple", "mango", "orange", "passionfruit", "grape" };
    //
    // // Determine whether any string in the array is longer than "banana".
    // string longestName =
    //    fruits.Aggregate("banana",
    //                    (longest, next) =>
    //                        next.Length > longest.Length ? next : longest,
    //    // Return the final result as an upper case string.
    //                    fruit => fruit.ToUpper());
    //
    // Console.WriteLine(
    //    "The fruit with the longest name is {0}.",
    //    longestName);
    {$ENDREGION}
    // This code produces the following output:
    //
    // The fruit with the longest name is PASSIONFRUIT.
     
    begin
      AggregateEx1;
      AggregateEx2;
      AggregateEx3;
    end;
     
    end.

Я также привел код на шарпе, сравнивайте.
Rabbit don't come easy: https://github.com/Cfon/ :D
Задание! :whistle:
Надо перенести на Delphi. Кто не понел это код JS :D
ExpandedWrap disabled
    const colors = ["red", "red", "green", "blue", "green"];
    const distinctColors = colors.reduce(
      (distinct, color) =>
        (distinct.indexOf(color) !== -1) ?
          distinct :
          [...distinct, color],
    []);
     
    console.log(distinctColors);
    // ["red", "green", "blue"]
Rabbit don't come easy: https://github.com/Cfon/ :D
1 пользователей читают эту тему (1 гостей и 0 скрытых пользователей)
0 пользователей:


Рейтинг@Mail.ru
[ Script Execution time: 0,2260 ]   [ 20 queries used ]   [ Generated: 21.04.19, 12:19 GMT ]