@property - take it behind the woodshed and shoot it?
Adam Wilson
flyboynw at gmail.com
Fri Jan 25 11:10:56 PST 2013
On Fri, 25 Jan 2013 10:39:50 -0800, H. S. Teoh <hsteoh at quickfur.ath.cx>
wrote:
> On Thu, Jan 24, 2013 at 12:34:42AM -0800, Walter Bright wrote:
>> This has turned into a monster. We've taken 2 or 3 wrong turns
>> somewhere.
>>
>> Perhaps we should revert to a simple set of rules.
>>
>> 1. Empty parens are optional. If there is an ambiguity with the
>> return value taking (), the () go on the return value.
>>
>> 2. the:
>> f = g
>> rewrite to:
>> f(g)
>> only happens if f is a function that only has overloads for () and
>> (one argument). No variadics.
>>
>> 3. Parens are required for calling delegates or function pointers.
>>
>> 4. No more @property.
>
> I've refrained so far from participating in this thread, but maybe it's
> time to say something.
>
> 1) @property and optional parentheses are orthogonal issues. Let's not
> conflate them and cause more unnecessary confusion in what is already
> a complex and convoluted discussion.
>
> 2) Personally, I don't like leaving out parentheses, but I don't really
> care either way. In any case, this has nothing to do with @property.
>
> 3) So, as far as @property is concerned, let's forget about optional
> parentheses or not.
>
> 3) @property is necessary for good abstraction. Yes, there have been
> precedents of abuse (like .dup and .idup, which really should *not*
> be properties but methods), and there are problems in the current
> implementation of @property, but the _concept_ of @property itself is
> a sound one. People have already mentioned the use case of a member
> variable that needs to be replaced with a getter/setter method.
> Conceptually speaking, the user of the class should not need to know
> or care whether it's just a POD field or an abstract entity
> manipulated by @property functions.
> For example, an Array class has a .length property, and user code
> should not need to know nor care if this length is an actual size_t
> field, or something else. All it needs to know is you can get a
> size_t out of it, and (optionally) change its value (if it's
> non-const, or if there's a setter method).
>
> Sometimes, you get into the situation where it's *possible* to
> implement a @property as a plain old field, but not desirable because
> of the SSOT (single source of truth) principle. It could be a
> computed value based on implementation-specific parameters, for
> example. It would not be nice if you had to store its value, then
> change code everywhere to make sure that it's always updated when the
> underlying parameters change. Lots of ugly, unnecessary, inefficient,
> and fragile code.
>
> Therefore, @property is necessary. If it causes a problem with the
> syntax, well, that's a problem with the syntax, not with the concept
> of @property itself.
>
> As far as syntax is concerned, it should be very straightforward. Given
> that the goal of @property is to simulate a variable, it should
> syntactically be identical to a variable, regardless of what it returns.
> So, given:
>
> struct S {
> @property T prop() { ... }
> }
> S s;
>
> Then:
>
> a) Writing s.prop returns a value of type T, for any type T (POD or
> struct or class or delegate or whatever);
> b) Writing s.prop() invokes opCall on the *return value* (because .prop
> behaves exactly as though it were an actual field);
> c) As a corollary, if T is not callable, then s.prop() is illegal;
> d) &s.prop returns a pointer to T (if .prop returns a ref).
> e) As for taking the address of the .prop function itself, my take on it
> is that (i) from a user's POV, .prop should be indistinguishable from
> a plain old field, so you shouldn't ever need to do this, and
> therefore (ii) it's impossible, and (iii) if you *really* need to do
> it, do this instead:
>
> struct S {
> @property T prop() { return this.propImpl(); }
>
> // You really only need to know about propImpl if you're
> // inside S's implementation anyway, so this is private.
> private T propImpl() { ... }
>
> void someMethod() {
> auto ptr = &propImpl;
> // There, now you have it.
> }
> }
>
> f) IOW, .prop cannot be distinguished from an actual field under normal
> circumstances. If you *really* need to do this (e.g. in serialization
> code), then use __traits.
>
> Consequently:
>
> - Assignment syntax like f=g should NOT be treated equivalently to f(g)
> because conceptually it makes no sense. Writing writeln = "abc"; makes
> no sense because writeln is not a value that you write to. Writing
> s.prop = "abc" *does* make sense, because S.prop is a @property, and
> therefore behaves like a variable. Writeln is a function, not a
> @property, so this is illegal.
>
> - Syntax like s.prop++ should work automatically (equivalent to
> s.prop(s.prop+1)), if .prop has both a getter and setter @property.
> It should NOT be allowed for arbitrary methods m just because m has
> both overloads of m() and m(T).
>
> - It's illegal to mark a function that takes 2 or more arguments as
> @property, because it makes no sense.
>
> The bottom line is, if you mark a function as @property, then it should
> behave as if it were a variable of its return type. This has nothing to
> do with optional parentheses or not, and assignment syntax should be
> reserved for variables (and by extension @property, because @property
> means something behaves like a variable), not arbitrary functions.
>
>
> T
>
++
--
Adam Wilson
IRC: LightBender
Project Coordinator
The Horizon Project
http://www.thehorizonproject.org/
More information about the Digitalmars-d
mailing list