• Is my analysis of this simple issue correct?

    From Jon Rossen@21:1/5 to All on Tue Feb 2 18:46:12 2016
    As a relative beginner in all of this, I'd really appreciate it if
    someone could give me some feedback as to whether my analysis of the
    issue I ran into is correct.

    The explanation for this seems really simple, and I think I know what it
    is but I'm not 100% sure. I'm seeing for a simple expression, I get an
    error when I use bracket/message syntax but using dot.notation is fine.

    I have a simple method, and it's using the parent class's getter to
    tweak an ivar. Here's the line in question:

    I can do this with no error: self.x = self.x * m;
    of this with no error: self.x = [self x] * m;

    But I can't do this: [self x] = self.x * m;
    or this: [self x] = [self x] * m;

    The error I get here: "Assigning to 'readonly' return result of an Objective-C message not allowed"

    The error makes sense and when thinking about I thought to myself
    DOH!!!! (a few times).

    The reason why dot notation works on the result is that the dot notation
    syntax can sort of 'morph' between setter and getter by use of the '='
    to assign a value..voila you have the setter. That's essentially what
    the examples with 'self.x = blah blah blah' is doing, and it's valid.

    For [self x], the message syntax is one of a getter and thus is
    readonly. So, therefore in order to use message syntax you have to
    follow through with it properly and use the setter: Put the code on the
    right of the '=' as the argument to the setter method: In other words:
    [self setX:self.x * m];

    Is my assessment of this pretty much correct?

    thanks,
    jonR

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Pascal J. Bourguignon@21:1/5 to Jon Rossen on Wed Feb 3 21:01:54 2016
    Jon Rossen <jonr17@comcast.net> writes:

    As a relative beginner in all of this, I'd really appreciate it if
    someone could give me some feedback as to whether my analysis of the
    issue I ran into is correct.

    The explanation for this seems really simple, and I think I know what
    it is but I'm not 100% sure. I'm seeing for a simple expression, I get
    an error when I use bracket/message syntax but using dot.notation is
    fine.

    I have a simple method, and it's using the parent class's getter to
    tweak an ivar. Here's the line in question:

    I can do this with no error: self.x = self.x * m;
    of this with no error: self.x = [self x] * m;

    But I can't do this: [self x] = self.x * m;
    or this: [self x] = [self x] * m;

    The error I get here: "Assigning to 'readonly' return result of an Objective-C message not allowed"

    The error makes sense and when thinking about I thought to myself
    DOH!!!! (a few times).

    The reason why dot notation works on the result is that the dot
    notation syntax can sort of 'morph' between setter and getter by use
    of the '=' to assign a value..voila you have the setter. That's
    essentially what the examples with 'self.x = blah blah blah' is doing,
    and it's valid.

    For [self x], the message syntax is one of a getter and thus is
    readonly. So, therefore in order to use message syntax you have to
    follow through with it properly and use the setter: Put the code on
    the right of the '=' as the argument to the setter method: In other
    words:
    [self setX:self.x * m];

    Is my assessment of this pretty much correct?

    Yes.

    --
    __Pascal Bourguignon__ http://www.informatimago.com/
    “The factory of the future will have only two employees, a man and a
    dog. The man will be there to feed the dog. The dog will be there to
    keep the man from touching the equipment.” -- Carl Bass CEO Autodesk

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From spikeysnack@21:1/5 to All on Thu Feb 4 01:43:46 2016
    It is much more low level than that.
    It is a fundamental of the computer memory model and syntax of assignment.

    The result of a function is always a read only value, because in ObjC, as in C,
    methods (functions) can return only one thing: a value.

    There is the fundamental concept of left values and right values.

    A value is a known type or the address of a known type.

    Left values are variables and have a certain memory address that can contain a value.
    Right Values are typed values like int or char or a pointer.

    An assignment is always of the form lvalue = rvalue. (left val ) = (right val) NEVER the other way.

    An lvalue has a storage address that can contain a value, an rvalue may not.
    If the value on the right is a variable it is de-referenced into a value.

    x = 10; x has a storage address and accessible memory location, 10 is just a value.

    10 = 12; makes no sense. It is a compiler error because both are rvalues.

    x = x +1; OK because x the lvalue can be assigned and the x the rvalue on the right is de-referenced into the value in x.

    x can not be changed on the right as an rvalue, only on the left as an lvalue. C does the right thing here and evaluates the right side fully before the assignment, overwriting the value in x.

    The value of an assignmentis returned as the value assigned,
    so (x = 0) returns 0. (x = 5) returns 5.

    x = y = z = 0; // you see this for setting up variables sometimes.
    How does the compiler figure out what is an rvalue and what is an lvalue here?

    The compiler recurses down the chain of assignments until it gets an rvalue and returns the value of each assignment as an rvalue in reverse.
    Your "mind compiler" should do the same thing as you read the line.
    " x = y, y = z , z = 0 . So z is the value 0, then y is the value of z , then x is the value of y."


    [self x] = x * m; is attempting to assign the rvalue returned by the accessor method and fails as a syntax error.
    The compiler should have been a bit more verbose and specific about that actually.

    So the right way is to set x directly inside the class if you know you are assigning a good value.
    But never directly set values inside a class from outside the class; always use an accessor function.
    Inside the class code the self clause is not necessary, x will do.
    The convention in Objective-C has been to name simple methods of setting/getting after the variable,
    and that carries on in objc 2.0 with properties as well,but it is not mandatory,
    just easy to work with in usual circumstances as a mnemonic device for what variable the method gets/sets.

    pointers follow the same rules as primitives when it comes to assignment: lvalue = rvalue.

    id myobj; // an object pointer is created with space for an address, but not assigned a value.
    (it may contain garbage or NULL -- who knows.)

    myobj = [ [SomeObject alloc] initWith: "a string"];
    is a common assignment syntax in ObjC.

    But it hides a lot of compiler evaluations behind its elegant form.

    First, the id type is a pointer to the address of an object. (usually a void*). So it needs an id rvalue for the assignment to be valid.
    The class SomeObject runs its alloc method, instantiating an instance of the class, and returns self (id) (rvalue).
    Then the instance class runs its initWith:(STR) method to initialize and then returns self (id) (rvalue).
    Then the myobj (lvalue) is assigned the address of the instance class (rvalue). Everything checks out typewise at every step, and every lvalue meets an rvalue.

    -(void) do_something:(STR) what;

    void methods of a class return nothing. Therefore they cannot be rvalues. (can not be on right hand side of = ).
    The runtime of ObjC often carefully ignores method returns (rvalues) if you don't assign them to a variable because
    often it is optional to take the return value of a method if it is an int or a boolean.
    methods like print that return the number of characters printed or methods that return self pointers to already assigned
    variables like [obj init] usually just throw away the rvalue returned. Theoretically you should never ignore return values
    of methods but practically if you don't need it just let it evaporate into the ether as the program goes on to the next line.
    Sorry for the wade in the deep end of the pool but that's where the gold is.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)