Possible @property compromise

Steven Schveighoffer schveiguy at yahoo.com
Thu Jan 31 07:57:12 PST 2013


On Thu, 31 Jan 2013 10:40:18 -0500, Michel Fortin  
<michel.fortin at michelf.ca> wrote:

> On 2013-01-31 14:50:40 +0000, "Steven Schveighoffer"  
> <schveiguy at yahoo.com> said:
>
>> It actually is a bit depressing, we have to reset the clock back to  
>> late  2009 to start over with properties...
>
> By the way I was a big proponent of properties with no semantic  
> ambiguities back in 2009. I even proposed a getX/setX scheme, which I  
> still like very much. I'd like to see real properties in D, but I don't  
> think it's realistic at this point.

Yes, I saw your post when looking for my post about the C# style which I  
couldn't find.

> And you have to admit that the way D does properties today is both  
> simple, clever, and appealing. It does have some error-prone liabilities  
> when it comes to callable types and generic programming especially, but  
> beside that I do like the design of the thing. It's a natural extension  
> of UFCS, even though it predates UFCS. Perhaps we should just call it a  
> day and live with the ambiguities. I don't like it, but I don't see any  
> viable alternative.

I liked it when I first saw it.  Seems, as you say, clever and intuitive.

However, it left a bad taste in my mouth when I had a certain situation  
that I was forced to deal with.

In Tango, I developed a struct called TimeSpan, which was a span of time  
(we have Duration in std.datetime which is similar).

I created constructors for spans of time that were named after the units  
they used.  For example, if you wanted a 10 minute, 30 second timespan you  
could do:

auto ts = TimeSpan.minutes(10) + TimeSpan.seconds(30);

The idea was to avoid having to document such a line, the above looks  
obvious.

Now, I also had accessors for a given timespan to return the timespan in  
those units.  For example:

assert(ts.seconds == 10 * 60 + 30);

The problem arose when someone complained that the seconds "setter" wasn't  
working:

ts.seconds = 5;

assert(ts.seconds != 5);

Wait, what?  I never made seconds a settable property!

Turns out, this translates to:

ts.seconds(5);

and because you can call static methods from an instance (another thing I  
don't really like), it made the constructor act like a property!  A  
completely unintended consequence.

The only viable solution (this was D1), was to rename the functions so  
they couldn't be mistaken as properties.  So they all became "fromSeconds"  
e.g.  Yuck!

This is one of the reasons I was so excited about D2 getting full-fledged  
properties.  I had used C# and liked the way those properties worked.

But we never got what was promised, and now we basically have the same  
junk with some duct-taped garbage keyword that half works.  No wonder  
people don't like @property!

At this point, I think it would be a huge step backwards not to solve (or  
at least have a yet-to-be implemented solution for) the above problem.  I  
can live with getters simply being parentheses-less functions, that isn't  
so bad (though as an API designer, I'd like to have full control over  
that).  But using any function as a setter is crap, and will forever be a  
wart on D unless we fix it.  It will result in bizarre things like mystery  
setters that don't exist, especially with UFCS.

-Steve


More information about the Digitalmars-d mailing list