Class: Algebrick::ProductVariant
- Inherits:
-
Type
show all
- Includes:
- FieldMethodReaders
- Defined in:
- lib/algebrick/product_variant.rb
Overview
Representation of Product and Variant types. The class behaves differently
based on #kind.
noinspection RubyTooManyMethodsInspection
Instance Attribute Summary (collapse)
Instance Method Summary
(collapse)
#add_all_field_method_readers, #add_field_method_reader, #add_field_method_readers, #field_names, #field_names?
Methods inherited from Type
#inspect, #match, #name
Methods included from Reclude
#include, #included, #included_into
#!, #&, #>, #>>, #case, #|, #~
Methods included from Matching
#any, #match, match_value, #on
Methods included from TypeCheck
#Child!, #Child?, #Match!, #Match?, #Type!, #Type?, error
Constructor Details
- (ProductVariant) initialize(name, &definition)
Returns a new instance of ProductVariant
26
27
28
29
30
|
# File 'lib/algebrick/product_variant.rb', line 26
def initialize(name, &definition)
super(name, &definition)
@to_be_kind_of = []
@final_variants = false
end
|
Instance Attribute Details
Returns the value of attribute fields
24
25
26
|
# File 'lib/algebrick/product_variant.rb', line 24
def fields
@fields
end
|
- (Object) variants
Returns the value of attribute variants
24
25
26
|
# File 'lib/algebrick/product_variant.rb', line 24
def variants
@variants
end
|
Instance Method Details
- (Object) ==(other)
95
96
97
98
|
# File 'lib/algebrick/product_variant.rb', line 95
def ==(other)
other.kind_of? ProductVariant and
variants == other.variants and fields == other.fields
end
|
- (Object) add_field_names(names)
185
186
187
188
189
190
191
192
193
|
# File 'lib/algebrick/product_variant.rb', line 185
def add_field_names(names)
@field_names = names
names.all? { |k| Type! k, Symbol }
dict = @field_indexes =
Hash.new { |_, k| raise ArgumentError, "unknown field #{k.inspect} in #{self}" }.
update names.each_with_index.inject({}) { |h, (k, i)| h.update k => i }
define_method(:[]) { |key| @fields[dict[key]] }
end
|
- (Object) apply_be_kind_of
105
106
107
108
109
110
|
# File 'lib/algebrick/product_variant.rb', line 105
def apply_be_kind_of
@to_be_kind_of.each do |type|
@constructor.send :include, type if @constructor
variants.each { |v| v.be_kind_of type unless v == self } if @variants
end
end
|
- (Object) assigned_types
165
166
167
|
# File 'lib/algebrick/product_variant.rb', line 165
def assigned_types
@assigned_types or raise TypeError, "#{self} does not have assigned types"
end
|
- (Object) assigned_types=(assigned_types)
169
170
171
172
|
# File 'lib/algebrick/product_variant.rb', line 169
def assigned_types=(assigned_types)
raise TypeError, "#{self} assigned types already set" if @assigned_types
@assigned_types = assigned_types
end
|
- (Object) be_kind_of(type)
100
101
102
103
|
# File 'lib/algebrick/product_variant.rb', line 100
def be_kind_of(type)
@to_be_kind_of << type
apply_be_kind_of
end
|
- (Object) call(*field_matchers)
112
113
114
115
|
# File 'lib/algebrick/product_variant.rb', line 112
def call(*field_matchers)
raise TypeError, "#{self} does not have any fields" unless @fields
Matchers::Product.new self, *field_matchers
end
|
- (Object) field(name)
62
63
64
|
# File 'lib/algebrick/product_variant.rb', line 62
def field(name)
fields[field_indexes[name]]
end
|
- (Object) field_indexes
58
59
60
|
# File 'lib/algebrick/product_variant.rb', line 58
def field_indexes
@field_indexes or raise TypeError, "field names not defined on #{self}"
end
|
66
67
68
69
|
# File 'lib/algebrick/product_variant.rb', line 66
def final!
@final_variants = true
self
end
|
noinspection RubyCaseWithoutElseBlockInspection
152
153
154
155
156
157
158
159
160
161
162
163
|
# File 'lib/algebrick/product_variant.rb', line 152
def kind
@kind ||= case
when @fields && !@variants
:product
when @fields && @variants
:product_variant
when !@fields && @variants
:variant
when !@fields && !@variants
raise TypeError, 'fields or variants have to be set'
end
end
|
- (Object) new(*fields)
Also known as:
[]
88
89
90
91
|
# File 'lib/algebrick/product_variant.rb', line 88
def new(*fields)
raise TypeError, "#{self} does not have fields" unless @constructor
@constructor.new *fields
end
|
- (Object) product_to_s
176
177
178
179
180
181
182
183
|
# File 'lib/algebrick/product_variant.rb', line 176
def product_to_s
fields_str = if field_names?
field_names.zip(fields).map { |name, field| "#{name}: #{field.name}" }
else
fields.map(&:name)
end
"#{name}(#{fields_str.join ', '})"
end
|
- (Object) set_fields(fields_or_hash)
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
|
# File 'lib/algebrick/product_variant.rb', line 32
def set_fields(fields_or_hash)
raise TypeError, 'can be set only once' if @fields
@kind = nil
fields, keys = case fields_or_hash
when Hash
[fields_or_hash.values, fields_or_hash.keys]
when Array
[fields_or_hash, nil]
else
raise ArgumentError
end
add_field_names keys if keys
fields.all? { |f| Type! f, Type, Class, Module }
raise TypeError, 'there is no product with zero fields' unless fields.size > 0
define_method(:value) { @fields.first } if fields.size == 1
@fields = fields
@constructor = Class.new(
field_names? ? ProductConstructors::Named : ProductConstructors::Basic).
tap { |c| c.type = self }
const_set :Constructor, @constructor
apply_be_kind_of
self
end
|
- (Object) set_variants(*variants)
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
|
# File 'lib/algebrick/product_variant.rb', line 71
def set_variants(*variants)
raise TypeError, 'can be set only once' if @variants && @final_variants
@kind = nil
variants.all? { |v| Type! v, Type, Class }
@variants ||= []
@variants += variants
apply_be_kind_of
variants.each do |v|
if v.respond_to? :be_kind_of
v.be_kind_of self
else
v.send :include, self
end
end
self
end
|
117
118
119
120
121
122
123
124
125
126
127
128
|
# File 'lib/algebrick/product_variant.rb', line 117
def to_m
case kind
when :product
Matchers::Product.new self
when :product_variant
Matchers::Variant.new self
when :variant
Matchers::Variant.new self
else
raise
end
end
|
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
|
# File 'lib/algebrick/product_variant.rb', line 130
def to_s
case kind
when :product
product_to_s
when :product_variant
name + '(' +
variants.map do |variant|
if variant == self
product_to_s
else
variant.name
end
end.join(' | ') +
')'
when :variant
"#{name}(#{variants.map(&:name).join ' | '})"
else
raise
end
end
|