1 # $Id: set.rb,v 1.8 2012/04/17 02:49:40 machan Exp $
2
3 require 'tmdoc/tmstd/assertion'
4 require 'tmdoc/tmstd/lsm/abstraction'
5
6
7 module TmStd
8
9 module Lsm
10
11 module Collection
12
13 module Set
14
15 class Abstract < Collection::Abstract
16 attr_reader :lsm_elements
17
18
19 def self.union(array_of_set = [])
20 Assertion.kind_of array_of_set, Array
21
22 new_set = self.new(
23 array_of_set.map { |set|
24 Assertion.kind_of set, Set::Abstract
25
26 set.to_a
27 }.flatten.uniq
28 )
29
30 Assertion.kind_of new_set, self
31 end
32
33
34 def initialize(elements = [])
35 Assertion.kind_of elements, Array
36
37 lsm_element_class
38
39 @lsm_elements = {}
40
41 for element in elements
42 __add__! element
43 end
44 end
45
46
47 def each(&block)
48 @lsm_elements.keys.each(&block)
49
50 nil
51 end
52
53
54 def map_with_index(&block)
55 array = []
56 self.sort.each_with_index do |element, index|
57 array << block.call(element, index)
58 end
59
60 Assertion.kind_of array, Array
61 end
62
63
64 def to_a
65 Assertion.kind_of @lsm_elements.keys, Array
66 end
67
68
69 def include?(element)
70 Assertion.kind_of element, lsm_element_class
71
72 result = if @lsm_elements[element] then true else false end
73
74 Assertion.boolean result
75 end
76
77
78 def union(array_of_set)
79 Assertion.kind_of array_of_set, Array
80
81 new_set = self.class.new(
82 (
83 self.to_a +
84 array_of_set.map { |set|
85 Assertion.kind_of set, Set::Abstract
86
87 set.to_a
88 }.flatten
89 ).uniq
90 )
91
92 Assertion.kind_of self.class
93 end
94
95
96 def +(other)
97 Assertion.kind_of other, Set::Abstract
98
99 new_set = self.class.new((self.to_a + other.to_a).uniq)
100
101 Assertion.kind_of new_set, self.class
102 end
103
104
105 def <<(element)
106 Assertion.kind_of element, lsm_element_class
107
108 if self.include?(element)
109 Assertion.abort(
110 [
111 "Member 'M' is already elemented in 'S'",
112 " M's class: %s",
113 " value: %s",
114 " S's class: %s",
115 " value: %s"
116 ].join("\n"),
117 element.class.to_s, element.to_s,
118 self.class.to_s, self.to_s
119 )
120 end
121
122 case element
123 when ::String, ::Integer
124 element.freeze
125 else
126 element.freeze_equality!
127 end
128
129 new_set = self.class.new(self.to_a + [element])
130
131 Assertion.kind_of new_set, self.class
132 end
133 alias add <<
134
135
136 private
137
138 def __add__!(element)
139 Assertion.kind_of element, lsm_element_class
140
141 if self.include?(element)
142 Assertion.abort(
143 [
144 "Member 'M' is already elemented in 'S'",
145 " M's class: %s",
146 " value: %s",
147 " S's class: %s",
148 " value: %s"
149 ].join("\n"),
150 element.class.to_s, element.to_s,
151 self.class.to_s, self.to_s
152 )
153 end
154
155 case element
156 when ::String, ::Integer
157 element.freeze
158 else
159 element.freeze_equality!
160 end
161 @lsm_elements[element] = true
162
163 nil
164 end
165 end
166
167
168
169 module Mutable
170 def add!(element)
171 __add__! element
172
173 nil
174 end
175
176
177 def union!(array_of_set)
178 Assertion.kind_of array_of_set, Array
179
180 merge_hash = array_of_set.map { |set|
181 Assertion.kind_of set, Set::Abstract
182
183 set.to_a
184 }.flatten.inject({}) { |result_hash, elem|
185 result_hash.merge! elem => true
186 }
187 @lsm_elements.merge! merge_hash
188
189 nil
190 end
191 end
192
193 end # TmStd::Lsm::Collection::Set
194
195 end # TmStd::Lsm::Collection
196
197
198
199 class SetOfString < Collection::Set::Abstract
200 LSM_ELEMENT_CLASS = String
201 end
202
203 EMPTY_SET_OF_STRING = SetOfString.new
204
205
206 class MutableSetOfString < SetOfString
207 include Collection::Set::Mutable
208 end
209
210 end # TmStd::Lsm
211
212 end # TmStd