Module: Rigor::ValueSemantics::ClassMethods

Defined in:
lib/rigor/value_semantics.rb

Instance Method Summary collapse

Instance Method Details

#value_fields(*fields) ⇒ Object

Define ‘==` / `eql?` / `hash` over the given immutable fields.



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
# File 'lib/rigor/value_semantics.rb', line 47

def value_fields(*fields)
  comparisons = fields.map { |f| "#{f} == other.#{f}" }
  guard = comparisons.empty? ? "" : " && #{comparisons.join(' && ')}"
  key = (["self.class"] + fields.map(&:to_s)).join(", ")

  # Codegen (not per-call reflection) so the generated `==` / `hash`
  # read fields directly and run at hand-written speed on the
  # inference hot path. For `value_fields :class_name, :type_args`
  # the emitted source is:
  #
  #   def ==(other)
  #     other.is_a?(self.class) && class_name == other.class_name && type_args == other.type_args
  #   end
  #   alias_method :eql?, :==
  #   def hash
  #     [self.class, class_name, type_args].hash
  #   end
  class_eval(<<~RUBY, __FILE__, __LINE__ + 1) # rubocop:disable Style/DocumentDynamicEvalDefinition
    def ==(other)
      other.is_a?(self.class)#{guard}
    end
    alias_method :eql?, :==

    def hash
      [#{key}].hash
    end
  RUBY
end