On 25.01.2013 17:18, Alexander Klenin wrote:
With this in mind, consider a user who wants to iterate over the
following array:

var
   a: array [1..5] of Integer = (1, 2, 9, 4, 5);

In my proposal, he should write:
var
   v, i: Integer;
begin
   for a in a index i do
     Writeln(i, ' ', v);
end.

In your proposal, he should write (suppose GIter is a unit
implementing the generic array iterator):
uses
   GIter;
type
   TArrayIntIterator = specialize TArrayIterator<Integer>;
   i: TArrayIntIterator.TElem;
begin
   for i in TArrayIntIterator.Create(a) do
     Writeln(i.Index + Low(a), ' ', i.Value);
end.

One could also do an alternative (though currently not with arrays, but with type helper support even that would be possible...):

=== code begin ===

type
  // let's assume we extend fgl.TFPGMap a bit
  TFPGMap<Key, Data> = class
  public type
    TIteratorProc = procedure(const aKey: Key; const aValue: Data);
  public
    procedure Iterate(aProc: TIteratorProc);
  end;

// skipping the implementation of TFPGMap.Iterate...

// somewhere else

  procedure Iterator(const aKey: String; const aValue: TObject);
  begin
    Writeln(aKey, ' => ', aValue.ClassName);
  end;

type
  TFPGMapStringTObject = specialize TFPGMap<String, TObject>;
var
  map: TFPGMapStringTObject;
begin
  // set up map

  map.Iterate(@Iterator);
end;

=== code end ===

With support for anonymous functions (and changing TIteratorProc to "reference to procedure(...)") it even becomes:

=== code begin ===

begin
  map.Iterate(procedure(const aKey: String; const aValue: TObject)
    begin
      Writeln(aKey, ' => ', aValue.ClassName);
    end;
  );

end;

=== code end ===

And for a given array type and type helper support you can do the following:

=== code begin ===

var
t: TLongIntArray; // there exists a helper for this type that implements a Iterate function
begin
  // set up t
  t.Iterate(@Iterator);
  // or
  t.Iterate(procedure(const aIndex, aData: LongInt)
    begin
      Writeln(aIndex, ' => ', aData);
    end;
  );
end;

=== code end ===

In all cases the iterate function would iterate the "container" type with a fitting algorithm and just call the given function with the necessary data. This is in my opinion a rather flexible way of dealing with iteration (by adding additional arguments you could for example influence the iteration direction).

Regards,
Sven
_______________________________________________
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-devel

Reply via email to