August 05, 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.
August 05, 2012
On 05-Aug-12 18:32, Adam D. Ruppe wrote:
> 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.
>

+1

[snip]
>
> 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.

Well in the end I think strict @property enforcement was meant to solve some corner cases (e.g. returning delegates from, and taking address of no-arg functions). But then it promptly killed at least one cool idiom (chaining & assignment in one name). Then once UFCS was finally working @property spoiled it (e.g. your algorithm examples).

So I'm with you - let non-@property work as before, and @property ones to be god damn properly enforced.


-- 
Dmitry Olshansky
August 05, 2012
On Sun, 05 Aug 2012 16:32:49 +0200, Adam D. Ruppe <destructionator@gmail.com> wrote:

> 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.

Yeah. I seem to do that every single time I want to give an example.

-- 
Simen
August 05, 2012
Adam D. Ruppe:

> octal!"555" - it is an enum, so gotta not use them).... but with UFCS, that's actually out the window now:

What about turning octal into a propety to fix this problem?


> 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...

All my large amount of D2 code gives no warning with -property. Maybe you should fix your code.

Bye,
bearophile
August 05, 2012
On Sunday, 5 August 2012 at 15:45:37 UTC, bearophile wrote:
> What about turning octal into a propety to fix this problem?

octal actually works because it isn't a function.

But in general, changing non-properties to properties just for syntax is backward anyway. Whether something is a property or not isn't a question of parenthesis. I think it was a mistake to conflate "property" with "parenthesis-less syntax" in the first place, since they aren't really the same thing.

A getX/setX pair in C++ is conceptually a property, but uses a different syntax. A method call in Ruby is still a method call, despite being able to write it without parens.

Something should be marked @property because it fits the conceptual definition, not because you want to leave parens out.


That's also why I don't like -property's implementation: it focuses purely on the syntax, without worrying about the concept. If you get the concept right, the syntax will fit on its own - for example, a property returning an int shouldn't be callable with () because calling an int like a function is nonsense regardless.

> All my large amount of D2 code gives no warning with -property. Maybe you should fix your code.

Maybe you should pay my mortgage.
August 05, 2012
Adam D. Ruppe:

> Maybe you should pay my mortgage.

I understand. The kind of programs I write enjoy run-time errors raised on overflow on integral values operations. Recently I opened a silly thread about this in D learn. Adding those to D will help me pay my bills and better keep my mind.

Bye,
bearophile
August 05, 2012
On Sunday, 5 August 2012 at 14:32:50 UTC, Adam D. Ruppe wrote:
> 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.
> [snip]

I completely agree, particularl with the UFCS part. UFCS is designed to get rid of the horrible mess of (), and now we want to arbitrarily force a () anyways? Seems like it defeats the purpose. To me, when comparing
range.filter!"a > 2".map!"a*a".countUntil(3)
to
range.filter!"a > 2"().map!"a*a"().countUntil(3)
Those extra paranthesis just don't do anything, they don't give extra meaning, they don't accomplish anything useful but distract from the actual expression.

Most importantly though, with the focus on avoiding breaking code, why are we putting in -property which has the *sole* purpose of breaking existing code. And a whole lot of it at that. Never mind that a huge number of people strongly dislike the idea of enforcing paranthesis in the first place. It's not even about whether I agree with enforcing it, it's that I strongly disagree with breaking code for no benefit besides what some people will arbitrarily think is cleaner code, and others will not.
August 06, 2012
On Saturday, 4 August 2012 at 20:53:53 UTC, Adam D. Ruppe wrote:
> On Saturday, 4 August 2012 at 19:08:58 UTC, Jacob Carlborg wrote:
>> foo += 10;
>>
>> Is rewritten as:
>>
>> auto __tmp = foo;
>> foo = __tmp + 10;
>
>
> I did this and now I think this thing is almost done
>
> ===
> int a;
> @property int funcprop() {
>         writeln("calling the getter and getting ", a);
> 	return a;
> }
> @property int funcprop(int s) {
> 	writeln("calling the setter with ", s);
> 	return a = s;
> }
> void main() {
> 	funcprop = 40;
> 	funcprop += 10;
> }
> ===
>
> run:
>
> calling the setter with 40
> calling the getter and getting 40
> calling the setter with 50
>
>
>
>
> Looks right to me. Now I just have to check for the @property tag on some of these rewrites and then clean it up and test for a pull request.

