Hi,
It’s not quite a Ruby questing, but much more a general developer
question.
I believe I’m an experienced Ruby programmer, but there’s one thing I
havent
ever used, but would like to be able to grasp the concept. This is when
to
freeze an object. Could you please show me the right use of #freeze and
#frozen? ? What are the usage patterns of these? When is this language
feature really useful?
On Mon, Apr 21, 2014 at 10:29 AM, Nokan E. [email protected]alid
wrote:
Hi,
It’s not quite a Ruby questing, but much more a general developer question.
I believe I’m an experienced Ruby programmer, but there’s one thing I havent
ever used, but would like to be able to grasp the concept. This is when to
freeze an object. Could you please show me the right use of #freeze and
#frozen? ? What are the usage patterns of these? When is this language
feature really useful?
For example, Hash uses it internally when the keys are strings, in
order to avoid aliasing effects, as a string is mutable. When you set
a value in a hash and the key is a string, it freezes the string.
Jesus.
On Apr 21, 2014, at 4:57, Quintus [email protected] wrote:
Reassigning will still work, but as said this will trigger a warning.
Which is easily avoidable. If you’re that paranoid about your code,
don’t let strangers run it.
Freezing string constants does have some performance benefits, but
you’re starting to get that for free in later ruby versions.
Am 21.04.2014 10:29, schrieb Nokan E.:
Hi,
It’s not quite a Ruby questing, but much more a general developer question.
I believe I’m an experienced Ruby programmer, but there’s one thing I havent
ever used, but would like to be able to grasp the concept. This is when to
freeze an object. Could you please show me the right use of #freeze and
#frozen? ? What are the usage patterns of these? When is this language
feature really useful?
From time to time, I need string constants in my classes, like this:
class Foo
SOME_CONSTANT = “foo bar baz”
end
However, one could still change the string without resorting to a
reassignment (which issues a warning):
Foo::SOME_CONSTANT.replace(“some other stuff”)
To prevent that, you can freeze your string constant.
class Foo
SOME_CONSTANT = “foo bar baz”.freeze
end
Reassigning will still work, but as said this will trigger a warning.
Vale,
Quintus
–
Blog: http://www.quintilianus.eu
I will reject HTML emails. | Ich akzeptiere keine HTML-Nachrichten.
|
Use GnuPG for mail encryption: | GnuPG für Mail-Verschlüsselung:
http://www.gnupg.org | http://gnupg.org/index.de.html
On Mon, Apr 21, 2014 at 9:14 PM, Ryan D. [email protected]
wrote:
On Apr 21, 2014, at 4:57, Quintus [email protected] wrote:
Reassigning will still work, but as said this will trigger a warning.
Which is easily avoidable. If you’re that paranoid about your code, don’t let
strangers run it.

Freezing string constants does have some performance benefits, but you’re
starting to get that for free in later ruby versions.
Because of what changes?
Btw.: IMO freezing a String constant is more about avoiding bugs than
about performance gains. That’s a nice side effect though.
Kind regards
robert
Robert K. [email protected] wrote:
On Mon, Apr 21, 2014 at 9:14 PM, Ryan D. [email protected] wrote:
Freezing string constants does have some performance benefits, but you’re
starting to get that for free in later ruby versions.
Because of what changes?
2.1 deduplicates string literals in source (but strings still get
created).
2.2 will also reuses frozen strings for hash[“lit”] and hash[“lit”]=,
so no new strings are created for common hash get/set ops.
(r44551 + a few followup fixes)
On Tue, Apr 22, 2014 at 12:11 PM, Eric W. [email protected]
wrote:
Robert K. [email protected] wrote:
On Mon, Apr 21, 2014 at 9:14 PM, Ryan D. [email protected] wrote:
Freezing string constants does have some performance benefits, but you’re
starting to get that for free in later ruby versions.
Because of what changes?
2.1 deduplicates string literals in source (but strings still get
created).
So basically there will be a shared string buffer but still individual
instances, i.e.
def f(a)
“foo” + a + “foo”
end
in Ruby there were two buffers and each String literal would create a
new instance. In 2.1 there is just one buffer and still every literal
creates a new instance for every evaluation.
If I understand http://rkh.im/ruby-2.1 properly String instance
creation can be avoided by using the “freeze” modifier:
def f(a)
"foo"f + a + "foo"f
end
Still, with the unfrozen String there is only a space gain and no
performance gain, correct?
2.2 will also reuses frozen strings for hash[“lit”] and hash[“lit”]=,
so no new strings are created for common hash get/set ops.
(r44551 + a few followup fixes)
How does that work? If I understand the diffs [1] properly then the
decision is made at parse time and it seems to me that it is done for
all #[] that fit the bill. Is that correct?
Kind regards
robert
[1]
https://bugs.ruby-lang.org/projects/ruby-trunk/repository/revisions/44551/diff/
Robert K. [email protected] wrote:
So basically there will be a shared string buffer but still individual
instances, i.e.
def f(a)
“foo” + a + “foo”
end
in Ruby there were two buffers and each String literal would create a
new instance. In 2.1 there is just one buffer and still every literal
creates a new instance for every evaluation.
Correct.
If I understand http://rkh.im/ruby-2.1 properly String instance
creation can be avoided by using the “freeze” modifier:
def f(a)
"foo"f + a + "foo"f
end
We dropped “f”, but “.freeze” is equivalent for compatibility with <=2.0
"foo".freeze + a + "foo".freeze
No new “foo” strings created.
Still, with the unfrozen String there is only a space gain and no
performance gain, correct?
Right, since large strings are copy-on-write.
2.2 will also reuses frozen strings for hash[“lit”] and hash[“lit”]=,
so no new strings are created for common hash get/set ops.
(r44551 + a few followup fixes)
How does that work? If I understand the diffs [1] properly then the
decision is made at parse time and it seems to me that it is done for
all #[] that fit the bill. Is that correct?
At parse time, we change the instruction from opt_a* to opt_a*_with
if we detect #[“lit”] or #[“lit”]=. #[non_lit] calls still become
opt_a* instructions.
At runtime, the new opt_a*_with instructions allow us to avoid
String instance creation if the receiver is a hash.
On Tue, Apr 22, 2014 at 11:25 PM, Eric W. [email protected]
wrote:
At runtime, the new opt_a*_with instructions allow us to avoid
String instance creation if the receiver is a hash.
Ah! That was the missing link. Thank you again, Eric!
Good night
robert