Ruby is a language like Java, everything is reference to object. An assignment does not produce copy of the value, but the copy of the reference. So if you have an a
object, and you say b=a
then you will have a b
object reference pointing to the same place as a
.
The naive approach of a string is that if I say a='x12345y'; b=a; b.sub!('234','---');
will result in an a
which's value is 'x12345y'
and a b
which's value is 'x1---5y'
.
The Java guys invented the immutable pattern which means that after a string is created it cannot be modified. The sensation of modification comes from the construction of new strings from old ones, like s = s.concat("TEST")
where s.concat("TEST")
creates a new string which's reference may or may not be stored back at s
itself.
But Ruby has weird behavior:
original = '|123|123|123|123|'
s = original
s['123']='TEST'
print(s,"\n")
s = original
s.sub!('123','TEST')
print(s,"\n")
will output
|TEST|123|123|123|
|TEST|TEST|123|123|
You do not know enough
- they say,
There are immutable objects in ruby too!
. I just have to call the
freeze
method and the object will be immutable. Let's try it.
original = '|123|123|123|123|'
original.freeze # <--- NEW GUY
s = original
s['123']='TEST'
print(s,"\n")
s = original
s.sub!('123','TEST')
print(s,"\n")
will output
stringtest.rb:4:in `[]=': can't modify frozen string (TypeError)
from stringtest.rb:4
That is just plain wonderful. We are still on the same place: nowhere. What would be the solution? Nothing sane is available. You have to use s = String.new(original)
instead of simple assignment. This is a terrible looking pain in the ass solution.
Who the hell knows where was my string declared at the first time? Who knows what will be broken if I change a string I got from somewhere? Who will find the real problem for an error message like File not found: 'TEST'
?