View mode: basic / threaded / horizontal-split · Log in · Help
January 28, 2013
Re: @property needed or not needed?
On Monday, 28 January 2013 at 16:55:40 UTC, Dicebot wrote:
> On Monday, 28 January 2013 at 16:50:37 UTC, Maxim Fomin wrote:
>> Than value of this expression (note, that evaluated expression 
>> is not b, it is b = c) is assigned to a.
>
> Quoting you (that was exactly part of standard I was referring 
> too):
> "assignment expression has the value of the left operand"
>
> Left operand for (b = c) is b. Thus (b = c) has value of b. 
> Value of b is b.getter(). Thus compiler is re-writing it wrong 
> if we copy C rules.

You are mixing value of expression and expression itself. If 
assignment expression has value of right operand, it does not 
mean that in complex assignment like a = b = c , right part of 
second assignment disappears and it becomes a = b. It is still a 
= b = c , and a is assigned to value of the whole expression b = 
c, not just value of b. This means it is a.setter((b = c)) = > 
a.setter(b.setter(c.getter)). Note, that original program does 
exactly what is required by ISO C.

>> b.setter cannot be called prior to b.getter as in your example 
>> #1 due to sequence rules. The example #2 would be for 
>> expression a = c, b = c which is not a = b = c in the presence 
>> of properties.
>
> What sequence rules are you speaking about?

About that side effects are sequenced after evaluation, but it is 
actually irrelevant, because b.getter is not called.
January 28, 2013
Re: @property needed or not needed?
On Monday, 28 January 2013 at 16:55:40 UTC, Dicebot wrote:
> On Monday, 28 January 2013 at 16:50:37 UTC, Maxim Fomin wrote:
>> Than value of this expression (note, that evaluated expression 
>> is not b, it is b = c) is assigned to a.
>
> Quoting you (that was exactly part of standard I was referring 
> too):
> "assignment expression has the value of the left operand"
>
> Left operand for (b = c) is b. Thus (b = c) has value of b. 
> Value of b is b.getter(). Thus compiler is re-writing it wrong 
> if we copy C rules.
>

Applying your logic:

Left operand for a = (b = c) is a. Thus a has value of (b = c). 
Value of b = c is b.setter(c.getter()).
January 28, 2013
Re: @property needed or not needed?
On Monday, 28 January 2013 at 17:20:13 UTC, Maxim Fomin wrote:
> ...

Those are C rules, do not forget it. Thus value of (b = c) IS 
equivalent to value of b when lvalues are considered. And you are 
perfectly allowed to forget about c and do a = b after b = c was 
evaluated. It is plain old data, after all, if b = c is not 
interchangeable with b, something is wrong.

At least I see nothing in standard that proves your statement.

>
> Applying your logic:
>
> Left operand for a = (b = c) is a. Thus a has value of (b = c). 
> Value of b = c is b.setter(c.getter()).

You are applying it wrong. Thing of it as of recursion.
1) evaluate "a = b = c"
2) evaluate a.set( (b = c).get() ), result of 1 will be a.get() ( 
if needed )
3) evaluate "b = c"
4) evaluate b.set( c.get() ), result of 3 will be b.get() ( if 
needed )
5) combine: a.set( b.set( c.get() ), b.get() )

Note that evaluation order for comma expression is defined, so 
"c.get() ), b.get()" is valid and correct code.
January 28, 2013
Re: @property needed or not needed?
On Monday, 28 January 2013 at 03:24:09 UTC, Steven Schveighoffer 
wrote:
> There are three intentions when creating a function w/ regards 
> to properties:
>
> 1. You intend the function to be called without parentheses to 
> clarify it is a property.
> 2. You intend the function to be only called with parentheses 
> to clarify it is a function.
> 3. You don't care whether it's called with parentheses or not, 
> because the name of the function is clearly a property or a 
> function.

This is a good point. Possibly since I'm the author of the 
following proposal, but also because I hope it will garner 
greater consideration than it has so far, this is how you would 
do these with my suggested language features single-instance 
structs and opGet:

