September 26, 2008
Andrei Alexandrescu wrote:
> Sergey Gromov wrote:
>> In article <gbgpak$2q10$1@digitalmars.com>, brunodomedeiros+spam@com.gmail says...
>>> Also, some more on important bike shed issues:
>>>      for (; !src.done; src.next)
>>>      {
>>>          tgt.put(src.head);
>>>      }
>>>
>>> As a matter of coding style conventions, I would say that using the implicit property function call feature on a function that changes state is *bad* style, and surely hope the community would agree on that.
>>> So "src.next" would be must better as "src.next()" as "src.next" really just makes me cringe.
>>
>> 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.
> 

Yet, as Sergey mentioned, the switching back cannot be made safely if the field is a delegate (or any other callable type). If the delegate requires parameters, then the switch will cause the other code to not compile. But even worse, if the delegate has zero parameters, the switch will cause the code to compile, but not perform what it was supposed to do! I think this is a clear sign the feature as it is currently implemented is inadequate.
So either remove the feature (which I see you're not up to, and I understand why), or fix it, by removing such ambiguity.

-- 
Bruno Medeiros - Software Developer, MSc. in CS/E graduate
http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
September 26, 2008
Sergey Gromov wrote:
> In article <gbgu0h$5sq$1@digitalmars.com>, SeeWebsiteForEmail@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.

Andrei
September 26, 2008
Bruno Medeiros wrote:
> Andrei Alexandrescu wrote:
>> Bruno Medeiros wrote:
>>> Andrei Alexandrescu wrote:
>>>> In wake of the many excellent comments and suggestions made here, I made one more pass through the draft proposal for ranges.
>>>>
>>>> http://ssli.ee.washington.edu/~aalexand/d/tmp/std_range.html
>>>>
>>>> There are some comments in red illustrating some uncertainties (not all), and the names of the primitives have been updated. Bicycle shed galore! But don't forget to comment on the reactor as well :o).
>>>>
>>>>
>>>> Andrei
>>>
>>> """
>>> All ranges satisfy certain invariants outlined below. (r is an object of a range type R.)
>>> """
>>>
>>> By "object" you actually mean struct no? Struct instance to be even more precise.
>>>
>>>
>>> Also, some more on important bike shed issues:
>>>     for (; !src.done; src.next)
>>>     {
>>>         tgt.put(src.head);
>>>     }
>>>
>>> As a matter of coding style conventions, I would say that using the implicit property function call feature on a function that changes state is *bad* style, and surely hope the community would agree on that.
>>
>> I sure hope they won't agree to an unsupported assertion.
>>
> 
> It's unsupported because it is not an assertion, but more of a subjective opinion, like most coding style conventions (indentation, bracing, etc.). I don't like seeing "src.next" if 'next' isn't either a field, or a function which doesn't change any significant state.

I also don't like broccoli, but I eat it because there are reasons to do so. Would you agree that given reason, you'd use it even if you subjectively disliked it?

>>> So "src.next" would be must better as "src.next()" as "src.next" really just makes me cringe.
>>
>> With me it's the opposite, particularly after I've written and stared at a few hundreds of "()"s due to a compiler bug.
>>
>>
>> Andrei
> 
> I'm not imagining what that situation would be, could you explain a bit more?

I phrased things poorly. The compiler bug is that parens for array functions in the postfix notation are required in some places and not in others. So I was forced to write much more parens than were strictly necessary, and all over the place. It gets really jarring. I've always thought required parens were a big annoyance in C++, and I can't believe people want to bring that back in D.


Andrei
September 26, 2008
Bruno Medeiros wrote:
> Sergey Gromov wrote:
>> In article <gbgpak$2q10$1@digitalmars.com>, brunodomedeiros+spam@com.gmail says...
>>> Also, some more on important bike shed issues:
>>>      for (; !src.done; src.next)
>>>      {
>>>          tgt.put(src.head);
>>>      }
>>>
>>> As a matter of coding style conventions, I would say that using the implicit property function call feature on a function that changes state is *bad* style, and surely hope the community would agree on that.
>>> So "src.next" would be must better as "src.next()" as "src.next" really just makes me cringe.
>>
>> 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.
> 
> Yes, I full agree, as many others do, as this has been discussed before (the latest discussion: http://www.digitalmars.com/d/archives/digitalmars/D/Omittable_parens_is_an_evil_73881.html) 
> 
> But that didn't seem to convince any of the higher-ups, so I was hopping to at least have the feature used more sensibly (ie, not being used in functions that are not intended to emulate properties).

Following that link I see there is a problem with accessing .mangleof. So the compiler sees a.b.mangleof and performs a.b().mangleof. I think that is a compiler bug because built-in properties like mangleof and sizeof should have priority over symbol evaluation.

Then I see a problem with new Thread(run). I think that is C++ habit at work.

Finally there's a discussion on how various language additions could work. I don't see how Walter could be convinced.


Andrei
September 26, 2008
KennyTM~ wrote:
> Andrei Alexandrescu wrote:
>> Bruno Medeiros wrote:
>>> As a matter of coding style conventions, I would say that using the implicit property function call feature on a function that changes state is *bad* style, and surely hope the community would agree on that.
>>
>> I sure hope they won't agree to an unsupported assertion.
>>
> 
> Actually I *do* hate this "feature" ^_^.
> 
> And this "feature" has been put to challenged before:
>  * Bug 2159. (http://d.puremagic.com/issues/show_bug.cgi?id=2159)
>  * "Omitting Parens is an Evil" (http://www.digitalmars.com/d/archives/digitalmars/D/Omittable_parens_is_an_evil_73881.html) 
> 
> *http://www.digitalmars.com/pnews/read.php?server=news.digitalmars.com&group=D&artnum=17579 
> 
> But nothing got changed.

I don't think the bug report has much strength.

> To the very least, when using next as a property I assume the call won't produce any secondary effect on src from the syntax, since I'm just reading a state! Not so if one calls src.next() as the "()" is an alarming sign that src _may_ change afterwards. This could is just a problem of personal taste since the compiler does not forbid src.next(), but not so if you're reading other's code.
> 
> P.S. If src.next() is too lengthy, why not just adopt ++src?

Because people (in wake of the recently introduced array operations) may legitimately expect that to mean "increment all elements of src".


Andrei
September 26, 2008
"Andrei Alexandrescu" wrote
>> P.S. If src.next() is too lengthy, why not just adopt ++src?
>
> Because people (in wake of the recently introduced array operations) may legitimately expect that to mean "increment all elements of src".

So in one case, you believe people's assumptions aren't important, i.e. an assumption that .next without parens will not change anything on the object, yet in another case you believe people's assumptions are the main argument. This doesn't sound consistent.

Not that I care too much :)  I am also in the camp of 'defined properties should be a language feature,' but I admit to using D-properties quite often.

The two things that bug me the most about D property syntax:

stuff like this:

x;

What the hell does this mean?  It looks like it does nothing.  But it could be a function call.  If explicit properties were required, and x was defined as a function, not a property, then x; would be a syntax error.

And stuff like you said:

writefln = 3;

I've been bitten by this type of weirdness.  In Tango, in the TimeSpan struct, I created several properties, one of which was:

ulong seconds();

Which converts the entire timespan to seconds.

I also had static 'constructors' to build time spans from common time types that looked like this:

static TimeSpan seconds(ulong nseconds);

Well, someone complained that this didn't set the timespan's value to 3 seconds, in fact the second line does nothing but create a temporary TimeSpan and throw it away:

TimeSpan ts = TimeSpan.seconds(5);
ts.seconds = 3;

And it does seem like it should set ts to equal 3 seconds.

So we were forced to abandon the succinct syntax of the static constructors and rename them fromSeconds, etc.  If properties were explicit, then I could define 'hey you can only use this static constructor as a function NOT a property'.  It's really those cases where you want to disallow one use or the other that are desired but not allowed by the current language.

-Steve


September 26, 2008
Steven Schveighoffer wrote:
> "Andrei Alexandrescu" wrote
>>> P.S. If src.next() is too lengthy, why not just adopt ++src?
>> Because people (in wake of the recently introduced array operations) may legitimately expect that to mean "increment all elements of src".
> 
> So in one case, you believe people's assumptions aren't important, i.e. an assumption that .next without parens will not change anything on the object, yet in another case you believe people's assumptions are the main argument. This doesn't sound consistent.

Of course it is. One expectation has to do with operational consistency (albeit a tad far-fetched), the other has to do with being used to a mistaken decision in the C language design.

> Not that I care too much :)  I am also in the camp of 'defined properties should be a language feature,' but I admit to using D-properties quite often.
> 
> The two things that bug me the most about D property syntax:
> 
> stuff like this:
> 
> x;
> 
> What the hell does this mean?  It looks like it does nothing.  But it could be a function call.  If explicit properties were required, and x was defined as a function, not a property, then x; would be a syntax error.

And what would be the advantage? I routinely use writeln; without feeling it makes for inferior style.

> And stuff like you said:
> 
> writefln = 3;
> 
> I've been bitten by this type of weirdness.  In Tango, in the TimeSpan struct, I created several properties, one of which was:
> 
> ulong seconds();
> 
> Which converts the entire timespan to seconds.

I agree.

> I also had static 'constructors' to build time spans from common time types that looked like this:
> 
> static TimeSpan seconds(ulong nseconds);
> 
> Well, someone complained that this didn't set the timespan's value to 3 seconds, in fact the second line does nothing but create a temporary TimeSpan and throw it away:
> 
> TimeSpan ts = TimeSpan.seconds(5);
> ts.seconds = 3;
> 
> And it does seem like it should set ts to equal 3 seconds.
> 
> So we were forced to abandon the succinct syntax of the static constructors and rename them fromSeconds, etc.  If properties were explicit, then I could define 'hey you can only use this static constructor as a function NOT a property'.  It's really those cases where you want to disallow one use or the other that are desired but not allowed by the current language.

I agree.


Andrei
September 26, 2008
Andrei Alexandrescu wrote:
> KennyTM~ wrote:
>> Andrei Alexandrescu wrote:
>>> Bruno Medeiros wrote:
>>>> As a matter of coding style conventions, I would say that using the implicit property function call feature on a function that changes state is *bad* style, and surely hope the community would agree on that.
>>>
>>> I sure hope they won't agree to an unsupported assertion.
>>>
>>
>> Actually I *do* hate this "feature" ^_^.
>>
>> And this "feature" has been put to challenged before:
>>  * Bug 2159. (http://d.puremagic.com/issues/show_bug.cgi?id=2159)
>>  * "Omitting Parens is an Evil" (http://www.digitalmars.com/d/archives/digitalmars/D/Omittable_parens_is_an_evil_73881.html) 
>>
>> *http://www.digitalmars.com/pnews/read.php?server=news.digitalmars.com&group=D&artnum=17579 
>>
>> But nothing got changed.
> 
> I don't think the bug report has much strength.

I mean the discussion within the bug report. That's a voice from the community isn't it?!

> 
>> To the very least, when using next as a property I assume the call won't produce any secondary effect on src from the syntax, since I'm just reading a state! Not so if one calls src.next() as the "()" is an alarming sign that src _may_ change afterwards. This could is just a problem of personal taste since the compiler does not forbid src.next(), but not so if you're reading other's code.
>>
>> P.S. If src.next() is too lengthy, why not just adopt ++src?
> 
> Because people (in wake of the recently introduced array operations) may legitimately expect that to mean "increment all elements of src".
>

It's fine not to use ++src since C++ is the only language that uses this syntax for iterators anyway, but may I mention that, to increase all elements of an array you use ++a[], note that there is a [] in the end.  ++a is syntax error anyway.

Also you should complain about ++p vs ++*p for a pointer p ;)

Like the () after the function call, which says I want to return the value after the function execution instead of the function object, the [] to my mind also signify I'm working on the content of the array, not the array itself.

> 
> Andrei
September 26, 2008
KennyTM~ wrote:
> Andrei Alexandrescu wrote:
>> KennyTM~ wrote:
>>> Andrei Alexandrescu wrote:
>>>> Bruno Medeiros wrote:
>>>>> As a matter of coding style conventions, I would say that using the implicit property function call feature on a function that changes state is *bad* style, and surely hope the community would agree on that.
>>>>
>>>> I sure hope they won't agree to an unsupported assertion.
>>>>
>>>
>>> Actually I *do* hate this "feature" ^_^.
>>>
>>> And this "feature" has been put to challenged before:
>>>  * Bug 2159. (http://d.puremagic.com/issues/show_bug.cgi?id=2159)
>>>  * "Omitting Parens is an Evil" (http://www.digitalmars.com/d/archives/digitalmars/D/Omittable_parens_is_an_evil_73881.html) 
>>>
>>> *http://www.digitalmars.com/pnews/read.php?server=news.digitalmars.com&group=D&artnum=17579 
>>>
>>> But nothing got changed.
>>
>> I don't think the bug report has much strength.
> 
> I mean the discussion within the bug report. That's a voice from the community isn't it?!

I agree. But then should we take arguments at face value, or just consider them valid because they exist?

>>> To the very least, when using next as a property I assume the call won't produce any secondary effect on src from the syntax, since I'm just reading a state! Not so if one calls src.next() as the "()" is an alarming sign that src _may_ change afterwards. This could is just a problem of personal taste since the compiler does not forbid src.next(), but not so if you're reading other's code.
>>>
>>> P.S. If src.next() is too lengthy, why not just adopt ++src?
>>
>> Because people (in wake of the recently introduced array operations) may legitimately expect that to mean "increment all elements of src".
>>
> 
> It's fine not to use ++src since C++ is the only language that uses this syntax for iterators anyway, but may I mention that, to increase all elements of an array you use ++a[], note that there is a [] in the end.  ++a is syntax error anyway.
> 
> Also you should complain about ++p vs ++*p for a pointer p ;)
> 
> Like the () after the function call, which says I want to return the value after the function execution instead of the function object, the [] to my mind also signify I'm working on the content of the array, not the array itself.

I agree, hence my "far-fetched" qualification in the reply to Steve.


Andrei
September 26, 2008
In article <gbiqbo$m1e$1@digitalmars.com>, SeeWebsiteForEmail@erdani.org says...
> Sergey Gromov wrote:
> > In article <gbgu0h$5sq$1@digitalmars.com>, SeeWebsiteForEmail@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
}

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.  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() {...}
}

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.
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19