Why can't I change the value of self on Int32
Beta Ziliani's answer is good and looks at the bigger picture.
For this particular example, the answer is actually very simple: primitive types in Crystal are immutable.
So it's impossible to change the value of a primitive type's instance. Mutating methods always have to return a new value. That value can then be assigned to the same variable again.
A workaround would be to wrap the primitive in a struct. Or as an unsafe alternative, you can pass a pointer to a variable with a primitive value to a method. Then the method can assign a value to that pointer.
Can't change the value of self
In Ruby, self
gives you access to the current object and cannot be set. In this case, self
refers to the current instance of the User
model. It looks like you just want to set the password_reset_token column, so:
def generate_token(column_name)
write_attribute column_name, SecureRandom.urlsafe_base64
end
Why can't I overwrite self in the Integer class?
You cannot change the value of self
An object is a class pointer and a set of instance methods (note that this link is an old version of Ruby, because its dramatically simpler, and thus better for explanatory purposes).
"Pointing" at an object means you have a variable which stores the object's location in memory. Then to do anything with the object, you first go to the location in memory (we might say "follow the pointer") to get the object, and then do the thing (e.g. invoke a method, set an ivar).
All Ruby code everywhere is executing in the context of some object. This is where your instance variables get saved, it's where Ruby looks for methods that don't have a receiver (e.g. $stdout
is the receiver in $stdout.puts "hi"
, and the current object is the receiver in puts "hi"
). Sometimes you need to do something with the current object. The way to work with objects is through variables, but what variable points at the current object? There isn't one. To fill this need, the keyword self
is provided.
self
acts like a variable in that it points at the location of the current object. But it is not like a variable, because you can't assign it new value. If you could, the code after that point would suddenly be operating on a different object, which is confusing and has no benefits over just using a variable.
Also remember that the object is tracked by variables which store memory addresses. What is self = 2
supposed to mean? Does it only mean that the current code operates as if it were invoked 2
? Or does it mean that all variables pointing at the old object now have their values updated to point at the new one? It isn't really clear, but the former unnecessarily introduces an identity crisis, and the latter is prohibitively expensive and introduce situations where it's unclear what is correct (I'll go into that a bit more below).
You cannot mutate Fixnums
Some objects are special at the C level in Ruby (false, true, nil, fixnums, and symbols).
Variables pointing at them don't actually store a memory location. Instead, the address itself stores the type and identity of the object. Wherever it matters, Ruby checks to see if it's a special object (e.g. when looking up an instance variable), and then extracts the value from it.
So there isn't a spot in memory where the object 123
is stored. Which means self
contains the idea of Fixnum 123
rather than a memory address like usual. As with variables, it will get checked for and handled specially when necessary.
Because of this, you cannot mutate the object itself (though it appears they keep a special global variable to allow you to set instance variables on things like Symbols).
Why are they doing all of this? To improve performance, I assume. A number stored in a register is just a series of bits (typically 32 or 64), which means there are hardware instructions for things like addition and multiplication. That is to say the ALU, is wired to perform these operations in a single clock cycle, rather than writing the algorithms with software, which would take many orders of magnitude longer. By storing them like this, they avoid the cost of storing and looking the object in memory, and they gain the advantage that they can directly add the two pointers using hardware. Note, however, that there are still some additional costs in Ruby, that you don't have in C (e.g. checking for overflow and converting result to Bignum).
Bang methods
You can put a bang at the end of any method. It doesn't require the object to change, it's just that people usually try to warn you when you're doing something that could have unexpected side-effects.
class C
def initialize(val)
@val = val # => 12
end # => :initialize
def bang_method!
"My val is: #{@val}" # => "My val is: 12"
end # => :bang_method!
end # => :bang_method!
c = C.new 12 # => #<C:0x007fdac48a7428 @val=12>
c.bang_method! # => "My val is: 12"
c # => #<C:0x007fdac48a7428 @val=12>
Also, there are no bang methods on integers, It wouldn't fit with the paradigm
Fixnum.instance_methods.grep(/!$/) # => [:!]
# Okay, there's one, but it's actually a boolean negation
1.! # => false
# And it's not a Fixnum method, it's an inherited boolean operator
1.method(:!).owner # => BasicObject
# In really, you call it this way, the interpreter translates it
!1 # => false
Alternatives
- Make a wrapper object: I'm not going to advocate this one, but it's the closest to what you're trying to do. Basically create your own class, which is mutable, and then make it look like an integer. There's a great blog post walking through this at http://blog.rubybestpractices.com/posts/rklemme/019-Complete_Numeric_Class.html it will get you 95% of the way there
- Don't depend directly on the value of a Fixnum: I can't give better advice than this without knowing what you're trying to do / why you feel this is a need.
Also, you should show your code when you ask questions like this. I misunderstood how you were approaching it for a long time.
Why can't I change the values of a list in the class using a method?
Try this
def union(self,p, q):
pid = self.id[p]
qid = self.id[q]
for i in range(len(self.id)):
if self.id[i] == pid: # This part is getting ignored, I think.
self.id[i] = qid
Can't modify self in ruby for integer
That's by design. It's not specific to integers, all classes behave like that. For some classes (String
, for example) you can change state of an instance (this is called destructive operation), but you can't completely replace the object. For integers you can't change even state, they don't have any.
If we were willing to allow such thing, it would raise a ton of hard questions. Say, what if foo
references bar1
, which we're replacing with bar2
. Should foo
keep pointing to bar1
? Why? Why it should not? What if bar2
has completely different type, how users of bar1
should react to this? And so on.
class Foo
def try_mutate_into another
self = another
end
end
f1 = Foo.new
f2 = Foo.new
f1.try_mutate_into f2
# ~> -:3: Can't change the value of self
# ~> self = another
# ~> ^
I challenge you to find a language where this operation is possible. :)
Self variable changes when the variable it's assigned to changes
Use either:
#1
unsortedList = self.list.copy()
Or
#2
unsortedList = self.list[:]
Or
#3
import copy
unsortedList = copy.deepcopy(self.list)
Explanation:
When you do an assignment via =
, it really is referring to the same list just that now that list has 2 different names.
To circumvent this, use #1 or #2 methods -> you would require the .copy()
inbuilt function or using [:]
.
As for #3, this is used when shallow copying isn't enough because you might have mutable objects within the list itself.
For a greater understanding on copy vs deepcopy, visit and read here
Is it safe to replace a self object by another object of the same type in a method?
It is unlikely that replacing the 'self' variable will accomplish whatever you're trying to do, that couldn't just be accomplished by storing the result of func(self) in a different variable. 'self' is effectively a local variable only defined for the duration of the method call, used to pass in the instance of the class which is being operated upon. Replacing self will not actually replace references to the original instance of the class held by other objects, nor will it create a lasting reference to the new instance which was assigned to it.
Related Topics
Does 'Upcase!' Not Mutate a Variable in Ruby
How to Add Iedriverserver to Path
Actionmailer Smtp "Certificate Verify Failed"
Rails: Merit Gem Badge Not Registering or Displaying
Ruby Daemon Process to Keep Objects Alive for Transient Ruby Instances
Has_Many and No Method Error Issue
Initialize the Delayed Jobs Gem by Starting the Workers on Application Start
How to Send Custom Invitation Using Devise_Invitable
Display Result Data Without Page Refresh on Form Submission in Ruby on Rails
How to Access HTML Elements That Are Rendered in JavaScript Using Xpath
Rails Object Based Permission/Authorization Engine
How to Print All the Staged File Names Using Ruby Git Pre-Commit Hook
Iterate JSON with Ruby and Get a Key,Value in an Array
How to Access Text Field in an Iframe
Should Repeat a Number of Times
Rails 3.2 Create a Form That's Used in the Footer of Every Page