File: immutable.rb

package info (click to toggle)
ruby-hamster 3.0.0-2
  • links: PTS, VCS
  • area: main
  • in suites: bullseye, buster, stretch
  • size: 1,860 kB
  • ctags: 588
  • sloc: ruby: 16,909; makefile: 3
file content (75 lines) | stat: -rw-r--r-- 1,676 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
module Hamster
  # @private
  module Immutable
    def self.included(klass)
      klass.extend(ClassMethods)
      klass.instance_eval do
        include InstanceMethods
      end
    end

    # @private
    module ClassMethods
      def new(*args)
        super.__send__(:immutable!)
      end

      def memoize(*names)
        include MemoizeMethods unless include?(MemoizeMethods)
        names.each do |name|
          original_method = "__hamster_immutable_#{name}__"
          alias_method original_method, name
          class_eval <<-METHOD, __FILE__, __LINE__
            def #{name}
              if @__hamster_immutable_memory__.instance_variable_defined?(:@#{name})
                @__hamster_immutable_memory__.instance_variable_get(:@#{name})
              else
                @__hamster_immutable_memory__.instance_variable_set(:@#{name}, #{original_method})
              end
            end
          METHOD
        end
      end
    end

    # @private
    module MemoizeMethods
      def immutable!
        @__hamster_immutable_memory__ = Object.new
        freeze
      end
    end

    # @private
    module InstanceMethods
      def immutable!
        freeze
      end

      def immutable?
        frozen?
      end

      alias_method :__hamster_immutable_dup__, :dup
      private :__hamster_immutable_dup__

      def dup
        self
      end

      def clone
        self
      end

      protected

      def transform_unless(condition, &block)
        condition ? self : transform(&block)
      end

      def transform(&block)
        __hamster_immutable_dup__.tap { |copy| copy.instance_eval(&block) }.immutable!
      end
    end
  end
end