Revised RFC on range design for D2

Steven Schveighoffer schveiguy at yahoo.com
Thu Oct 2 08:30:07 PDT 2008


"Michel Fortin" wrote
> On 2008-09-30 09:42:43 -0400, "Steven Schveighoffer" said:
>
>> "Michel Fortin" wrote
>>> On 2008-09-29 12:55:18 -0400, "Steven Schveighoffer" said:
>>>
>>>> Stdout.newline.formatln("Hi there {}", var);
>>>>
>>>> Is newline a property of Stdout, on which I'm calling formatln, or is
>>>> newline a function that I'm calling, and then using the result of that
>>>> function to call formatln?  Compare with:
>>>>
>>>> Stdout.newline().formatln("Hi there {}", var);
>>>>
>>>> There is no ambiguity.  newline is clearly a function, not a property.
>>>
>>> Interesting. To me both of these things have exactly the same meaning.
>>> Perhaps it's because I'm used to D, but I think it's more because I 
>>> can't
>>> count how many times I've seen this pattern in C++:
>>>
>>> SomeSimgleton::Instance().doSomething();
>>>
>>> where Instance() is simply an accessor.
>>
>> Yes, that is a workaround for not having property constructs available. 
>> The
>> intuitive label of 'property' comes from the name of the getter 
>> 'Instance'.
>> It screams that you are getting the instance of the class, and it's well
>> accepted as a property.  What has happened is that instead of relying on 
>> the
>> compiler to enforce what is a property and what is not, you are relying 
>> on
>> the interpretation of English words.
>
> But one problem is that the distinction between a accessor (of a property) 
> and a function is often matter to interpretation. In the case above, most 
> likely the Instance() function will create the singleton object if it 
> doesn't exist yet; seen that way it isn't a simple accessor. If you ask if 
> Instance() should be a property or not, you're likely to get different 
> answers from different people.

The difference is syntax-implied meaning.  A property is a field implemented 
as a function.  It is a form of information hiding and imposing access on a 
field, which could be a virtual field.  By specifically defining properties, 
I'm telling you, 'this is a field.  Access it like a field.  pay no 
attention to how the field is constructed, or whether it is actually a field 
or not'.  This allows me to later on make it a true field if it seems like 
the right decision.  Or to specify a guarantee about properties.

The other way around is already possible.  I can take a field that is 
already in use and make it into a property.  But the reverse is not so easy. 
Anyone who has accessed the field using parentheses would now have to go 
back and change all their code to remove the parentheses.

For example, with the magic of static constructors, I can change Instance 
from a property to an actual field, by initializing it in a static 
constructor.  Now every place you use Instance() (and there's probably a lot 
of them) is now invalid code.  If the *required* method of accessing 
Instance is without parens, then you notice no differences, and the 
interface to Instance remains the same.

As far as interpreting code, with the current state of affairs a function 
can be called like a field, which makes things more difficult to decipher. 
What is this symbol supposed to be?  It becomes an interpretation of the 
actual words used, which I don't argue isn't part of the equation anyways, 
but leaving it completely up to that is not as precise.  I have a real world 
example where someone thought a static constructor method I wrote was 
actually a property setter.  See this bug in Tango: 
http://www.dsource.org/projects/tango/ticket/1184  I never intended the 
static constructor to be a property, but it just works that way because the 
compiler matches the developer's request for a setter property by finding a 
static function which does nothing like the developer intended.  So it's a 
very hard bug to solve, and we couldn't solve it in the way I wanted, 
because the compiler cannot be forced not to look at all functions as 
possible properties.

I agree that there is a subjective line as to what makes a property and what 
does not.  What I propose is that we put the control of that line in the 
hands of the author, not the hands of the user.  If the author thinks it's 
better used as a property, that is their call.  It shouldn't be up to the 
user to say 'hey, I thought you meant function() here, you can't change it 
now!'  It's the same concept behind interfaces.

> Arguably, there are cases even more ambiguous than this one. The issue I 
> want to bring is that without having a formal definition of what is a 
> property and what is not -- one the compiler can enforce -- people will 
> make different choices, not always coherent with each others, and you may 
> very well find yourself having to call Instance() with parenthesis in one 
> D lib and without parenthesis in another.

You end up with that situation anyways.  If you have a project written by 
more than one person, one developer might use parens, one might not for the 
*same library* not just different libraries.  Hell, I use the same function 
sometimes as property or function depending on how much I'm paying 
attention.  I don't like the inconsistency that allowing all noarg functions 
to potentially be properties fosters.

At least with a formal definition, the user of the lib knows what the author 
was trying to create, and uses the property in a forwards-compatible 
fashion.

>> But in a language like C#, you would define Instance as a property, not a
>> function.  So it would never look like that.
>
> I could, but should I?
>
> I'm very interested in your criterions about why Instance would qualify to 
> be a property and not as a function in this case.
>
> It's not just me. Just as an example, this article's author doesn't want 
> to decide if Instance() should be a property or not:
> <http://www.yoda.arachsys.com/csharp/singleton.html>
> "Note that all of these implementations also use a public static property 
> Instance as the means of accessing the instance. In all cases, the 
> property could easily be converted to a method, with no impact on 
> thread-safety or performance."

I guess what I should have said is that I would make it a property ;) 
Sometimes it's hard to envision a different point of view, but you are 
absolutely right, it could be considered a function instead.

