Why are there frozen constants everywhere? Why are there frozen constants everywhere? ruby ruby

Why are there frozen constants everywhere?


It is correct that Ruby prints a warning when you re-assign a value to an already initialized constant:

> FOO = 'foo'> FOO = 'bar'# :2: warning: already initialized constant FOO# :1: warning: previous definition of FOO was here> FOO# => "bar"

But there is no protection from changing the value in the constant. Example without freeze:

> FOO = 'foo'> FOO[1] = '-'> FOO# => "f-o"

But freeze allows to protect the value of the constants from being changed. Example with freeze:

> FOO = 'foo'.freeze> FOO[1] = '-'# => RuntimeError: can't modify frozen String


normally Rubyist freeze string literals to make execution faster. If there is some function call for example like below in some controller, every request will call that function.

log("debug")

what happens is ruby defines a new garbage string object every time. Object allocation is not free. it consumes memory and CPU. Garbage will be there till GC collects them.

but if literals are frozen

log("debug".freeze)

ruby allocates once and caches it for later use. Also, the string object will be immutable and safe for use in the multithreaded environment.

From ruby 3.0 ruby is gonna freeze every string, - according to Matz.


update:

If you add the following comment in the beginning of ruby file then every string literal in the entire file will be immutable. This is pretty helpful when you are trying to optimize your app for the muti-threaded environment.

# frozen_string_literal: true

or you can even start your Ruby process with --enable-frozen-string-literal switch.


One explanation why you see this consistent freezing of constants in popular projects is that they use Rubocop, a code analyzer.

It's a standard Rubocop rule that constants shouldn't be mutable, for the reasons mentioned above by @spickermann.