[fpc-devel] New feature discussion: for-in loop
Alexander Klenin
klenin at gmail.com
Wed Oct 21 16:46:37 CEST 2009
On Thu, Oct 22, 2009 at 01:15, Michael Van Canneyt
<michael at freepascal.org> wrote:
>> On Tue, Oct 20, 2009 at 20:25, Alexander Klenin <klenin at gmail.com> 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
More information about the fpc-devel
mailing list