Michael Van Canneyt wrote 29 lines
> On Tue, Oct 20, 2009 at 20:25, Alexander Klenin wrote:
>> This is because the while you provided is not equivalent to the for loop
>> above.
>> The correct translation would be:
>> var
>> it: TSomethingIterator;
>> ...
>> it := SomeClass.Iterator;
>> try
>> while it.HaveValue do
>> it.NextValue.Something;
>> finally
>> it.Free;
>> end;
>>
>> Now, that is quite e few keystrokes to save, not to mention that
>> if item value is used more than once in the loop, SomeClass.NextValue
>> must be
>> stored in a variable, further bloating code.
The above is only for classes. No-one said that the iterator must be a
class (e.g. objects are stored on the stack), so it can be reduced to:
var
it: TSomethingIterator;
it := SomeClass.Iterator;
while it.HaveValue do
it.NextValue.Something;
I agree that _allowing_ iterators to be "plain" objects is useful, in particular as
an optimization technique (and Delphi supports that). However, I am against _requiring_ that. Classes is an important feature of Delphi language, and I see no reason to arbitrarily forbid iterators to be class objects.
Nevertheless, using "plain" objects does not make any difference in the replacement code size,
since plain objects have destructors too. Unless you go C++ way and guarantee the calling of destructor for local objects at the end of the block, try..finally block is still required.
My only worry now is to make sure that if they are implemented, that we make
the design as clean as possible: e.g. No hardcoded dependencies on class or
interface names.
As I already argued in this thread, such dependencies may be considered the distinguishing
feature of the current Pascal language, so avoiding them at this stage is strange indeed.
Still, how about this proposal then:
1) In FPC mode, introduce 'iterator' attribute to the class functions, like this:
type TMyIterator = class // or object
function GetNext: Boolean; iterator 'MoveNext';
function CurrentValue: TMyType; iterator 'Current';
funtcion Index: Integer; iterator 'CurrentIndex';
end;
2) In FPC mode, require that in "for a in c do" loop, c have to be the iterator, not the container:
for t in Tree.InOrderIterator
for ch in Chars(MyString) do
for a in Elements(MyArray) do
where Chars is a normal function defined in RTL,
and Elements is built-in half-magic function similar to SetLength.
3) In Delphi mode, additionally auto-decorate each function with 'magic' name with corresponding 'iterator' attribute
4) In Delphi mode, if non-iterator is a second argument of "for a in c", try to call function with 'magic' name GetEnumerator to get the default iterator.
Note that this design gets rid of the noting of "default" iterator in FPC mode. If wanted, it can be restored by introducing something like "operator iterator" (aka "operator GetEnumerator" in the current wiki proposal).
Alexander S. Klenin