How to unfreeze an object in Ruby? - ruby

In Ruby, there is Object#freeze, which prevents further modifications to the object:
class Kingdom
attr_accessor :weather_conditions
end
arendelle = Kingdom.new
arendelle.frozen? # => false
arendelle.weather_conditions = 'in deep, deep, deep, deep snow'
arendelle.freeze
arendelle.frozen? # => true
arendelle.weather_conditions = 'sun is shining'
# !> RuntimeError: can't modify frozen Kingdom
script = 'Do you want to build a snowman?'.freeze
script[/snowman/] = 'castle of ice'
# !> RuntimeError: can't modify frozen String
However, there is no Object#unfreeze. Is there a way to unfreeze a frozen kingdom?

Update: As of Ruby 2.7 this no longer works!
Yes and no. There isn't any direct way using the standard API. However, with some understanding of what #freeze? does, you can work around it. Note: everything here is implementation details of MRI's current version and might be subject to change.
Objects in CRuby are stored in a struct RVALUE.
Conveniently, the very first thing in the struct is VALUE flags;.
All Object#freeze does is set a flag, called FL_FREEZE, which is actually equal to RUBY_FL_FREEZE. RUBY_FL_FREEZE will basically be the 11th bit in the flags.
All you have to do to unfreeze the object is unset the 11th bit.
To do that, you could use Fiddle, which is part of the standard library and lets you tinker with the language on C level:
require 'fiddle'
class Object
def unfreeze
Fiddle::Pointer.new(object_id * 2)[1] &= ~(1 << 3)
end
end
Non-immediate value objects in Ruby are stored on address = their object_id * 2. Note that it's important to make the distinction so you would be aware that this wont let you unfreeze Fixnums for example.
Since we want to change the 11th bit, we have to work with the 3th bit of the second byte. Hence we access the second byte with [1].
~(1 << 3) shifts 1 three positions and then inverts the result. This way the only bit which is zero in the mask will be the third one and all other will be ones.
Finally, we just apply the mask with bitwise and (&=).
foo = 'A frozen string'.freeze
foo.frozen? # => true
foo.unfreeze
foo.frozen? # => false
foo[/ (?=frozen)/] = 'n un'
foo # => 'An unfrozen string'

No, according to the documentation for Object#freeze:
There is no way to unfreeze a frozen object.
The frozen state is stored within the object. Calling freeze sets the frozen state and thereby prevents further modification. This includes modifications to the object's frozen state.
Regarding your example, you could assign a new string instead:
script = 'Do you want to build a snowman?'
script.freeze
script = script.dup if script.frozen?
script[/snowman/] = 'castle of ice'
script #=> "Do you want to build a castle of ice?"
Ruby 2.3 introduced String#+#, so you can write +str instead of str.dup if str.frozen?

frozen_object = %w[hello world].freeze
frozen_object.concat(['and universe']) # FrozenError (can't modify frozen Array)
frozen_object.dup.concat(['and universe']) # ['hello', 'world', 'and universe']

