November 19, 2012
On Monday, 19 November 2012 at 21:44:35 UTC, Jonathan M Davis wrote:
> Excep that i don't think that it's really a question of style. It's treating a
> function as if it were a variable, when it's not only not a variable, but it's
> not even acting like one. It's implying that the code has one set of semantics
> when it has another. Dropping parens when specifically creating a function
> which is intended to emulate a variable makes sense. But dropping parens just
> because you feel like it then makes a function look like a variable when it's
> not and not intended to even act like one. That violates the very difference
> between function and variable on even a conceptual level. It would be one
> thing to make a particular character or sequence of characters optional when
> doing so doesn't make it look like it's something else entirely
>  (e.g.
> optional braces don't make anything look like anything else - they just drop
> some characters, and they don't introduce any ambiguities in the process). But
> it's quite another to make those characters optional when they make one
> language construct look like another.
>
> - Jonathan M Davis

I see what you are saying.

Consider this:

@property allows a function to behave as if it were a variable, so in that case we're effectively creating an alternate set of language constructs for at least some functions. The enforcement through @property however constrains it to only behave as if it were a variable and not a function, there's no ambiguity in this case, and it's clearly intentional, not a mistake.

Without @property, but allowing the programmer to decide if, when, and where, a function may emulate a variable, and when it will not, may confuse some people and may also confuse the compiler in some cases, but it does offer the programmer additional flexibility that may prove to be useful, although it may also prove to be a costly mistake, and if so it may be a matter of how good the programmer is.

All I know at this point is that because @property was not fully implemented as originally intended, I was able to experience the flexibility, and personally I found it to be OK for whatever reason, esp wrt UFCS.

I would still be happy to have @property perform constraints to enforce a function to emulate a variable or to resolve ambiguities, and certainly for any function no matter where it may be declared. I can definitely see the value in that and I can't see any reason for not supporting it.

Side Note: In some cases you may want a setter but no getter for write only variable emulation, or a setter but no getter for read only emulation.

What is not so clear, is if optional () should be allowed or not, but I do understand the argument that it makes the code look better in some cases which in that case is a question of style rather than anything to do with @property.

Also do not forget that we can not only drop the (), but also perform assignments to functions that take in one variable, but I'm not sure if the return must be void for that to work. It seems strange to allow arbitrarily dual function/variable constructs for functions, but being strange does not necessarily mean it is wrong.

I do wonder however, if there's something much more fundamental or generalized going on with this that can settle the question in clear terms? I fully understand the variable emulation argument, and it's seems to be sound, however imagine reversing the argument and suggesting that all (or some) variables should be enforced to emulate function calls with @function.

We've seen this being done in C++, where I can initialize a variable in multiple emulated ways:

// class constructor emulation
int x(42);

// function emulation
int y;
x = y(42);

// regular variable form
int x = 42;

I don't have an answer, but there may be more to the picture than we think.

--rt

November 20, 2012
On 11/19/12 5:23 PM, Rob T wrote:
> I don't have an answer, but there may be more to the picture than we think.

I agree. In particular I find it a specious argument to insist on religiously associating "()" with function calling and the lack thereof with variable access. I don't see myself, when seeing an expression like "generator(x, y, z).map!(x => x * x)()", going like "holy cow, good I saw those trailing parens, otherwise I would've sworn it was a variable". Trailing parens in UFCS chains are just warts, this is the reality. Let's deal with it.


Andrei


November 20, 2012
Le 19/11/2012 00:45, thedeemon a écrit :
> On Monday, 19 November 2012 at 08:23:43 UTC, Jonathan M Davis wrote:
>> On Monday, November 19, 2012 09:16:29 Rob T wrote:
>>> My guess is that if @property gets enforced, we'll see a lot of
>>> functions with empty parameter lists being defined as @property
>>> for the sole reason to get rid of having to type in the ().
>>
>> Which completely violates the concept of a property in the first
>> place. It's
>> intended to be an abstraction for a variable. Using @property just to
>> get rid
>> of parens would be like naming types with verbs instead of nouns. It's
>> completely backwards.
>>
>> - Jonathan M Davis
>
> I very much like the combination of UFCS, ranges and parens-free style
> which allows writing code like
>
> iota(0, 1000000).map!(to!string).retro.take(50).retro[10].writeln;
>
> So I like Andrei's idea to force @property only for those functions
> where it's absolutely necessary to fight ambiguity.

With opDispatch and clear semantic, the following is doable :

iota(0, 1000000).map!(to!string).retro.take(50).retro[10].writeln();

No need for an ambiguous situation where function get called implicitly.
November 20, 2012
Le 19/11/2012 06:58, Andrei Alexandrescu a écrit :
> On 11/19/12 4:01 AM, monarch_dodra wrote:
>> I kind of agree with Jonathan here. @property really shines when you
>> want to "add" an attribute to a struct.
>
> I kind of agree with him, too, but it would be a mistake to not reckon a
> change in dynamics. UFCS makes all those extra parens just awkward, and
> people will vote with their code regardless whether some particular
> viewpoint from some particular angle considers the approach backwards.
>
> Andrei

As aid bunch of time, I'm pretty sure we can have a clean semantic and still allow mosts use of parenthsesless call using opDispatch .
November 20, 2012
Le 18/11/2012 22:52, Andrei Alexandrescu a écrit :
> On 11/19/12 1:02 AM, Rob T wrote:
>> So what's up with @property?
>
> It's a mistake on top of another. We need to redesign it to such that
> the keyword '@property' is only required in cases that otherwise would
> be ambiguous (functions returning functions).
>
> Andrei
>

It isn't the only ambiguous case.
November 20, 2012
Le 19/11/2012 10:02, Adam D. Ruppe a écrit :
> On Monday, 19 November 2012 at 15:01:36 UTC, Andrei Alexandrescu wrote:
>> Would you please start a DIP with a paste of this idea?
>
> here it is:
> http://www.prowiki.org/wiki4d/wiki.cgi?LanguageDevel/DIPs/DIP21
>
> I tried to implement this a while ago and hit some pain after some early
> success. The pain was trying to get assignments to work without breaking
> other cases like returning ref.
>
> My plan was to make any reference to a @property change to a CallExp or
> whatever. But if you do that and it is on the left hand side of an
> assignment, you do the wrong thing.
>
> foo = foo + 1;
>
> should generally become:
>
> foo(foo() + 1);
>
> but if there isn't a setter, we should leave it as foo() = foo() + 1;
> and finding the setter is a bit of a pain. Then, of course, we ideally
> want foo += 1 to work too..
>

This make it impossible to only define a getter only when one want to return by reference.

> Maybe someone who knows the compiler better than me will make it look
> easy though.

November 20, 2012
On Monday, November 19, 2012 21:31:09 deadalnix wrote:
> Le 19/11/2012 10:02, Adam D. Ruppe a écrit :
> > On Monday, 19 November 2012 at 15:01:36 UTC, Andrei Alexandrescu wrote:
> >> Would you please start a DIP with a paste of this idea?
> > 
> > here it is: http://www.prowiki.org/wiki4d/wiki.cgi?LanguageDevel/DIPs/DIP21
> > 
> > I tried to implement this a while ago and hit some pain after some early success. The pain was trying to get assignments to work without breaking other cases like returning ref.
> > 
> > My plan was to make any reference to a @property change to a CallExp or whatever. But if you do that and it is on the left hand side of an assignment, you do the wrong thing.
> > 
> > foo = foo + 1;
> > 
> > should generally become:
> > 
> > foo(foo() + 1);
> > 
> > but if there isn't a setter, we should leave it as foo() = foo() + 1;
> > and finding the setter is a bit of a pain. Then, of course, we ideally
> > want foo += 1 to work too..
> 
> This make it impossible to only define a getter only when one want to return by reference.

Returning by reference generally already defeats the purpose of defining a property function in the first place. Certainly, if you return by ref, it _definitely_ defeats the purpose of only defining a getter. By returning by ref from a getter, you've not only implicitly declared a setter, but you've made it impossible to verify anything about what's being set, because it's going through the ref rather than through an actual setter.

- Jonathan M Davis
November 20, 2012
On 11/20/12 12:24 AM, deadalnix wrote:
> Le 19/11/2012 06:58, Andrei Alexandrescu a écrit :
>> On 11/19/12 4:01 AM, monarch_dodra wrote:
>>> I kind of agree with Jonathan here. @property really shines when you
>>> want to "add" an attribute to a struct.
>>
>> I kind of agree with him, too, but it would be a mistake to not reckon a
>> change in dynamics. UFCS makes all those extra parens just awkward, and
>> people will vote with their code regardless whether some particular
>> viewpoint from some particular angle considers the approach backwards.
>>
>> Andrei
>
> As aid bunch of time, I'm pretty sure we can have a clean semantic and
> still allow mosts use of parenthsesless call using opDispatch .

Could you please give more detail? On first sight this seems to complicate the majority case for the benefit of a few.

Andrei
November 20, 2012
On 11/20/12 12:28 AM, deadalnix wrote:
> Le 18/11/2012 22:52, Andrei Alexandrescu a écrit :
>> On 11/19/12 1:02 AM, Rob T wrote:
>>> So what's up with @property?
>>
>> It's a mistake on top of another. We need to redesign it to such that
>> the keyword '@property' is only required in cases that otherwise would
>> be ambiguous (functions returning functions).
>>
>> Andrei
>>
>
> It isn't the only ambiguous case.

That's why it's good to enumerate them all in http://www.prowiki.org/wiki4d/wiki.cgi?LanguageDevel/DIPs/DIP21.

Thanks,

Andrei
November 20, 2012
Le 19/11/2012 21:53, Andrei Alexandrescu a écrit :
> On 11/20/12 12:24 AM, deadalnix wrote:
>> Le 19/11/2012 06:58, Andrei Alexandrescu a écrit :
>>> On 11/19/12 4:01 AM, monarch_dodra wrote:
>>>> I kind of agree with Jonathan here. @property really shines when you
>>>> want to "add" an attribute to a struct.
>>>
>>> I kind of agree with him, too, but it would be a mistake to not reckon a
>>> change in dynamics. UFCS makes all those extra parens just awkward, and
>>> people will vote with their code regardless whether some particular
>>> viewpoint from some particular angle considers the approach backwards.
>>>
>>> Andrei
>>
>> As aid bunch of time, I'm pretty sure we can have a clean semantic and
>> still allow mosts use of parenthsesless call using opDispatch .
>
> Could you please give more detail? On first sight this seems to
> complicate the majority case for the benefit of a few.
>
> Andrei

consider the following opDispatch :

auto opDispatch(string name, T, U...)(T function() t, U args) {
    return mixin("t()." ~ name ~ "(args)");
}

I ommited to support delegates and to do the right checks in order to make the example obvious.

With such opDispatch, it is easy to get an autoevaluation for chained functions call via UFCS. () is only required on the last one.

I don't see how it can complicate the current situation. The current situation is like crazy complicated, and nobody is sure of what can be expected to be the correct behavior in many corner cases.