Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Weird behaviour with setters calling associated getter #1002

Open
marcusnaslund opened this issue Jun 27, 2016 · 7 comments
Open

Weird behaviour with setters calling associated getter #1002

marcusnaslund opened this issue Jun 27, 2016 · 7 comments

Comments

@marcusnaslund
Copy link
Contributor

marcusnaslund commented Jun 27, 2016

Example 1 (associated getter):

Test: class {
    value: Int {
        get { return 2 }
        set (x) { 
            if (this value == 2)
                "two" println()
            else
                "not two, but: %i" printfln(this value)
         }
    }
    init: func
}

x := Test new()
x value = 10

should print "two" but prints "not two, but: 0".

Example 2 (setter calling itself):

Same here. But:

Test: class {
    value: Int {
        get { return 2 }
        set (x) {
            "old value=%i" printfln(this value)
            this value = x
        }
    }
    init: func
}

x := Test new()
x value = 2
x value = 3
x value = 4

should always print "old value=2" but prints

old value=0
old value=2
old value=3
@marcusnaslund marcusnaslund changed the title Weird behaviour with setters calling associated getter or themselves Weird behaviour with setters calling associated getter Jun 27, 2016
@horasal
Copy link
Contributor

horasal commented Jun 28, 2016

It seems that this value in getter is not unwrapped to the getter call.

void test2__Test___setvalue___impl(test2__Test* this, lang_Numbers__Int x) {
    if (this->value == 2) {
        lang_String__String_println(__test2_strLit2);
    }

From source/rock

                // We are in a setter/getter and we're having a variable access. That means
                // the property is not virtual.
                ref as PropertyDecl setVirtual(false)

@alexnask
Copy link
Collaborator

Yes, I'm pretty sure this is expected behavior (accessing the property inside the property decl returns the actual backing variable).

@marcusnaslund
Copy link
Contributor Author

this is expected behavior

But, why? I see no logic in reading the "backing variable" in the setter when, as I have written the code, I would not expect any variable called value at all. I would expect value to always give me 2.

Also, I would expect this code to give the same result as example 1, but it does not:

Test: class {
    value: Int {
        get { return 2 }
        set (x) {
            if (this getTheGetter() == 2)
                "two" println()
            else
                "not two, but: %i" printfln(this value)
         }
    }
    init: func
    getTheGetter: func -> Int {
        this value
    }
}

x := Test new()
x value = 10

That code, in fact, gives me "two".

Is there some logic to this that I'm missing? :)

@alexnask
Copy link
Collaborator

alexnask commented Jun 28, 2016

This code results in fetching two because of the indirection.

I do think setters could use the getter function when just accessing the property instead of the backing variable, as you've brought out valid points.

I'm trying to think of some weird edgecases that would break but I don't think there are any.
By the way, are you aware of how C# does that?
I'm not quite sure myself as I've never used it but am aware it provides almost the exact same feature.

EDIT: Btw, "expected behavior" was referring to the way rock currently handles this case, not the most intuitive way it could be done.

@marcusnaslund
Copy link
Contributor Author

are you aware of how C# does that?

The following code

public class Test
{
    public int X
    {
        get { return 2; }
        set
        {
            System.Console.WriteLine("old value={0}", this.X);
        }
    }
}

public class Hello
{
    public static void Main()
    {
        Test test = new Test();
        test.X = 3;
        System.Console.WriteLine("X={0}", test.X);
    }
}

prints

old value=2
X=2

as expected. (In C# I cannot assign this.X = value; in the setter, because this causes an infinite loop.)

@vendethiel
Copy link

I'd argue it's a bit different still, because backing properties are explicit in (non-bleeding-edge versions of) c#.

@alexnask
Copy link
Collaborator

Ah, I though non-virtual/backing properties were automatically inferred in C# as well, guess I was wrong :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants