new DIP5: Properties 2

Andrei Alexandrescu SeeWebsiteForEmail at erdani.org
Fri Jul 31 13:16:43 PDT 2009


Steven Schveighoffer wrote:
> On Fri, 31 Jul 2009 13:34:13 -0400, Marianne Gagnon <auria.mg at gmail.com> 
> wrote:
> 
>>
>>>
>>> I think the poll might have been skewed due to context (forget my
>>> newsgroup poll, that was worthy of an abortion, but I also didn't 
>>> mean to
>>> submit it :), I'm talking about Ary's)
>>>
>>> The question was asked, what do you think this code means.  In the 
>>> context
>>> of D, where you know a symbol without parentheses can mean either a
>>> function or a property/field, I'm certain there were several respondants
>>> who didn't understand it was asking what they think is best, not *what D
>>> currently does*.  Ask that same questions to C++ developers and see what
>>> you get...
>>>
>>> It's hard to phrase the question properly without bias to a group of
>>> people who already know the current behavior.  Maybe something like:
>>>
>>> Assume the D programming language required parentheses for normal
>>> parameter-less functions, and required no parentheses for parameter-less
>>> functions that returned a property.  For example, the following code
>>> should imply a getter for a filter inside x:
>>>
>>>      auto tmp = x.filter;
>>>
>>> And the following code should imply performing a filtering action 
>>> using x,
>>> returning the result:
>>>
>>>      auto tmp = x.filter();
>>>
>>> Do you think it's worth adding such a capability, given that you will 
>>> then
>>> no longer be able to call ordinary parameter-less functions without
>>> parentheses, an author of a property function must properly indicate 
>>> that
>>> the function is a property, and the compiler must trust the author for
>>> this implication?
>>>
>>
>>
>> IMP, the parenthesis thing is not about parameters vs function. I 
>> think the question is about whether the function can modify my object 
>> or not.
>>
>> e.g. if I call
>>
>> foo = object.x;
>>
>> I assume 'object' was not modified. But if x can be like a function, 
>> disguised as a parameter, I can modify my object without knowing.
>>
>> In C++, I'd say this behaviour is ok for 'const' functions. Now I 
>> haven't taken the time to study D constness, so I can't readily tell 
>> what is the direct equivalent, but I guess you understand what I mean.
>>
>> In short, IMO everything that can modify my object should require () 
>> to stress that this is an action with possible side effects, not 
>> merely a getter.
> 
> Hm... this is somewhat similar to const, be we already have const in D.
> 
> I think you and I or on the same page -- parentheses implies action, no 
> parentheses implies no action (and therefore, no change to the object).  
> However, I can envision properties that do take actions (such as 
> logging) and may even change the object (such as caching), and functions 
> that perform actions but do not modify the object.  I wouldn't say 
> modification of the object is a direct 1-to-1 mapping with parens or 
> lack of parens, but I'd definitely say that lack of parens implies no 
> "public" modification.
> 
> However, none of this would be enforcible via the compiler.  For that, 
> we have const.  A const property would make loads of sense, but 
> unfortunately, it modifies the contract you have with the object members 
> when calling it (see DIP2 
> http://prowiki.org/wiki4d/wiki.cgi?LanguageDevel/DIPs/DIP2).
> 
> So to sum up, with this feature lack of parentheses would imply no 
> action, but would not be enforced.  However, it would be considered 
> incorrect logic if the rule was not followed, similar to naming your 
> functions something other than what they do.

I am leery of such a feature. It essentially introduces a way to define 
conventions that are in no way useful to, or checked by, language rules. 
In my experience this has been a bad idea more often than not. Of 
course, simple conventions such as capitalized types, camel case values, 
and so on, are useful and easy to follow. But as soon as complexity of 
conventions becomes only a bit higher, their usefulness becomes a 
downward step function.

In C++ there were two ways to define a template:

template <class T> ...

and

template <typename T> ...

The existence of "typename" as a keyword has an interesting history of 
its own, but in here it was allowed for the reason that T may be any 
type, not a class type. So, people thought, it would be less confusing 
if people wrote "typename" for type template parameters.

So far so good. When I wrote Modern C++ Design, I decided to make a bold 
move and use "typename" in code samples wherever it could have been any 
type, and "class" wherever the type was indeed restricted to a class 
type. I documented that convention in the introduction and off I went.

The experiment was an unqualified failure. First of all, people got 
confused. Then some found actual "bugs" because I used one keyword when 
I had promised to use the other. Of course I had bugs - there's plenty 
of template code and no automated means to check it! If I could turn 
back in time, I'd just use "class" everywhere.

There are similar cases in other communities, probably Perl being a 
prime example because it allows most everything to mean something, so 
conventions are very important. My reading of the experience on 
espousing complex, unchecked, and unused reified conventions? Don't.


Andrei



More information about the Digitalmars-d mailing list