Can't modify frozen Fixnum on Ruby 2.0

ruby, ruby-2.0

Solution

`@divisors` is an instance variable on an instance of Fixnum, so you are trying to alter it. You probably shouldn't be doing this.

What about this?

module Divisors
  def self.for(number)
    @divisors ||= { }
    @divisors[number] ||= begin
      case (number)
      when 1
        [ number ]
      else
        prime_division.map do |n,p|
          (0..p).map { |i| n**i }
        end.inject([1]) do |a,f|
          a.product(f)
        end.map { |f| f.flatten.reduce(:*) } - [ number ]
      end
    end
  end

  def self.sum(number)
     @divisors_sum ||= { }
     @divisors_sum[number] ||= divisors(number).reduce(:+)
  end
end

class Numeric
  #... math helpers

  def divisors
    Divisors.for(self)
  end

  def divisors_sum
     Divisors.sum(self)
  end
end

This means that the methods in Numeric do not modify any instance, the cache is stored elsewhere.

Problem

I have the following code: ``` require 'prime' class Numeric #... math helpers def divisors return [self] if self == 1 @divisors ||= prime_division.map do |n,p| (0..p).map { |i| n**i } end.inject([1]) do |a,f| a.product(f) end.map { |f| f.flatten.reduce(:*) } - [self] end def divisors_sum @divisors_sum ||= divisors.reduce(:+) end #... more methods that evaluate code and 'caches' and assigns (||=) to instance variables end ``` Which outputs an error with: ``` > 4.divisors /home/cygnus/Projects/project-euler/stuff/numbers.rb:24:in `divisors_sum': can't modify frozen Fixnum (RuntimeError) ``` The error disappears when I remove caching into the instance variables `@divisors`, `@divisors_sum`... etc. And this only happens on ruby 2.0. Ran it on 1.9.3 without issues. What's happening?

Original source