@property

Adam D. Ruppe destructionator at gmail.com
Sun Aug 5 07:32:49 PDT 2012


On Sunday, 5 August 2012 at 04:12:23 UTC, Jonathan M Davis wrote:
> I'd be very surprised if all that many people compile with 
> -property.

Indeed. Sometimes I try it just to see what happens, and always 
the same results: it doesn't solve problems and complains about 
code.

Some examples of things that break:

import std.algorithm;
foreach(i; [1,2,3].map!"a+1") {

}
prophate.d(5): Error: not a property [1,2,3].map!("a+1")


Of course, this is relatively new, using ufcs in 2.059, so the 
breakage probably isn't too bad, but I'm not the only one who 
writes it this way - I've seen a number of reddit and newsgroup 
comments do this too, especially when chaining it.

Another thing I do is I have a template function called 
getDocument in a lot of my code. It takes the document name as a 
template param, because in a lot of cases, I want to build the 
doc at compile time.

auto document = getDocument!"about-me";

Is that a function or a property? I think it is a function, it 
does a lot work. But, the arguments are there already... do we 
really need to say getDocument!"about-me"() just to appease a 
compiler switch?

(This function also can take some runtime params, but it has 
defaults so param less calling works as well.)



What about std.conv? This works fine in all old code - its 
functions either naturally require parens (such as 
to!(int)("10"), gotta have at least the outer set, or octal!"555" 
- it is an enum, so gotta not use them).... but with UFCS, that's 
actually out the window now:

         int i = "10".to!int;
prophate.d(4): Error: not a property "10".to!(int)


Now, I've never actually written this. With map!(), I do that in 
the real world, but not with this. Still, I could imagine someone 
who might. If we had the strictness before 2.059, I could live 
with it. Just add the () (though, then queue the people 
complaining about syntatic noise!).


But, now we're several months past that. I say that ship has 
sailed.



The big breakage for me is something I have been doing for years 
though, and that's using my dom.d with chaining:

import arsd.dom;

// in one place I might use:
auto ele = Element.make("span", 
"Hello").className("hello").setAttribute("foo", "bar");

// but in another I say:

ele.className = "something";



Now, many of my newer functions obviate this kind of thing; 
Element.make now offers overloads for inner text, inner html, and 
common attributes. There's now an addClass() so it isn't all 
dependent on className.

But, there's still hundreds of lines of me using the older 
functions like this, and every so often, it still comes up.

What happens with -property?


prophate.d(7): Error: not a property ele.className
arsd/domconvenience.d(49): Error: not a property className
arsd/domconvenience.d(81): Error: not a property n.strip
arsd/domconvenience.d(81): Error: not a property className
arsd/domconvenience.d(88): Error: not a property className
arsd/domconvenience.d(218): Error: not a property e.innerHTML
arsd/dom.d(201): Error: not a property e.innerText
arsd/dom.d(212): Error: not a property e.innerText
arsd/dom.d(217): Error: not a property e.innerText
arsd/dom.d(232): Error: not a property e.innerText
arsd/dom.d(234): Error: not a property e.className
arsd/dom.d(242): Error: not a property m.innerHTML
arsd/dom.d(506): Error: not a property name.toLower
arsd/dom.d(508): Error: not a property value.strip
arsd/dom.d(1162): Error: not a property child.innerText
arsd/dom.d(1634): Error: not a property innerText
arsd/dom.d(1831): Error: not a property e.innerText
arsd/dom.d(1859): Error: not a property child.innerText
arsd/dom.d(1913): Error: not a property e.innerText
arsd/dom.d(2135): Error: not a property 
this.captionElement().innerText
arsd/dom.d(2140): Error: not a property 
this.captionElement().innerText



wooo, but only the first line is this specific example. You can 
also see in here strip() and toLower() on which is just me being 
lax:

                         auto v = value.strip.toLower();

for example. Adding the inner parens would be annoying but it 
wouldn't require changing the form of the code like changing the 
dual use ones.




....huh, my example here actually does work if I set @property, 
but still use it as a function. Buggy switch. But I know I've 
tried this before and had one set of usages break with @property 
and another break without it. Maybe it was innerHTML, which can 
also be overloaded to take an Appender argument.

Yeah, then I get this:
arsd/dom.d(982): Error: cannot overload both property and 
non-property functions


There's just no winning without redoing a LOT of code, changing 
names, changing some expressions into statements since the 
chaining is out, duplicating functionality across two functions 
when one could do...


It was at that point that I decided it'd be better to put my 
effort into killing -property than trying to "fix" my code to 
appease its idiotic demands.




And now the UFCS map, filter, etc. chains and whatnot are just 
icing on the cake. Bearophile, I've seen you complain about the 
mess of parenthesis in std.algorithm before. With ufcs and 
template arguments, you can be rid of many of them. It is 
actually pretty beautiful, even to me.

Do you really want to break that now?


My position right now is @property has a strict syntax out of 
necessity. Stuff without @property should work the way it does 
now - thus minimizing broken code to that which already opted-in 
to @property (which generally does it right anyway), while 
keeping the status quo on the rest. It can turn out ugly, I'll 
agree, but it can be beautiful too and just plain isn't worth the 
code breakage either way.


More information about the Digitalmars-d mailing list