Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.objective-c > #252 > unrolled thread

Is my analysis of this simple issue correct?

Started byJon Rossen <jonr17@comcast.net>
First post2016-02-02 18:46 -0800
Last post2016-02-04 01:43 -0800
Articles 3 — 3 participants

Back to article view | Back to comp.lang.objective-c


Contents

  Is my analysis of this simple issue correct? Jon Rossen <jonr17@comcast.net> - 2016-02-02 18:46 -0800
    Re: Is my analysis of this simple issue correct? "Pascal J. Bourguignon" <pjb@informatimago.com> - 2016-02-03 21:01 +0100
    Re: Is my analysis of this simple issue correct? spikeysnack <spikeysnack@gmail.com> - 2016-02-04 01:43 -0800

#252 — Is my analysis of this simple issue correct?

FromJon Rossen <jonr17@comcast.net>
Date2016-02-02 18:46 -0800
SubjectIs my analysis of this simple issue correct?
Message-ID<n8rplo$c3t$1@news.albasani.net>
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

[toc] | [next] | [standalone]


#253

From"Pascal J. Bourguignon" <pjb@informatimago.com>
Date2016-02-03 21:01 +0100
Message-ID<87wpqlh8b1.fsf@kuiper.lan.informatimago.com>
In reply to#252
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

[toc] | [prev] | [next] | [standalone]


#254

Fromspikeysnack <spikeysnack@gmail.com>
Date2016-02-04 01:43 -0800
Message-ID<d797119c-28eb-4fd7-a021-cfdc6db6994e@googlegroups.com>
In reply to#252
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.

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.objective-c


csiph-web