My definition of what I would like to see in an accessor (mind you, this is 
my definition, and would only be valid for libraries I wrote.  Someone else 
could have a different definition, and that's fine with me) is something 
that consistently returns a value.  So if I called it twice without anything 
changing, it would return the same thing, and accessing it doesn't change 
what it returns next time.

So Instance qualifies because once it is constructed, it always returns the 
same thing.  Perfect example of a use for an accessor property (to me 
anyway).

If two different libraries use different accessing methods for Instance, 
that's fine.  At least it's consistent.  You are going to have a hard time 
enforcing design decisions over all the different libraries you use to be 
consistent.  But at least they should be consistent every time you use them.

>> In D, properties are equivalent to functions, so you have a choice as to
>> whether to use the parentheses or not.  But that isn't the problem, the
>> problem is really that you can call functions as properties.
>
> But what is the difference between a property and a function (beside the 
> syntax?). I can find countless discussions on the net about this; 
> interesting discussions but with no definitive answer. In the end, it all 
> boils down to the author's feeling about his function/property, which may 
> be the opposite from its user's.

The difference is the interface.  Which is the syntax, and that is important 
to me at least.  If you don't like the authors usage of properties, don't 
use the lib.  I don't see any other aspect of library design that leaves it 
up to the user as to how their functions/objects should be interfaced.  Why 
should the user be allowed to decide the property/function interface?

> I'd like very much to quote Bruce Wood from this discussion:
> <http://bytes.com/forum/thread478064.html>
>
> (feel free to comment the quote)
>
> """
> You see, it's not always so cut-and-dried.
>
> On the one hand, if you make something a property, you are implying
> that getting the information will be quick. So, if getting the
> information is slow, that is a hint that it shouldn't be a property.

This is the opinion of the author (and I have the same opinion), but it's 
not written in stone.  The only things that are written in stone (or I guess 
binary) are what the compiler guarantees.  These kinds of debates have no 
real true answer, so there is no way to enforce.  How would you enforce it 
anyways?

But you can enforce the interface, and that's what I want.

> On the other hand, you don't want to determine what is a property or
> not based upon implementation details. By doing so you're letting the
> internal guts of how your class works leak out into its interface with
> the outside world. That's bad style. So, something should be a property
> if it makes sense that it be a property.
>
> Certainly, anything that affects the state of the object in a manner
> more sophisticated than just "set this to that" should be a method.
> That's painfully obvious.

I disagree with that ;), but then again that's my opinion and there is no 
right answer.

> Similarly, an aspect of your class that can be read and set, even if
> setting it does more than just set a variable, should probably be a
> property. Reasonably straightfoward.
>
> However, sometimes the two design goals above-properties that return
> results quickly and not letting implementation determine
> interface-are at odds with each other, and you have to make a
> judgement call.
>
> In the case of my system, I had things that logically should be
> properties (from an interface point of view) but the object held only
> keys, not references to the objects themselves, so the "get" on the
> property has to fetch the object in question from the database. It was
> an open question whether to code:
>
> Supplier theSupplier = stockItem.Supplier;
>
> or
>
> Supplier theSupplier = stockItem.GetSupplier();
>
> I chose the former, preferring to hide the implementation (holding
> supplier UID, not supplier itself) rather than let it leak out that
> getting the supplier was actually a lot of work. In our case it's no
> problem, because we're a very small shop. In a different situation I
> might have gone for door #2.
> """

In my opinion, I'd always go for door #1 in that case.  But I'd probably use 
some sort of cache, where the lookup was implemented as a function, and the 
access of the value was done as a property afterwards.

> With the current approach in D, you just don't need to choose, just 
> document what your function/property is doing and be done with it... well 
> you may still have to choose about the name :-), so in a way the argument 
> is still there, but what I mean is that I don't think we really need a 
> black and a white syntax for one concept that may take many shades of 
> gray.

We don't need a formal definition of what should or should not be a 
property.  But we need to allow the author to define what should or should 
not be a property.  Without doing this, you are making the interface 
inconsistent or ambiguous -- even if only from a syntax point of view.

>>> In my opinion, "newline" isn't a good function name for what it does
>>> because it has no verb. Having no verb makes it look like an accessor 
>>> much
>>> more than the absence or presence of parenthesis.
>>
>> So newline() seems like a property to you more than 'start a new line'? 
>> I
>> suppose I can see that, but consider if you were used to a system where
>> properties *prohibited* parentheses, and functions *required* them.  It
>> becomes less about interpretation of English vocabulary and more about
>> compiler-enforced interface.  I like that system better.
>
> But I'm still puzzled by what being a property means in opposition as if 
> it was a function.
>
> The thing is that the compiler just can't guaranty anything about 
> properties: it's really just another syntax for calling a function, a 
> function the author has classified as a property by some subjective 
> standard, a standard which will often differ between authors. Properties 
> are often touted as an indicator for low-cost functions -- 
> whatever "low-cost" means --, but even this fuzzy standard somewhat hinder 
> the often seeked goal of separating interface and implementation.
>
> Without aggreement on a formal definition for properties and compiler 
> enforcability, I find it very difficult to justify a formal syntax for 
> properties.

But you have no problems allowing a library author to define what is an 
interface and what is a class?  Or what is a struct?  Or if a function 
should return by value or by reference?  Defining the interface is the job 
of the author, and the very very good reason behind that is so the author 
can change details without changing the interface to make upgrades easier 
for him *and* you.  If he cannot define the interface, then he cannot make 
changes without affecting someone.

-Steve 




More information about the Digitalmars-d-announce mailing list