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