The new syntax changes:

struct __foo {}
__foo foo;

to:

foo struct {}

This makes single-instance structs as easy to write as lambda 
functions. Combining them with two new operator definitions opGet 
and... let me see... opDo should cover it... it would look like 
this:

struct Goo
{
  int _n;
  foo struct
  {
    int opGet() { return _n; } // Exactly like opCall, but may 
not be used with parentheses
  }
}

Goo g;
g.foo(); // Error

A struct may have exactly one of opGet, opCall, and opDo.

foo struct
{
  int opGet() { ... }
  int opDo() { ... } // Error: a struct may not have both opGet 
and opDo
}

opDo does exactly the opposite of opGet: it mandates the uses of 
parentheses instead of prohibits them. opCall, on the other hand, 
permits either one freely.

foo struct { int opDo() { return 4; } }
foo; // Error: foo must be called with parentheses

Note how the single-instance struct does not store data of its 
own, but is used for its value as a namespace and its ability to 
overload variables. That doesn't mean you *can't* store data in 
it. It's just like any other struct except that is has what I was 
thinking of calling a Highlander type: There can be only one!
January 28, 2013
Re: @property needed or not needed?
On Monday, January 28, 2013 13:31:34 Jacob Carlborg wrote:
> > Having the compiler lower the following:
> > 
> > @property int a;
> > 
> > to
> > 
> > private int __a;
> > 
> > @property int a() {
> > return __a;
> > }
> > @property int a(int new_a) {
> > 
> > __a=new_a;
> > return __a;
> > 
> > }
> 
> I would love that. But the setter should return void and the compiler
> should to property rewrites.

Both should work. It's more efficient to chain assignments if the setter returns 
a value, but chaining should still work if it returns void. It would just be 
lowered differently in that case.

- Jonathan M Davis
January 28, 2013
Re: @property needed or not needed?
On Monday, 28 January 2013 at 17:41:07 UTC, Dicebot wrote:
> On Monday, 28 January 2013 at 17:20:13 UTC, Maxim Fomin wrote:
>> ...
>
> Those are C rules, do not forget it. Thus value of (b = c) IS 
> equivalent to value of b when lvalues are considered. And you 
> are perfectly allowed to forget about c and do a = b after b = 
> c was evaluated. It is plain old data, after all, if b = c is 
> not interchangeable with b, something is wrong.
>
> At least I see nothing in standard that proves your statement.
>

You are still breaking expression a = b = c and mixing terms of 
value of expression and expression itself.

>>
>> Applying your logic:
>>
>> Left operand for a = (b = c) is a. Thus a has value of (b = 
>> c). Value of b = c is b.setter(c.getter()).
>
> You are applying it wrong. Thing of it as of recursion.

I applied exactly as you did.

> 1) evaluate "a = b = c"
> 2) evaluate a.set( (b = c).get() ), result of 1 will be a.get() 
> ( if needed )

.get() is wrong here. Expression is a = b = c, not a = ( (b = 
c).get ))

> 3) evaluate "b = c"
> 4) evaluate b.set( c.get() ), result of 3 will be b.get() ( if 
> needed )
> 5) combine: a.set( b.set( c.get() ), b.get() )

This breaks requirement from quoted paragraph that side effects 
are sequenced after value computations on both operands: 
computing value of b (b.get) happened after updating value 
(b.set).

In Bugzilla there were close to this case like following (do not 
remember #):

struct S { int a; int b; int c; }
...
S s1, s2;

s1 = { 1, s1.a 2 }

Compiler was wrongly applied side effects before evaluating s1.a 
(it should be zero, not 1).

> Note that evaluation order for comma expression is defined, so 
> "c.get() ), b.get()" is valid and correct code.

Well, discussion went repetitive - I still insists that a = b = c 
should be evaluated as it is currently a.set(b=c) = > 
a.set(b.set(c)) => a.set(b.set(c.get)). By the way, this C# 
program also behaves as I understand rules:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

class S
{
    int _i;
    public int i
    {
        get { Console.WriteLine("getter"); return _i; }
        set { Console.WriteLine("setter"); _i = value; }
    }
}

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            S s1 = new S() , s2 = new S(), s3 = new S();
            s1.i = s2.i = s3.i;
        }
    }
}