As noted above copying the variable back into itself also effectively unfreezes the variable.
As noted this can be done using the .dup method:
var1 = var1.dup
This can also be achieved using:
var1 = Marshal.load(Marshal.dump(var1))
I have been using Marshal.load(Marshal.dump( ... )
I have not used .dup and only learned about it through this post.
I do not know what if any differences there are between Marshal.load(Marshal.dump( ... )
If they do the same thing or .dup is more powerful, then stylistically I like .dup better. .dup states what to do -- copy this thing, but it does not say how to do it, whereas Marshal.load(Marshal.dump( ... ) is not only excessively verbose, but states how to do the duplication -- I am not a fan of specifying the HOW part if the HOW part is irrelevant to me. I want to duplicate the value of the variable, I do not care how.

Related

Overwrite a variable without repeating the name

Is there a method to overwrite variable without copying its name? For example, when I want to change my_var = '3' to an integer, I must do something like this:
my_var = my_var.to_i
Is there way to do this without copying variable's name? I want to do something like this:
my_var = something_const.to_i
For numbers there exists +=, -= etc, but is there universal way to do this for all methods ?
There is no way to covert a string to an integer like that, without repeating the variable name. Methods such as String#upcase! and Array#flatten! work by mutating the object; however, it is not possible to define such a method like String#to_i! because we are converting the object to an instance of a different class.
For example, here is a (failed) attempt to define such a method:
# What I want to be able to do:
# my_var = "123"
# my_var.to_i! # => my_var == 123
class String
def to_i!
replace(Integer(self))
end
end
my_var = "123"
my_var.to_i! # TypeError: no implicit conversion of Fixnum into String
...And even if this code were valid, it would still offer no performance gain since a new object is still being created.
As for your examples of += and -=, these are in fact simply shorthand for:
x += 1
# Is equivalent to:
x = x + 1
So again, there is no performance gain here either; just slightly nicer syntax. A good question to ask is, why doesn't ruby support a ++ operator? If such an operator existed then it would offer performance gain... But I'll let you research for yourself why this is missing from the language.
So to summarise,
is there universal way to do this for all methods?
No. The special operators like +=, -=, |= and &= are all predefined; there is no "generalised" version such as method_name=.
You can also define methods that mutate the object, but only when appropriate. Such methods are usually named with a !, are called "bang-methods", and have a "non-bang" counterpart. On String objects, for example, there is String#capitalize! (and String#capitalize), String#delete! (and String#delete), String#encode! (and String#encode), .... but no String#to_i! for the reasons discussed above.

Multiplying string by integer vs integer by string in ruby

I was playing around in irb, and noticed one cannot do
5 * "Hello".
Error
String can't be coerced into Fixnum
However "Hello"*5 provided "HelloHelloHelloHelloHello" as expected.
What is the exact reason for this? I've been looking around in the doc's and could not find the exact reason for this behavior. Is this something the designers of ruby decided?
Basically, you are asking "why is multiplication not commutative"? There are two possible answers for this. Or rather one answer with two layers.
The basic principle of OO is that everything happens as the result of one object sending a message to another object and that object responding to that message. This "messaging" metaphor is very important, because it explains a lot of things in OO. For example, if you send someone a message, all you can observe is what their response is. You don't know, and have no idea of finding out, what they did to come up with that response. They could have just handed out a pre-recorded response (reference an instance variable). They could have worked hard to construct a response (execute a method). They could have handed the message off to someone else (delegation). Or, they just don't understand the message you are sending them (NoMethodError).
Note that this means that the receiver of the message is in total control. The receiver can respond in any way it wishes. This makes message sending inherently non-commutative. Sending message foo to a passing b as an argument is fundamentally different from sending message foo to b passing a as an argument. In one case, it is a and only a that decides how to respond to the message, in the other case it is b and only b.
Making this commutative requires explicit cooperation between a and b. They must agree on a common protocol and adhere to that protocol.
In Ruby, binary operators are simply message sends to the left operand. So, it is solely the left operand that decides what to do.
So, in
'Hello' * 5
the message * is sent to the receiver 'Hello' with the argument 5. In fact, you can alternately write it like this if you want, which makes this fact more obvious:
'Hello'.*(5)
'Hello' gets to decide how it responds to that message.
Whereas in
5 * 'Hello'
it is 5 which gets to decide.
So, the first layer of the answer is: Message sending in OO is inherently non-commutative, there is no expectation of commutativity anyway.
But, now the question becomes, why don't we design in some commutativity? For example, one possible way would be to interpret binary operators not as message sends to one of the operands but instead message sends to some third object. E.g., we could interpret
5 * 'Hello'
as
*(5, 'Hello')
and
'Hello' * 5
as
*('Hello', 5)
i.e. as message sends to self. Now, the receiver is the same in both cases and the receiver can arrange for itself to treat the two cases identically and thus make * commutative.
Another, similar possibility would be to use some sort of shared context object, e.g. make
5 * 'Hello'
equivalent to
Operators.*(5, 'Hello')
In fact, in mathematics, the meaning of a symbol is often dependent on context, e.g. in ℤ, 2 / 3 is undefined, in ℚ, it is 2/3, and in IEEE754, it is something close to, but not exactly identical to 0.333…. Or, in ℤ, 2 * 3 is 6, but in ℤ|5, 2 * 3 is 1.
So, it would certainly make sense to do this. Alas, it isn't done.
Another possibility would be to have the two operands cooperate using a standard protocol. In fact, for arithmetic operations on Numerics, there actually is such a protocol! If a receiver doesn't know what to do with an operand, it can ask that operand to coerce itself, the receiver, or both to something the receiver does know how to handle.
Basically, the protocol goes like this:
you call 5 * 'Hello'
5 doesn't know how to handle 'Hello', so it asks 'Hello' for a coercion. …
… 5 calls 'Hello'.coerce(5)
'Hello' responds with a pair of objects [a, b] (as an Array) such that a * b has the desired result
5 calls a * b
One common trick is to simply implement coerce to flip the operands, so that when 5 retries the operation, 'Hello' will be the receiver:
class String
def coerce(other)
[self, other]
end
end
5 * 'Hello'
#=> 'HelloHelloHelloHelloHello'
Okay, OO is inherently non-commutative, but we can make it commutative using cooperation, so why isn't it done? I must admit, I don't have a clear-cut answer to this question, but I can offer two educated guesses:
coerce is specifically intended for numeric coercion in arithmetic operations. (Note the protocol is defined in Numeric.) A string is not a number, nor is string concatenation an arithmetic operation.
We just don't expect * to be commutative with wildly different types such as Integer and String.
Of course, just for fun, we can actually observe that there is a certain symmetry between Integers and Strings. In fact, you can implement a common version of Integer#* for both String and Integer arguments, and you will see that the only difference is in what we choose as the "zero" element:
class Integer
def *(other)
zero = case other
when Integer then 0
when String then ''
when Array then []
end
times.inject(zero) {|acc, _| acc + other }
end
end
5 * 6
#=> 30
5 * 'six'
#=> 'sixsixsixsixsix'
5 * [:six]
#=> [:six, :six, :six, :six, :six, :six]
The reason for this is, of course, that the set of strings with the concatenation operation and the empty string as the identity element form a monoid, just like arrays with concatenation and the empty array and just like integers with addition and zero. Since all three are monoids, and our "multiplication as repeated addition" only requires monoid operations and laws, it will work for all monoids.
Note: Python has an interesting twist on this double-dispatch idea. Just like in Ruby, if you write
a * b
Python will re-write that into a message send:
a.__mul__(b)
However, if a can't handle the operation, instead of cooperating with b, it cooperates with Python by returning NotImplemented. Now, Python will try with b, but with a slight twist: it will call
b.__rmul__(a)
This allows b to know that it was on the right side of the operator. It doesn't matter much for multiplication (because multiplication is (usually but not always, see e.g. matrix multiplication) commutative), but remember that operator symbols are distinct from their operations. So, the same operator symbol can be used for operations that are commutative and ones that are non-commutative. Example: + is used in Ruby for addition (2 + 3 == 3 + 2) and also for concatenation ('Hello' + 'World' != 'World' + 'Hello'). So, it is actually advantageous for an object to know whether it was the right or left operand.
This is because that operators are also methods(Well there are exceptions as Cary has listed in the comments which I wasn't aware of).
For example
array << 4 == array.<<4
array[2] == array.[](2)
array[2] ='x' == array.[] =(2,'x')
In your example:
5 * "Hello" => 5.*("Hello")
Meanwhile
"hello" *5 => 5.*("hello")
An integer cannot take that method with a string param
If you ever dabble around in python try 5*hello and hello*5, both work. Pretty interesting that ruby has this feature to be honest.
Well, as Muntasir Alam has already told that Fixnum does not has a method named * which takes a string as argument. So, 5*"Hello" produces that error.But, to have fun we can actually achieve 5*"Hello" this by adding that missing method to the Fixnum class.
class Fixnum # open the class
def * str # Override the *() method
if str.is_a? String # If argument is String
temp = ""
self.times do
temp << str
end
temp
else # If the argument is not String
mul = 0
self.times do
mul += str
end
mul
end
end
end
now
puts 5*"Hello" #=> HelloHelloHelloHelloHello
puts 4*5 #=> 20
puts 5*10.4 #=> 52.0
Well, that was just to show that the opposite is also possible. But that will bring a lot of overhead. I think we should avoid that at all cost.

Odd Ruby Behaviour

Consider the following Ruby code:
a = ["x"] * 3 # or a = Array.new(3, "x")
a[0].insert(0, "a")
a.each {|i| puts i}
I would expect the output to be ax, x, x (on new lines of course). However, with Ruby 1.9.1 the output is ax, ax, ax. What's going on? I've narrowed the problem down to the way the array a is defined. If I explicitly write out
a = ["x", "x", "x"]
then the code works as expected, but either version in the original code gives me this unexpected behaviour. It appears that the */initializer means the copies are actually references to the same copy of the string "x". However, if instead of the insert command I write
a[0] = "a" + a[0]
Then I get the desired output. Is this a bug, or is there some feature at work which I'm not understanding?
The documentation to Array.new(size=0, obj=nil):
... it is created with size copies of obj (that is, size references to the same obj).
and Array * int:
... returns a new array built by concatenating the int copies of self
So in both of the forms you're surprised by, you end up with three references to the same "x" object, just as you figured out. I'd say you might argue about the design decision, but it's a documented intentional behavior, not a bug.
The best way I know to get the behavior you want without manually writing the array literal (["x", "x", "x"]) is
a = Array.new(3) {"x"}
Or course, with just three elements, it doesn't much matter, but with anything much bigger, this form comes in handy.
In short, although "x" is just a literal, it is an object. You use ["x'] * 3 so a is containing 3 same object. You insert 'a' to one of them, they will be all changed.

In Ruby, why does inspect() print out some kind of object id which is different from what object_id() gives?

When the p function is used to print out an object, it may give an ID, and it is different from what object_id() gives. What is the reason for the different numbers?
Update: 0x4684abc is different from 36971870, which is 0x234255E
>> a = Point.new
=> #<Point:0x4684abc>
>> a.object_id
=> 36971870
>> a.__id__
=> 36971870
>> "%X" % a.object_id
=> "234255E"
The default implementation of inspect calls the default implementation of to_s, which just shows the hexadecimal value of the object directly, as seen in the Object#to_s docs (click on the method description to reveal the source).
Meanwhile the comments in the C source underlying the implementation of object_id shows that there are different “namespaces” for Ruby values and object ids, depending on the type of the object (e.g. the lowest bit seems to be zero for all but Fixnums). You can see that in Object#object_id docs (click to reveal the source).
From there we can see that in the “object id space” (returned by object_id) the ids of objects start from the second bit on the right (with the first bit being zero), but in “value space” (used by inspect) they start from the third bit on the right (with the first two bits zero). So, to convert the values from the “object id space” to the “value space”, we can shift the object_id to the left by one bit and get the same result that is shown by inspect:
> '%x' % (36971870 << 1)
=> "4684abc"
> a = Foo.new
=> #<Foo:0x5cfe4>
> '%x' % (a.object_id << 1)
=> "5cfe4"
0x234255E
=>36971870
It's not different, it's the hexadecimal representation of the memory address:-)

Ruby: Resumable functions with arguments

I want a function that keeps local state in Ruby. Each time I call the function I want to return a result that depends both on a calling argument and on the function's stored state. Here's a simple example:
def inc_mult(factor)
#state ||= 0 # initialize the state the first time.
#state += 1 # adjust the internal state.
factor * #state
end
Note that the state is initialized the first time, but subsequent calls access stored state. This is good, except that #state leaks into the surrounding context, which I don't want.
What is the most elegant way of rewriting this so that #state doesn't leak?
(Note: My actual example is much more
complicated, and initializing the
state is expensive.)
You probably want to encapsulate inc_mult into its own class, since you want to encapsulate its state separately from its containing object. This is how generators (the yield statement) work in Python and C#.
Something as simple as this would do it:
class Foo
state = 0
define_method(:[]) do |factor|
state += 1
factor * state
end
end
Philosophically, I think what you’re aiming for is incompatible with Ruby’s view of methods as messages, rather than as functions that can somewhat stand alone.
Functions are stateless. They are procedural code. Classes contain state as well as procedural code. The most elegant way to do this would be to follow the proper programming paradigm:
Class to maintain state
Function to manipulate state
Since you're using Ruby, it may seem a bit more elegent to you to put these things in a module that can be included. The module can handle maintaining state, and the method could simply be called via:
require 'incmodule'
IncModule::inc_mult(10)
Or something similar
I want a function that keeps local state in Ruby.
That word "function" should immediately raise a big fat red flashing warning sign that you are using the wrong programming language. If you want functions, you should use a functional programming language, not an object-oriented one. In a functional programming language, functions usually close over their lexical environment, which makes what you are trying to do absolutely trivial:
var state;
function incMult(factor) {
if (state === undefined) {
state = 0;
}
state += 1;
return factor * state;
}
print(incMult(2)); // => 2
print(incMult(2)); // => 4
print(incMult(2)); // => 6
This particular example is in ECMAScript, but it looks more or less the same in any functional programming language.
[Note: I'm aware that it's not a very good example, because ECMAScript is actually also an object-oriented language and because it has broken scope semantics that atually mean that state leaks in this case, too. In a language with proper scope semantics (and in a couple of years, ECMAScript will be one of them), this'll work as intended. I used ECMAScript mainly for its familiar syntax, not as an example of a good functional language.]
This is the way that state is encapsulated in functional languages since, well, since there are functional languages, all the way back to lambda calculus.
However, in the 1960s some clever people noticed that this was a very common pattern, and they decided that this pattern was so common that it deserved its own language feature. And thus, the object was born.
So, in an object-oriented language, instead of using functional closures to encapsulate state, you would use objects. As you may have noticed, methods in Ruby don't close over their lexical environment, unlike functions in functional programming languages. And this is precisely the reason: because encapsulation of state is achieved via other means.
So, in Ruby you would use an object like this:
inc_mult = Object.new
def inc_mult.call(factor)
#state ||= 0
#state += 1
factor * #state
end
p inc_mult.(2) # => 2
p inc_mult.(2) # => 4
p inc_mult.(2) # => 6
[Sidenote: This 1:1 correspondence is what functional programmers are talking about when they say "objects are just a poor man's closures". Of course, object-oriented programmers usually counter with "closures are just a poor man's objects". And the funny thing is, both of them are right and neither of them realize it.]
Now, for completeness' sake I want to point out that while methods don't close over their lexical environment, there is one construct in Ruby, which does: blocks. (Interestingly enough, blocks aren't objects.) And, since you can define methods using blocks, you can also define methods which are closures:
foo = Object.new
state = nil
foo.define_singleton_method :inc_mult do |factor|
state ||= 0
state += 1
factor * state
end
p foo.inc_mult(2) # => 2
p foo.inc_mult(2) # => 4
p foo.inc_mult(2) # => 6
It seems like you could just use a global or a class variable in some other class, which would at least allow you to skip over the immediately surrounding context.
Well, you could play around a bit... What about a function that rewrites itself?
def imult(factor)
state = 1;
rewrite_with_state(state+1)
factor*state
end
def rewrite_with_state(state)
eval "def imult(factor); state = #{state}; rewrite_with_state(#{state+1}); factor*state; end;"
end
Warning: This is extremely ugly and should not be used in production code!
you can use lambda.
eg,
$ cat test.rb
def mk_lambda( init = 0 )
state = init
->(factor=1, incr=nil){
state += incr || 1;
puts "state now is: #{state}"
factor * state
}
end
f = mk_lambda
p f[]
p f[1]
p f[2]
p f[100]
p f[100,50]
p f[100]
$ ruby test.rb
state now is: 1
1
state now is: 2
2
state now is: 3
6
state now is: 4
400
state now is: 54
5400
state now is: 55
5500
kind regards -botp

Resources