Norman Clarke

Programming open source code for fun and profit!

When to use freeze in Ruby

I recently saw a few Tweets where some pretty bright Ruby developers were complaining that Ruby's freeze method causes more problems than it's worth. (For those who don't work with Ruby, freeze makes a mutable object immutable). I've seen this method used incorrectly a few times in the past, so I thought it merited writing a short blog post.

In order to understand the utility of freeze, it's important to look at a language's features in terms of those useful at runtime (i.e. calculating string length) and those useful during development (i.e. defining a class).

Freeze is mostly useful for development. Consider the code below:

class Universe

  include Singleton

  ELEMENTS = {
    1 => :H,
    2 => :He,
    3 => :Li,
    4 => :Be,
      ...
    103 => :Lr
  }.freeze
end

Here, freezing the ELEMENTS hash makes it impossible to add new elements. (Yes, Ruby constants are mutable). Why do this? Because it should be something extremely unusual to add a new element; so unusual in fact, that I want to make it very hard for a developer on my team to do so without causing an error. I'm not going to worry about freeze causing runtime errors, because I'm writing tests and assume my collaborators are too. If a new element is discovered, I don't want it added via a monkey-patch, I want the source itself patched.

These are the only places I tend to use freeze; almost any place else is likely to cause annoyance. I'm sure there are plenty of exceptions to prove this rule, but by and large unless you know WHY, don't use freeze except in setup code.

Published