getter
setter
setter
January 28, 2013
Re: @property needed or not needed?
On 2013-01-28 15:00, Maxim Fomin wrote:

> Returning void instead of int in the example break assignment chaining a
> = b = c. Besides, how such implicitly defined functions may call user
> defined code (check input validity, call events, etc.)?

No, the compiler should do a rewrite, as follows:

class Foo
{
    int bar_;

    @property int bar () { return bar_; }
    @property void bar (int value) { bar_ = value; }
}

auto foo = new Foo;
int a = foo.bar = 3;

The above line should be rewritten as:

foo.bar = 3;
int a = foo.bar;

The compiler also need to rewrite the following:

struct Bar
{
    int a;
}

class Foo
{
    Bar bar_;

    @property Bar bar () { return bar_; }
    @property void bar (Bar value) { bar_ = value; }
}

auto foo = new Foo;
foo.bar.a = 3;

The above line should be rewritten to:

auto __tmp = foo.bar;
__tmp.a = 3;
foo.bar = __tmp;

If not, the value of "foo.bar.a" hasn't really changed since you 
returned a copy by value. If you instead return by reference you can 
bypass the setter using the getter.

-- 
/Jacob Carlborg
January 28, 2013
Re: @property needed or not needed?
On 2013-01-28 17:21, Steven Schveighoffer wrote:

> I think Jacob's point is that a = b = c would lower to:
>
> b = c;
> a = b;

This is how the semantics should be. This also shows a clear complete 
example:

http://forum.dlang.org/thread/uxhgbxdsselokcdkvltx@forum.dlang.org?page=14#post-ke6l44:242mfh:241:40digitalmars.com

> But I think it would be wasteful in the given case.  __a is already in
> the register, I think actually the return __a is a noop.
>
> In other cases, where the property value may be a large struct or
> whatnot, not returning the new value from a setter would make sense.
>
> It would be nice if the compiler made the right choice depending on
> whether you returned a value from the property or not.

Then it's up to the compiler to implement them, I don't need to know the 
details in the optimizations it can do.

-- 
/Jacob Carlborg
January 29, 2013
Re: @property needed or not needed?
On Mon, 28 Jan 2013 15:00:41 -0500, Jacob Carlborg <doob@me.com> wrote:

> On 2013-01-28 17:21, Steven Schveighoffer wrote:

>> But I think it would be wasteful in the given case.  __a is already in
>> the register, I think actually the return __a is a noop.
>>
>> In other cases, where the property value may be a large struct or
>> whatnot, not returning the new value from a setter would make sense.
>>
>> It would be nice if the compiler made the right choice depending on
>> whether you returned a value from the property or not.
>
> Then it's up to the compiler to implement them, I don't need to know the  
> details in the optimizations it can do.

Like I said, the synthesizing of properties can be done via a library.
The compiler simply needs to call the getter when the setter returns void,
or return the setter's return value when it returns a value.

-Steve
January 29, 2013
Re: @property needed or not needed?
On Mon, 28 Jan 2013 15:00:41 -0500, Jacob Carlborg <doob@me.com> wrote:

> On 2013-01-28 17:21, Steven Schveighoffer wrote:

>> But I think it would be wasteful in the given case.  __a is already in
>> the register, I think actually the return __a is a noop.
>>
>> In other cases, where the property value may be a large struct or
>> whatnot, not returning the new value from a setter would make sense.
>>
>> It would be nice if the compiler made the right choice depending on
>> whether you returned a value from the property or not.
>
> Then it's up to the compiler to implement them, I don't need to know the  
> details in the optimizations it can do.

Like I said, the synthesizing of properties can be done via a library.
The compiler simply needs to call the getter when the setter returns void,
or return the setter's return value when it returns a value.

-Steve
10 11 12 13 14 15
Top | Discussion index | About this forum | D home