Fixing D's Properties
BCS
ao at pathlink.com
Sat Aug 18 10:29:09 PDT 2007
Reply to Chad,
> BCS wrote:
>
>> Reply to Chad,
>>
>>> -------------------------------------(1)
>>>
>>> First, the very common ambiguity:
>>>
>>> Does
>>> foo.bar++;
>>> become
>>> foo.bar( foo.bar + 1 );
>>> or
>>> foo.bar() + 1;
>>> ??
[...]
>> This is not a syntax issue with how properties are defined, but the
>> semantics of there use.
>> It can be fixed with minor changes.
>
> What minor changes?
>
> If you're going to suggest giving implicit properties lvalueness, then
> this would break any code that relies on the quirks of current
> implicit properties. I was hoping to preserve reverse compatibility
> with my solution, especially since Walter seems conservative about
> doing anything that breaks existing code.
>
How? Letting implicit properties be simultaneously L and R values (they can
now be either, just not both at the same time) won't break anything that
I know of. Anything that is legal now, still would be, and any cases where
the behavior would be different, were illegal to begin with.
>>> -------------------------------------(2)
>>>
>> [...]
>>
>> this is the same as #1 (or am i missing somthing)
>>
> Promotion != lvalueness
>
> The idea here is that #2 is a natural consequence of #1, thus you see
> them as the same. #2 though, has a different consequence for the
> programmer. #1 is merely very annoying, while #2 causes nasty code
> extensibility issues.
>
If you see them as disticntly different points, then we must be looking at
things at different levels. I see both 1 and 2 as saying: "properties can
be used with ++, += etc and members can". OK I'll grant that #1 doesn't cover
a few cases that #2 does, but that just makes #1 a special case of #2.
>>> -------------------------------------(3)
>>>
>>> Third, there is a problem with value types and properties. Consider
>>> the following code:
>>>
>> short version:
>>
>> struct S {int i; void I(int j){i=j;} }
>> struct P {S s void GetS() { return s;} }
>> P p;
>> p.GetS.I = 5; // assignes 5 to temp, not member of p
>>
>> This is a reference semantics issue. The same isses happens to
>> general functions.
>>
> Exactly. I don't want function semantics with my properties. I
> already have function semantics with my functions.
>
I see your point and I strongly disagree. Under the covers, it IS a function
and I /don't/ want that hidden.
>>> -------------------------------------(5)
>>>
>>> Fifth, delegates aren't over with yet.
>> [...]
>>> the user code that relies on the delegate will fail.
>> [...]
>>
>> ouch! that sounds worse than the problem you point out.
>>
> I disagree, but in light of what you value, it becomes an aesthetics
> vs functionality issue.
>
Unless you can trust the compiler to inline delegate literals (and the potentially
virtual function call underneath), it is a performance issue.
>>> ========================================
>>> How to fix it
>>> ========================================
>> [...]
>>
>>> *lvalue: If foo is an lvalue, than foo = 5; should set foo's value
>>> to
>>> 5, instead of evaluating to 5; and doing nothing. Implicit write
>>> properties fake this to some extent, but do not hold in the general
>>> case. Example (3) above and the foo++; and foo+=10; issues are
>>> examples
>>> where lvalueness is needed.
>>
>> I would disagree. I would clam that the issue is that implicit
>> properties can be used a lvalues or rvalues, but not both.
>>
> Still doesn't handle promotion/demotion between fields and properties.
My point was not intended to. It is a minor issue claming that the mechanics
of one of your (valid) issues with implicit properties is incorrectly stated.
> Also, if you have a way to make the lvalue&rvalue semantics work, let
> me hear it.
>
I think that you actually described somewhere the solution I wold use.
Use the R-value property (getter) to get the value, do the operation, then
use the L-value property (setter) to push it back in.
struct S { ... int i(); void i(int); }
S s;
s.i++;
// becomes
{
auto __tmp = s.i;
__tmp++;
s.i = __tmp;
}
If only one or the other property exits then it is assumed the author wants
to disallow this type of operation.
>> [......]
>>
>> The basis of your thoughts seem to come from the idea that hiding the
>> fact that properties are functions would be a good thing. I would
>> assert that this is highly debatable. I will concede that the current
>> semantics of properties being not quite interchangeable with fields
>> is sub optimal. However fixing this by creating a new construct that,
>> in the end, is identical to a function but with a number of things
>> forbidden seems somehow wrong.
>>
> Actually, I am suggesting that properties not be functions at all.
> They will of course share the notion of a body of executable code, but
> for all intents and purposes they are a way of accessing data while
> introducing side effects.
>
Will they be accessed by doing a call/return sequence at the machine code
level? If so, I would assert they are functions for all purposes I'm interested
in. If it would be implemented by some other means, then I have have missed
some major point of your post.
D is a low level language in many respects, as such, if it looks like a function
when it comes out of the compiler, I want to be able to treat it as a function
when it goes in.
>> As I see it the issues you bring up amount to:
>>
>> 1> no L/R-value usage (++, +=, etc, use as an inout or out arg)
>> 2> they can lead to hard to find reference semantics issues
>> 3> syntax problems with properties retuning delegates
>> 4> not interchangeable with fields
>> #1 can be fixed without explicit properties
>>
> how?
same as above
>
>> #2 is not at all a problem in my book
>>
> I have suffered many hours of debugging thanks to this "feature".
> Don't tell me it isn't a problem!
>
It's not a problem with /properties/. dropping properties compleaty wouldn't
remove this type of isses. It might make some cases easyer to spot but nothing
more. As to converting from a member to a property changing things, that
is part of point #4.
>> #4 this is a good point, however, as stated above, I don't like the
>> proposed solution. Also, the proposed solution doesn't fix the issue
>> because taking the address of a field is allowed, even with explicit
>> properties, this wouldn't work
>>
> If the proposed solution is not good enough, please give a better one.
> Suggestions are welcome and encouraged.
>
Nothing yet. IMHO, your proposed solution, while maybe appropriate for higher
level languages, is not right for D. If I see a solution that solves these
issues without cause to many of its own problems, I would be interested.
> As for the address of a field... perhaps if taking the address of a
> field returned a delegate... nah.
> This is somewhat of a corner case, but you've got me there, for now.
> I'd love to see someone come up with a slick solution to this.
> I should also note that C# didn't seem to have this problem with its
> explicit properties. That is probably because in C#, using pointers
> was
> considered "unsafe" and done very infrequently. It makes me want to
> bust out C# again and see what happens when one tries to take the
> address of a property, and I probably will at some point.
> Even if the addressing thing can't be fixed, I'd at least like to see
> the rest of the stuff get fixed.
I'll bet you can't. You can't use one for an out or ref argument (I just
cheked) but you can use a member.
More information about the Digitalmars-d
mailing list