It would be cool

http://forum.dlang.org/thread/xcbweciovapinaicxgbn@forum.dlang.org
and
http://d.puremagic.com/issues/show_bug.cgi?id=8006
August 07, 2012
On Sun, Aug 5, 2012 at 2:32 PM, Kapps <opantm2+spam@gmail.com> wrote:
> On Sunday, 5 August 2012 at 14:32:50 UTC, Adam D. Ruppe wrote:
>>
>> 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.
>> [snip]
>
>
> I completely agree, particularl with the UFCS part. UFCS is designed to get
> rid of the horrible mess of (), and now we want to arbitrarily force a ()
> anyways? Seems like it defeats the purpose. To me, when comparing
> range.filter!"a > 2".map!"a*a".countUntil(3)
> to
> range.filter!"a > 2"().map!"a*a"().countUntil(3)
> Those extra paranthesis just don't do anything, they don't give extra
> meaning, they don't accomplish anything useful but distract from the actual
> expression.
>

Just a small comment. I have been following this thread a little and was somewhat surprise that the argument against enforcing parenthesis on non-properties is that a call like [1,2,3].map!"a+1" would look ugly as [1,2,3].map!"a+1"(). To me that is a issue of the std.algorithm module and not so much of the language.

Personally I am not a huge fan of using strings as a way to pass a function into a high-order function. I suspect that this string stuff became popular because D didn't have lambda declarations and type inference when the module was designed and implemented. I wonder if the module signatures would look different if you designed it to use the current features of D.

To be honest, when first saw 'some_array.map!"a+1"()' a few years back when I first learned about D my knee jerk reaction was: "from where in the world is 'a' coming from?". I remember I had to read std/algorithm.d and whatever module implements unary "string" functions to figure out what was going on. Anyways, I digress.

Part of me looks forward to the day that I can use D reliably another part of my wants to just wait for Rust to hopefully get it "right".

Thanks,
-Jose
August 07, 2012
On Mon, Aug 6, 2012 at 11:59 PM, José Armando García Sancio < jsancio@gmail.com> wrote:

> On Sun, Aug 5, 2012 at 2:32 PM, Kapps <opantm2+spam@gmail.com> wrote:
> > On Sunday, 5 August 2012 at 14:32:50 UTC, Adam D. Ruppe wrote:
> >>
> >> 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.
> >> [snip]
> >
> >
> > I completely agree, particularl with the UFCS part. UFCS is designed to
> get
> > rid of the horrible mess of (), and now we want to arbitrarily force a ()
> > anyways? Seems like it defeats the purpose. To me, when comparing
> > range.filter!"a > 2".map!"a*a".countUntil(3)
> > to
> > range.filter!"a > 2"().map!"a*a"().countUntil(3)
> > Those extra paranthesis just don't do anything, they don't give extra
> > meaning, they don't accomplish anything useful but distract from the
> actual
> > expression.
> >
>
> Just a small comment. I have been following this thread a little and was somewhat surprise that the argument against enforcing parenthesis on non-properties is that a call like [1,2,3].map!"a+1" would look ugly as [1,2,3].map!"a+1"(). To me that is a issue of the std.algorithm module and not so much of the language.
>
> Personally I am not a huge fan of using strings as a way to pass a function into a high-order function. I suspect that this string stuff became popular because D didn't have lambda declarations and type inference when the module was designed and implemented. I wonder if the module signatures would look different if you designed it to use the current features of D.
>
> To be honest, when first saw 'some_array.map!"a+1"()' a few years back when I first learned about D my knee jerk reaction was: "from where in the world is 'a' coming from?". I remember I had to read std/algorithm.d and whatever module implements unary "string" functions to figure out what was going on. Anyways, I digress.
>
> Part of me looks forward to the day that I can use D reliably another part of my wants to just wait for Rust to hopefully get it "right".
>
> Thanks,
> -Jose
>

There was a pull to switch std.algorithm over to the new lambda syntax (by me).  It caused the dmd unit tests to fail though.  There is also an issue with intermodule visibility of nested structs that popped up and prevented the every function from being switched over.  I should probably recreate the pull request so one of the compiler guys can take a look.

BA