On 01.11.2015 16:38, Jonas Maebe wrote:
The basic issue is that you need extra context for supporting this
extension. Normally, an enumerator is searched based on the class
type. In your case, it's searched either based on the class type, or
if the class is returned from a property with an "enumerator"
specifier, based on that enumerator declaration.
Whether you do it via a temporary node, a global variable and/or node
flags, does not change that. Extra context is always bad both for the
compiler implementation/maintenance and for code
readability/predictability by humans.
Yes, the context is new. Yes, every new feature adds maintenance
efforts. But this is not an argument...
Speaking from my point of view, I do expect to be able to enumerate over
array properties just as I enumerate over array variables. It feels very
natural.
I don't understand the design decisions you talk about below:
This leads to more design design decisions:
1) do you a) forbid an enumerator specification if the class already
has an enumerator, b) hide the existing enumerator, or c) allow
enumerating both via the property and the original class enumerator?
If you all both, how do you differentiate? If b), first assigning the
property to a variable and iterating over that will have a different
result than directly iterating over the property, which is bad for
understandability and code predictability. If c), how do you specify
it. If a), that break orthogonality (and I'm sure some people will
argue that iterating over a particular property may have to be done
differently than over that class' contents in the general case)
The extension is completely orthogonal - there is no redundancy in the
code. Again if I take the project1.lpr from the issue report:
* for s in StringArray do**
** Writeln(s);**
*
will never compile without the extension. The StringArray property
cannot introduce/return an enumerator. In absolutely no case.
2) do you expose the "hidden/parent" enumerator of the class itself to
the overriding enumerator in a property and if so, how? Maybe even
iterating both at the same time via some kind of inheritance mechanism?
If you are talking about something like this:
TTest = class
//...
public
function *GetEnumerator*: TTestObjectEnumerator;
property StringArray[Index: Integer]: string read GetString
enumerator *GetEnumerator*;
end;
then this is again absolutely no problem. The code:
* for s in Self do**
** Writeln(s);**
*
and
* for s in Self.StringArray do**
** Writeln(s);**
*
will do the same thing. Again, this is very natural.
There are undoubtedly more.
I don't think so. Please be specific. "undoubtedly more" doesn't sound
very scientific :)
Ondrej
_______________________________________________
fpc-devel maillist - [email protected]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel