When should actually freeze work?


(Philip Mateescu) #1

Hi,

I have the following cases where I thought freeze should work. It doesn’t,
and I have no clue as to why… (in all cases assignment seems to cancel the
values).

s = "abc"
s.freeze
s.frozen ? # >> true
s = “123” # doesn’t throw a can’t modify frozen string. why ?
s.frozen? # >> false (but I thought I told it to freeze :slight_smile:

s = "abc"
t = "123"
s.freeze #s=“abc”, frozen; t=“123”, !frozen
t = s #s=“abc”, frozen; t=“abc”, frozen
t = “123” #s=“abc”, frozen; t=“123”, !frozen
s = t #s=“123”, frozen; t=“123”, !frozen

i = "50"
1.upto(5) { |i|
puts “i=#{i}”
}

All 3 cases under version 1.7.2 (both cygwin and windows).

Thanks a lot,
philip


(Evan Martin) #2

You need to be careful to distinguish a frozen string from the reference
to the string. It’s a subtle distinction, especially because modifying
the actual string means that your reference

s = "abc"
Means that s now refers to the string "abc"
s.freeze
Means freeze the string that s refers to. You haven’t really changed s,
so you can reassign it.

However, if you try to modify the string itself (functions ending with a !
are good examples), the freeze works as expected:

irb(main):005:0> s = “abc”
“abc"
irb(main):006:0> s.freeze
"abc"
irb(main):007:0> s.gsub!(/a/, ‘b’)
TypeError: can’t modify frozen string
from (irb):7:in `gsub!'
from (irb):7
irb(main):008:0> s
"abc”

Here’s another exercise in how references and strings are separate.
I make b and a refer to the same string, then I change the string and
both b and a now show the change.

irb(main):001:0> a = “abc”
"abc"
irb(main):002:0> b = a
"abc"
irb(main):003:0> b.gsub!(/a/, “hello”)
“hellobc"
irb(main):004:0> b
"hellobc"
irb(main):005:0> a
"hellobc”

This is also why the function is suffixed with an exclamation-- it has
the potential to do something confusing. You may have intended to do
this, instead:

irb(main):001:0> a = “abc”
"abc"
irb(main):002:0> b = a
"abc"
irb(main):003:0> b = b.gsub(/a/, “hello”)
“hellobc"
irb(main):004:0> b
"hellobc"
irb(main):005:0> a
"abc”

Here, I reassign b to be the result of the gsub (notice there’s no ! so
it doesn’t modify the original string; it makes a new one). That leaves
the string a refers to alone.

···

On Wed, Jun 05, 2002 at 03:41:16AM +0900, Philip Mateescu wrote:

s = "abc"
s.freeze
s.frozen ? # >> true
s = “123” # doesn’t throw a can’t modify frozen string. why ?
s.frozen? # >> false (but I thought I told it to freeze :slight_smile:


Evan Martin
martine@cs.washington.edu
http://neugierig.org


(Ned Konz) #3

Because objects are frozen, not variables.

s = "abc"
s.freeze
s.frozen? # >> true
s[0] = 92
TypeError: can’t modify frozen string

···

On Tuesday 04 June 2002 11:41 am, Philip Mateescu wrote:

Hi,

I have the following cases where I thought freeze should work. It
doesn’t, and I have no clue as to why… (in all cases assignment
seems to cancel the values).


Ned Konz
http://bike-nomad.com
GPG key ID: BEEA7EFE


(Kent Dahl) #4

Philip Mateescu wrote:

I have the following cases where I thought freeze should work. It doesn’t,
and I have no clue as to why… (in all cases assignment seems to cancel the
values).

Common newbie misunderstanding. Please remember that all variables are
simply references to objects. Freeze applies to the objects themselves.
Assignment makes a variable refer to a different object, which does not
affect the frozen object.

s = “123” # doesn’t throw a can’t modify frozen string. why ?
s.frozen? # >> false (but I thought I told it to freeze :slight_smile:

Yup, but you have a different string now in s. The frozen one is
probably floating around in ObjectSpace, waiting to get GC’ed.

HTH

To all: I’ve seen this kind of question a few times now, but can’t
locate it in the FAQ.

···


([ Kent Dahl ]/)_ ~ [ http://www.stud.ntnu.no/~kentda/ ]/~
))_student
/(( _d L b_/ NTNU - graduate engineering - 4. year )
( __õ|õ// ) )Industrial economics and technological management(
_
/ö____/ (_engineering.discipline=Computer::Technology)


(Tobi Reif) #5

Evan Martin wrote:

(notice there’s no ! so
it doesn’t modify the original string

Watch out; this is not always true.

Tobi

···


http://www.pinkjuice.com/


(Dossy) #6

Really? I thought assignment was shallow copy (both variables
refer to the same object) while sending #dup to an object caused
a deep copy, whereby the variable would refer to a new, different
object.

– Dossy

···

On 2002.06.05, Kent Dahl kentda@stud.ntnu.no wrote:

Philip Mateescu wrote:

I have the following cases where I thought freeze should work. It doesn’t,
and I have no clue as to why… (in all cases assignment seems to cancel the
values).

Common newbie misunderstanding. Please remember that all variables are
simply references to objects. Freeze applies to the objects themselves.
Assignment makes a variable refer to a different object, which does not
affect the frozen object.


Dossy Shiobara mail: dossy@panoptic.com
Panoptic Computer Network web: http://www.panoptic.com/
“He realized the fastest way to change is to laugh at your own
folly – then you can let go and quickly move on.” (p. 70)


(Evan Martin) #7

Really? Man, I’ve been spoiled by Scheme or something… :slight_smile:
When is it not true?

···

On Wed, Jun 05, 2002 at 04:13:38AM +0900, Tobias Reif wrote:

(notice there’s no ! so
it doesn’t modify the original string

Watch out; this is not always true.


Evan Martin
martine@cs.washington.edu
http://neugierig.org


(Yohanes Santoso) #8

Dossy dossy@panoptic.com writes:

Really? I thought assignment was shallow copy (both variables
refer to the same object) while sending #dup to an object caused
a deep copy, whereby the variable would refer to a new, different
object.

Assignment is analogous to changing the value of a C’s pointer
variable. It does not perform any copying.

#dup performs shallow copy, only the referred object is copied. If
that referred object holds some other objects, then the hold objects
are not copied.

The built-in Marshal class can be used to perform a deep copy. There
are some limitations, though.

YS.


(Tobi Reif) #9

Evan Martin wrote:

When is it not true?

irb(main):001:0> a=[1,2,3]
[1, 2, 3]
irb(main):002:0> b=a+[4,5]
[1, 2, 3, 4, 5]
irb(main):003:0> b
[1, 2, 3, 4, 5]
irb(main):004:0> a
[1, 2, 3]
irb(main):005:0> a[0]=100
100
irb(main):006:0> a
[100, 2, 3]

[]= is bang (which is obvious as it has the “=”)

irb(main):009:0> a.delete 100
100
irb(main):010:0> a
[2, 3]

delete was bang, without a bang ("!")

irb(main):011:0> d=‘foo’
"foo"
irb(main):012:0> d.delete ‘o’
“f"
irb(main):013:0> d
"foo”

here, delete was not bang,

although it was for the array

(or did I err somewhere?)

Most explainable, some counter-intuitive.

Tobi

···


http://www.pinkjuice.com/


(Tobi Reif) #10

Evan Martin wrote:

When is it not true?

clearer:

irb(main):001:0> ary=[1,2,3]
[1, 2, 3]
irb(main):002:0> str=‘bamboozle’
"bamboozle"
irb(main):003:0> [ary,str].each do |obj| obj.freeze end
[[1, 2, 3], “bamboozle”]
irb(main):004:0> ary.delete 1
TypeError: can’t modify frozen array
from (irb):4:in `delete’
from (irb):4

bang without a “!”

irb(main):005:0> str.delete ‘b’
“amoozle”

non-bang when used on a string

irb(main):006:0> str
"bamboozle"

Tobi

···


http://www.pinkjuice.com/