Module: Rigor::ValueSemantics
- Included in:
- Cache::Descriptor::ConfigEntry, Cache::Descriptor::DependencyEntry, Cache::Descriptor::FileEntry, Cache::Descriptor::GemEntry, Cache::Descriptor::PluginEntry, Type::AcceptsResult, Type::App, Type::BoundMethod, Type::DataClass, Type::DataInstance, Type::Difference, Type::Dynamic, Type::HashShape, Type::IntegerRange, Type::Intersection, Type::Nominal, Type::Refined, Type::Singleton, Type::Tuple, Type::Union
- Defined in:
- lib/rigor/value_semantics.rb
Overview
Generates the value-object identity trio (‘==` / `eql?` / `hash`) from a fixed field list. Every `Rigor::Type` carrier and the cache descriptor entries are immutable value objects that each hand-wrote the same three methods; forgetting a field in one of them (or letting `==` and `hash` disagree) silently corrupts `Set` / `Hash`-key behaviour — a carrier vanishes after its first insertion, or two distinct types compare equal.
The methods are CODE-GENERATED at class-definition time, not driven by per-call reflection, so they are as fast as the hand-written versions they replace — ‘hash` and `==` run on the inference hot path (type dedup, fact-store keys, memo caches), where a `send`-per-field would be a real regression.
Usage:
class Nominal
include Rigor::ValueSemantics
value_fields :class_name, :type_args
end
generates exactly:
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
Value objects whose equality is NOT a plain field-wise comparison keep their hand-written ‘==` / `hash` and do not call `value_fields` — e.g. `Type::Constant` also distinguishes `value.class` (so `Constant != Constant`), and `Type::Top` / `Type::Bot` are field-free singletons.
Defined Under Namespace
Modules: ClassMethods
Class Method Summary collapse
Class Method Details
.included(base) ⇒ Object
41 42 43 |
# File 'lib/rigor/value_semantics.rb', line 41 def self.included(base) base.extend(ClassMethods) end |