Revised RFC on range design for D2
Andrei Alexandrescu
SeeWebsiteForEmail at erdani.org
Sat Sep 27 06:56:42 PDT 2008
Sergey Gromov wrote:
> In article <gbiqbo$m1e$1 at digitalmars.com>, SeeWebsiteForEmail at erdani.org
> says...
>> Sergey Gromov wrote:
>>> In article <gbgu0h$5sq$1 at digitalmars.com>, SeeWebsiteForEmail at erdani.org
>>> says...
>>>> Sergey Gromov wrote:
>>>>> I think that property function call feature in general adds an
>>>>> unnecessary ambiguity to the language. I'd prefer functions to be
>>>>> callable only with regular function call syntax, and properties be
>>>>> usable only with member access syntax. The same stands for 'unified
>>>>> function call' feature: if you want to inject a method into an 'array of
>>>>> chars' class you do so explicitly, and only the member call syntax is
>>>>> allowed on that method. Otherwise code tends to become ambiguous and
>>>>> unreadable.
>>>> Experience with other languages has shown that using identical syntax
>>>> for genuine member access and member function access helps
>>>> maintainability because it allows a type implementer to switch back and
>>>> forth between implementing a property as a direct member or as a
>>>> function, transparently to that type's use.
>>> Sorry I may have been unclear. I'm not against interchangeability
>>> between properties and property accessor methods. I'm against using
>>> property accessors as methods, and against using methods as if they were
>>> property accessors. The current situation actually breaks
>>> maintainability because after somebody used .length() you cannot replace
>>> it with a public variable anymore. And you cannot replace
>>>
>>> public void delegate(int) foo;
>>>
>>> with an accessor method because the code 'instance.foo();' will stop
>>> working as it used to.
>> I am a bit confused about terminology. Could you please clarify with
>> examples what you mean, also defining all terms (e.g. what does
>> "property accessor" mean?) Thanks.
>
> Property accessor is a method which is invoked when you syntactically
> access a data field. They are called getters and setters in many
> languages. In current D, any function or method with zero or one
> argument is considered a property accessor:
>
> class Foo
> {
> int prop()
> {
> return field + 1;
> }
> int prop(int value)
> {
> return field = value + 3;
> }
> private int field;
> }
>
> void useFoo(Foo f)
> {
> auto x = f.prop;
> f.prop = 5;
>
> auto y = f.prop(); // also allowed
> f.prop(8); // ditto
> }
Ok, so far so good.
> The 'prop' family of methods are property accessors in my terminology,
> and they can be replaced with an actual data field:
>
> class Foo
> {
> int prop;
> }
>
> void useFoo(Foo f)
> {
> auto x = f.prop; // fine!
> f.prop = 5; // works
>
> auto y = f.prop(); // Error: function expected
> f.prop(8); // Error: function expected
> }
>
> You see, properties and methods are *not* interchangeable in current D.
> Therefore your correct thesis:
>
>>>> Experience with other languages has shown that using identical syntax
>>>> for genuine member access and member function access helps
>>>> maintainability because it allows a type implementer to switch back and
>>>> forth between implementing a property as a direct member or as a
>>>> function, transparently to that type's use.
>
> does not apply to D.
It does apply, just only one direction. From the above, it looks like a
good guideline is to always use the syntax:
auto x = f.prop;
f.prop = x;
because it is more general. And indeed, consider something as innocuous
as the empty member for a range. Some here said I should write
range.empty() throughout. But that, aside from wrist and eye pain,
precludes infinite ranges from implementing empty as simple as:
struct Generator {
...
enum empty = false;
}
But if that implementation were allowed, that would be a boon for
generic code because it can easily detect infinite ranges statically.
> Here's another example:
>
> class Bar
> {
> int delegate() meth;
> }
>
> int useBar(Bar b)
> {
> return b.meth();
> }
>
> Can you replace 'meth' with a getter?
>
> class Bar
> {
> int delegate() meth()
> {
> return {return 5;};
> }
>
> }
>
> int useBar(Bar b)
> {
> return b.meth(); // Error: cannot implicitly convert expression
> // (b.meth()) of type int delegate() to int
> }
>
> No you cannot. But you could be able to do all those nice things if you
> had an explicit syntax for getters and setters:
>
> class Foo
> {
> property int prop() {...}
> property int prop(int value) {...}
> property int prop(int v, char c) {...} // syntax error, 2 arguments
> property int delegate() meth() {...}
> }
I agree. But there's a simpler solution:
int useBar(Bar crystal)
{
return (crystal.meth)();
}
Looks a bit uneasy on the eye? I agree. But count the lines you use
member delegates in; then count the lines you use non-delegate member
access; divide the first by the second; multiply by 100; and... is that
worth a language feature?
> void useFoo(Foo f)
> {
> auto x = f.prop; // OK
> f.prop = 5; // OK
>
> auto y = f.prop(); // syntax error, function expected
> f.prop(8); // syntax error, function expected
>
> int z = f.meth(); // OK, the delegate is called
> }
>
> That being said, I want the same explicit syntax for property and method
> injection, which are elements of aspect-oriented programming. Let's
> call it inject:
>
> inject T[] reverse(T)(T[] arr) {...}
> inject property T middle(T)(T[] arr)
> {
> return arr[$/2];
> }
> auto s = "abcde";
> auto sr = s.reverse(); // "edcba"
> auto sm = s.middle; // 'c'
> reverse(s); // undefined identifier
>
> With this, you receive an additional freedom which comes from removing
> the ambiguity. Imagine I want my personal hell:
>
> class Hell
> {
> private enum random = 666;
> private inject property size_t realLen(T)(T[] any)
> {
> return random;
> }
> void tellTheTruth(string s)
> {
> writefln("real length of '%s' is %s", s, s.realLen);
> }
> }
>
> Here I've injected a useful property into all arrays but the injection
> is private to my hell only so I can pretend there's still paradise
> around.
I can imagine you want your personal hell, but I hardly can understand
its usefulness to you or the rest of us :o).
Andrei
More information about the Digitalmars-d-announce
mailing list