Why can't I change the value of self?
Asked Answered
S

2

6

How come I'm allowed to change "self" this way:

self.map! {|x| x*2}

Or this way:

self.replace(self.map {|x| x*2})

But not this way:

self = self.map {|x| x*2}

Why doesn't Ruby allow me to change the object that the "self" variable points to, but does allow me to change the object's attributes?

Schiff answered 14/9, 2014 at 14:42 Comment(2)
My guess would be because the first two options only replace values/attributes, while the third options could actually replace the object itself (which you do not want)Surfactant
It's not hard, it's impossible.Boony
P
4

Not an answer, just a clue.

a=[1,2]
=>[1,2]
a.object_id
=>2938

a.map!{|x| x*2}
=>[2,4]
a.object_id  # different data but still the same object
=>2938

a.replace(a.map {|x| x*2})
=>[4,8]
a.object_id  # different data but still the same object
=>2938

a = a.map{|x| x*2} # .map will create a new object assign to a 
=>[8,16]
a.object_id  #different object
=>2940   

You can't change your self to another one.

Pavlodar answered 14/9, 2014 at 15:12 Comment(1)
Thank you, this is great. Helped me clarify my question!Schiff
B
2

In Ruby, values and variables are references (pointers to objects). Assigning to a variable simply makes it point to a different object; it has no effect on the object the variable used to point to. To change an object, you must call a method (including property getters/setters) on it.

You can think of self as a variable that points to the object the method was called on. If you could assign to it, you could make it point to another object. If you could do that, it would not alter the object the method was called on; instead, you would make it so that any following code in that method that uses self would use that object, not the object the method was called on. This would be super confusing, because self would no longer point to the object the method was called on, which is a basic assumption.

Bravery answered 15/9, 2014 at 8:12 Comment(8)
Thanks for your response! Your answer seems to be that Ruby doesn't allow it because it would be confusing/bad practice. But Ruby allows plenty of things that are confusing/bad practice. So why not allow this one, while allowing the others? Moreover, every language that I know of disallows this. So the issue seems like it's bigger than one of mere bad practice/confusion.Schiff
@user3680688: It's not just Ruby. Pretty much all object-oriented languages do not allow you to assign to the variable this/self. Also, 99% of the time people think they want to assign to self, it's because they somehow mistakenly believe that this will change the object that the method is called on. But that's not what assigning to a variable does in Ruby. It simply makes the variable point to a different object.Bravery
"Moreover, every language that I know of disallows this". I realize it's not just Ruby. I appreciate your taking the time to respond, but you aren't answering my question. I'll grant that it's bad practice to want to change the value of self. But why do all of these languages make this bad practice impossible? Why this one? When so many other bad practices are allowed. It seems that something is missing from your explanation.Schiff
@user3680688: 1) Because it's likely to be misunderstood by most people who come across it, and you will see tons of questions on sites like these asking why they assigned to self and it doesn't change the object. 2) Because self is not meant to be a general-purpose variable; it's just an implicit variable that has a very well-defined meaning (it points to the object the method was called on) which you would break if you can assign to it.Bravery
@user3680688: 3) If you could make self point to a different object, and you access an instance variable or instance method (without calling it on an object explicitly), I don't even know if that would use the object the method was called on or the new self; if it used the new self, that would break the rule that instance variables cannot be accessed from another object.Bravery
@user3680688: 4) Because if you really wanted a variable that started out as the object the method was called on and you can assign to, there's an easy workaround: just create a local variable (call it self2), do self2 = self at the very beginning of the method, and then where you would use self you would use self2 later on; and you can assign to self2 as you like.Bravery
So let me see if I understand: it's disallowed because it's bad practice. Ok good. Now answer: why banish this bad practice universally from every language when other bad practices are allowed? You're providing evidence for something I agree with.Schiff
@user3680688: I did not say it was bad practice. Please stop repeating the same thing over and over again.Bravery

© 2022 - 2024 — McMap. All rights reserved.