Revised RFC on range design for D2

Andrei Alexandrescu SeeWebsiteForEmail at erdani.org
Thu Sep 25 15:58:52 PDT 2008


Yigal Chripun wrote:
> Andrei Alexandrescu wrote:
>> Sergey Gromov wrote:
>>> In article <gbgpak$2q10$1 at digitalmars.com>,
>>> brunodomedeiros+spam at 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.
>>
>> Two nice examples of the undesirability of distinct notation are the
>> std::pair first and second members in the STL, which made what seemed
>> like an innocuous decision turn into a catastrophe, and also
>> std::numeric_limits<T>::min and max, which partially prompted creation
>> of an entire language feature(!).
>>
>>
>> Andrei
> 
> I've got a few questions regarding this:
> suppose D gets a specific syntax for properties like C# has:
> for example:
> class MyClass {
> private int x;
> public int X {
>   get {
>     return x;
>   }
>   set {
>     x = value;
>   }
> }
> }
> 
> wouldn't it solve the problem of the implementer switching between a
> direct member and a function, transparently to that type's use?
> In the above you could remove the data member and re-implement the
> get/set by calling suitable functions.

It would solve the problem by adding a language feature. It is unclear 
to me whether the cost of adding the feature justifies its benefits.

> my main question is of style:
> is it better in your opinion to allow all functions with no parameters
> to be called as "function_name;" (i.e. no parens) and if you need to
> refer to the function identifier itself you need to do &func (for
> example if you want to pass it as a parameter to a different function)
> OR
> require an operator such as parens to signify you call the function and
> the name without parens will just signify the function itself (so no
> need to use &func when func is a parameter) ?

There are a few principles at work here that I consider universal, plus 
some others that I consider a matter of preference. One principle that I 
consider universal is that a language should minimize the number of 
syntactic constructs that are semantically and/or pragmatically 
meaningless. Another that I also consider universal is that the more 
frequently-used constructs should be given syntactic priority over the 
less-used constructs, particularly when the latter are also at risk of 
breaking the first principle.

C's handling of function names royally breaks both of these principles. 
It makes

func;

a valid syntactic construct with inoperant semantics and consequently 
useless pragmatics. Moreover,

a = func;
gunc(func);

both have valid syntax and semantics, but the pragmatics are the 
infrequently-used manipulations of function addresses in higher-order 
programming, something C is not quite adept at to start with. (So that 
makes the state of affairs all the more ironic.)

C++ builds on that irony by making

obj.func;
b = obj.func;
gunc(obj.func);

still syntactically valid but one order of magnitude less useful because 
they traffic in references to member functions, a contraption that is 
defined sufficiently bad and inefficient to be useless in practice, and 
also of a type with a syntax I'd be glad to remove from my memory. (How 
many here _do_ know that type's syntax and have the scars to prove it?)

So thinking of function call syntax has quite a few deep underpinnings. 
We shouldn't confuse habit acquired from C and C++ with some fundamental 
truth or just a matter of preference that can't be decided on an 
objective basis.

One issue with today's function call syntax in D is that people can 
write code that is of dubious expressiveness:

writeln = 3;

Properties would solve this problem by confining assignment syntax to 
themselves only.


Andrei


More information about the Digitalmars-d-announce mailing list