hamster 1.0.1.pre.rc2 → 1.0.1.pre.rc3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (482) hide show
  1. checksums.yaml +4 -4
  2. data/lib/hamster.rb +2 -2
  3. data/lib/hamster/core_ext.rb +0 -1
  4. data/lib/hamster/core_ext/enumerable.rb +17 -17
  5. data/lib/hamster/core_ext/io.rb +15 -17
  6. data/lib/hamster/deque.rb +229 -0
  7. data/lib/hamster/enumerable.rb +147 -105
  8. data/lib/hamster/experimental/mutable_queue.rb +2 -2
  9. data/lib/hamster/hash.rb +488 -82
  10. data/lib/hamster/immutable.rb +4 -0
  11. data/lib/hamster/list.rb +839 -196
  12. data/lib/hamster/read_copy_update.rb +1 -0
  13. data/lib/hamster/set.rb +317 -54
  14. data/lib/hamster/sorted_set.rb +1014 -0
  15. data/lib/hamster/trie.rb +67 -47
  16. data/lib/hamster/undefined.rb +1 -3
  17. data/lib/hamster/vector.rb +989 -76
  18. data/lib/hamster/version.rb +1 -1
  19. data/spec/{hamster → lib/hamster}/core_ext/array_spec.rb +1 -1
  20. data/spec/{hamster → lib/hamster}/core_ext/enumerable_spec.rb +4 -0
  21. data/spec/{hamster → lib/hamster}/core_ext/io_spec.rb +0 -0
  22. data/spec/lib/hamster/deque/clear_spec.rb +34 -0
  23. data/spec/lib/hamster/deque/construction_spec.rb +30 -0
  24. data/spec/lib/hamster/deque/copying_spec.rb +20 -0
  25. data/spec/lib/hamster/deque/dequeue_spec.rb +27 -0
  26. data/spec/lib/hamster/deque/empty_spec.rb +42 -0
  27. data/spec/{hamster/queue → lib/hamster/deque}/enqueue_spec.rb +7 -10
  28. data/spec/lib/hamster/deque/head_spec.rb +20 -0
  29. data/spec/lib/hamster/deque/inspect_spec.rb +24 -0
  30. data/spec/lib/hamster/deque/last_spec.rb +20 -0
  31. data/spec/lib/hamster/deque/marshal_spec.rb +34 -0
  32. data/spec/lib/hamster/deque/new_spec.rb +44 -0
  33. data/spec/lib/hamster/deque/pop_spec.rb +25 -0
  34. data/spec/lib/hamster/deque/random_modification_spec.rb +34 -0
  35. data/spec/{hamster/queue → lib/hamster/deque}/size_spec.rb +4 -9
  36. data/spec/lib/hamster/deque/to_a_spec.rb +27 -0
  37. data/spec/{hamster/queue → lib/hamster/deque}/to_ary_spec.rb +6 -6
  38. data/spec/lib/hamster/deque/to_list_spec.rb +26 -0
  39. data/spec/lib/hamster/deque/unshift_spec.rb +26 -0
  40. data/spec/{hamster → lib/hamster}/experimental/mutable_set/add_qm_spec.rb +0 -0
  41. data/spec/{hamster → lib/hamster}/experimental/mutable_set/add_spec.rb +0 -0
  42. data/spec/{hamster → lib/hamster}/experimental/mutable_set/delete_qm_spec.rb +0 -0
  43. data/spec/{hamster → lib/hamster}/experimental/mutable_set/delete_spec.rb +0 -0
  44. data/spec/{hamster → lib/hamster}/hash/all_spec.rb +10 -0
  45. data/spec/lib/hamster/hash/any_spec.rb +56 -0
  46. data/spec/lib/hamster/hash/assoc_spec.rb +52 -0
  47. data/spec/lib/hamster/hash/clear_spec.rb +43 -0
  48. data/spec/lib/hamster/hash/construction_spec.rb +39 -0
  49. data/spec/{hamster → lib/hamster}/hash/copying_spec.rb +2 -4
  50. data/spec/lib/hamster/hash/default_proc_spec.rb +73 -0
  51. data/spec/lib/hamster/hash/delete_spec.rb +40 -0
  52. data/spec/lib/hamster/hash/each_spec.rb +78 -0
  53. data/spec/lib/hamster/hash/each_with_index_spec.rb +30 -0
  54. data/spec/lib/hamster/hash/empty_spec.rb +46 -0
  55. data/spec/lib/hamster/hash/eql_spec.rb +70 -0
  56. data/spec/lib/hamster/hash/except_spec.rb +43 -0
  57. data/spec/lib/hamster/hash/fetch_spec.rb +58 -0
  58. data/spec/lib/hamster/hash/filter_spec.rb +58 -0
  59. data/spec/lib/hamster/hash/find_spec.rb +44 -0
  60. data/spec/lib/hamster/hash/flat_map_spec.rb +36 -0
  61. data/spec/lib/hamster/hash/flatten_spec.rb +99 -0
  62. data/spec/lib/hamster/hash/get_spec.rb +80 -0
  63. data/spec/lib/hamster/hash/has_key_spec.rb +32 -0
  64. data/spec/lib/hamster/hash/has_value_spec.rb +28 -0
  65. data/spec/{hamster → lib/hamster}/hash/hash_spec.rb +5 -12
  66. data/spec/{hamster → lib/hamster}/hash/immutable_spec.rb +0 -0
  67. data/spec/lib/hamster/hash/inspect_spec.rb +31 -0
  68. data/spec/lib/hamster/hash/invert_spec.rb +31 -0
  69. data/spec/lib/hamster/hash/key_spec.rb +28 -0
  70. data/spec/{hamster → lib/hamster}/hash/keys_spec.rb +3 -6
  71. data/spec/lib/hamster/hash/map_spec.rb +46 -0
  72. data/spec/{hamster → lib/hamster}/hash/marshal_spec.rb +3 -3
  73. data/spec/lib/hamster/hash/merge_spec.rb +77 -0
  74. data/spec/lib/hamster/hash/min_max_spec.rb +50 -0
  75. data/spec/lib/hamster/hash/new_spec.rb +71 -0
  76. data/spec/{hamster → lib/hamster}/hash/none_spec.rb +12 -14
  77. data/spec/lib/hamster/hash/partition_spec.rb +36 -0
  78. data/spec/lib/hamster/hash/pretty_print_spec.rb +35 -0
  79. data/spec/lib/hamster/hash/put_spec.rb +81 -0
  80. data/spec/lib/hamster/hash/reduce_spec.rb +36 -0
  81. data/spec/lib/hamster/hash/remove_spec.rb +62 -0
  82. data/spec/lib/hamster/hash/reverse_each_spec.rb +28 -0
  83. data/spec/lib/hamster/hash/sample_spec.rb +14 -0
  84. data/spec/{hamster → lib/hamster}/hash/size_spec.rb +2 -2
  85. data/spec/lib/hamster/hash/slice_spec.rb +45 -0
  86. data/spec/lib/hamster/hash/sort_spec.rb +27 -0
  87. data/spec/lib/hamster/hash/store_spec.rb +54 -0
  88. data/spec/lib/hamster/hash/take_spec.rb +36 -0
  89. data/spec/lib/hamster/hash/to_a_spec.rb +14 -0
  90. data/spec/lib/hamster/hash/to_hash_spec.rb +22 -0
  91. data/spec/{hamster → lib/hamster}/hash/uniq_spec.rb +2 -4
  92. data/spec/lib/hamster/hash/values_at_spec.rb +14 -0
  93. data/spec/lib/hamster/hash/values_spec.rb +25 -0
  94. data/spec/{hamster → lib/hamster}/immutable/copying_spec.rb +0 -0
  95. data/spec/{hamster → lib/hamster}/immutable/immutable_spec.rb +0 -0
  96. data/spec/{hamster → lib/hamster}/immutable/memoize_spec.rb +2 -2
  97. data/spec/{hamster → lib/hamster}/immutable/new_spec.rb +0 -0
  98. data/spec/{hamster → lib/hamster}/immutable/transform_spec.rb +0 -0
  99. data/spec/{hamster → lib/hamster}/immutable/transform_unless_spec.rb +0 -0
  100. data/spec/lib/hamster/list/add_spec.rb +20 -0
  101. data/spec/lib/hamster/list/all_spec.rb +60 -0
  102. data/spec/{hamster → lib/hamster}/list/any_spec.rb +12 -20
  103. data/spec/{hamster → lib/hamster}/list/append_spec.rb +9 -10
  104. data/spec/lib/hamster/list/at_spec.rb +30 -0
  105. data/spec/lib/hamster/list/break_spec.rb +70 -0
  106. data/spec/{hamster → lib/hamster}/list/cadr_spec.rb +5 -8
  107. data/spec/{hamster → lib/hamster}/list/chunk_spec.rb +5 -8
  108. data/spec/{hamster → lib/hamster}/list/clear_spec.rb +4 -7
  109. data/spec/lib/hamster/list/combination_spec.rb +34 -0
  110. data/spec/{hamster → lib/hamster}/list/compact_spec.rb +5 -8
  111. data/spec/lib/hamster/list/compare_spec.rb +31 -0
  112. data/spec/{hamster → lib/hamster}/list/cons_spec.rb +5 -9
  113. data/spec/lib/hamster/list/construction_spec.rb +118 -0
  114. data/spec/{hamster → lib/hamster}/list/copying_spec.rb +3 -7
  115. data/spec/lib/hamster/list/count_spec.rb +37 -0
  116. data/spec/lib/hamster/list/cycle_spec.rb +29 -0
  117. data/spec/lib/hamster/list/delete_at_spec.rb +19 -0
  118. data/spec/lib/hamster/list/delete_spec.rb +17 -0
  119. data/spec/{hamster → lib/hamster}/list/drop_spec.rb +5 -8
  120. data/spec/lib/hamster/list/drop_while_spec.rb +39 -0
  121. data/spec/lib/hamster/list/each_slice_spec.rb +52 -0
  122. data/spec/lib/hamster/list/each_spec.rb +43 -0
  123. data/spec/lib/hamster/list/each_with_index_spec.rb +29 -0
  124. data/spec/{hamster → lib/hamster}/list/elem_index_spec.rb +4 -14
  125. data/spec/{hamster → lib/hamster}/list/elem_indices_spec.rb +5 -9
  126. data/spec/{hamster → lib/hamster}/list/empty_spec.rb +4 -13
  127. data/spec/{hamster → lib/hamster}/list/eql_spec.rb +2 -8
  128. data/spec/lib/hamster/list/fill_spec.rb +50 -0
  129. data/spec/{hamster → lib/hamster}/list/filter_spec.rb +3 -2
  130. data/spec/{hamster → lib/hamster}/list/find_all_spec.rb +3 -2
  131. data/spec/{hamster → lib/hamster}/list/find_index_spec.rb +4 -14
  132. data/spec/{hamster → lib/hamster}/list/find_indices_spec.rb +11 -9
  133. data/spec/{hamster → lib/hamster}/list/find_spec.rb +10 -16
  134. data/spec/{hamster → lib/hamster}/list/flat_map_spec.rb +0 -0
  135. data/spec/{hamster → lib/hamster}/list/flatten_spec.rb +5 -8
  136. data/spec/{hamster → lib/hamster}/list/grep_spec.rb +9 -17
  137. data/spec/{hamster → lib/hamster}/list/group_by_spec.rb +8 -24
  138. data/spec/{hamster → lib/hamster}/list/hash_spec.rb +4 -12
  139. data/spec/{hamster → lib/hamster}/list/head_spec.rb +2 -7
  140. data/spec/{hamster → lib/hamster}/list/include_spec.rb +4 -13
  141. data/spec/{hamster → lib/hamster}/list/init_spec.rb +5 -9
  142. data/spec/lib/hamster/list/inits_spec.rb +29 -0
  143. data/spec/lib/hamster/list/insert_spec.rb +47 -0
  144. data/spec/lib/hamster/list/inspect_spec.rb +30 -0
  145. data/spec/{hamster → lib/hamster}/list/intersperse_spec.rb +5 -8
  146. data/spec/lib/hamster/list/join_spec.rb +64 -0
  147. data/spec/lib/hamster/list/last_spec.rb +24 -0
  148. data/spec/{hamster → lib/hamster}/list/map_spec.rb +11 -20
  149. data/spec/lib/hamster/list/maximum_spec.rb +42 -0
  150. data/spec/{hamster → lib/hamster}/list/merge_by_spec.rb +4 -13
  151. data/spec/{hamster → lib/hamster}/list/merge_spec.rb +0 -0
  152. data/spec/lib/hamster/list/minimum_spec.rb +42 -0
  153. data/spec/lib/hamster/list/multithreading_spec.rb +48 -0
  154. data/spec/{hamster → lib/hamster}/list/none_spec.rb +11 -21
  155. data/spec/{hamster → lib/hamster}/list/one_spec.rb +12 -22
  156. data/spec/lib/hamster/list/partition_spec.rb +116 -0
  157. data/spec/lib/hamster/list/permutation_spec.rb +56 -0
  158. data/spec/{hamster → lib/hamster}/list/pop_spec.rb +1 -1
  159. data/spec/lib/hamster/list/product_spec.rb +24 -0
  160. data/spec/lib/hamster/list/reduce_spec.rb +97 -0
  161. data/spec/{hamster → lib/hamster}/list/remove_spec.rb +9 -19
  162. data/spec/{hamster → lib/hamster}/list/reverse_spec.rb +7 -14
  163. data/spec/lib/hamster/list/rotate_spec.rb +37 -0
  164. data/spec/lib/hamster/list/sample_spec.rb +14 -0
  165. data/spec/{hamster → lib/hamster}/list/select_spec.rb +3 -2
  166. data/spec/{hamster → lib/hamster}/list/size_spec.rb +4 -13
  167. data/spec/lib/hamster/list/slice_spec.rb +230 -0
  168. data/spec/{hamster → lib/hamster}/list/sorting_spec.rb +10 -20
  169. data/spec/lib/hamster/list/span_spec.rb +77 -0
  170. data/spec/{hamster → lib/hamster}/list/split_at_spec.rb +13 -14
  171. data/spec/lib/hamster/list/subsequences_spec.rb +24 -0
  172. data/spec/lib/hamster/list/sum_spec.rb +24 -0
  173. data/spec/lib/hamster/list/tail_spec.rb +31 -0
  174. data/spec/lib/hamster/list/tails_spec.rb +29 -0
  175. data/spec/{hamster → lib/hamster}/list/take_spec.rb +5 -8
  176. data/spec/{hamster → lib/hamster}/list/take_while_spec.rb +11 -17
  177. data/spec/lib/hamster/list/to_a_spec.rb +40 -0
  178. data/spec/{hamster → lib/hamster}/list/to_ary_spec.rb +1 -3
  179. data/spec/{hamster → lib/hamster}/list/to_list_spec.rb +3 -7
  180. data/spec/{hamster → lib/hamster}/list/to_set_spec.rb +2 -10
  181. data/spec/lib/hamster/list/transpose_spec.rb +20 -0
  182. data/spec/{hamster → lib/hamster}/list/union_spec.rb +5 -12
  183. data/spec/{hamster → lib/hamster}/list/uniq_spec.rb +5 -8
  184. data/spec/{hamster → lib/hamster}/list/zip_spec.rb +2 -9
  185. data/spec/lib/hamster/set/add_spec.rb +76 -0
  186. data/spec/{hamster → lib/hamster}/set/all_spec.rb +18 -14
  187. data/spec/{hamster → lib/hamster}/set/any_spec.rb +19 -16
  188. data/spec/{hamster → lib/hamster}/set/clear_spec.rb +8 -11
  189. data/spec/{hamster → lib/hamster}/set/compact_spec.rb +4 -7
  190. data/spec/{hamster → lib/hamster}/set/construction_spec.rb +4 -8
  191. data/spec/{hamster → lib/hamster}/set/copying_spec.rb +3 -5
  192. data/spec/{hamster → lib/hamster}/set/count_spec.rb +11 -16
  193. data/spec/lib/hamster/set/delete_spec.rb +72 -0
  194. data/spec/lib/hamster/set/difference_spec.rb +50 -0
  195. data/spec/lib/hamster/set/disjoint_spec.rb +26 -0
  196. data/spec/lib/hamster/set/each_spec.rb +46 -0
  197. data/spec/lib/hamster/set/empty_spec.rb +47 -0
  198. data/spec/{hamster → lib/hamster}/set/eqeq_spec.rb +0 -0
  199. data/spec/{hamster → lib/hamster}/set/eql_spec.rb +7 -1
  200. data/spec/lib/hamster/set/exclusion_spec.rb +48 -0
  201. data/spec/lib/hamster/set/filter_spec.rb +74 -0
  202. data/spec/{hamster → lib/hamster}/set/find_spec.rb +7 -11
  203. data/spec/lib/hamster/set/flatten_spec.rb +47 -0
  204. data/spec/{hamster → lib/hamster}/set/foreach_spec.rb +5 -4
  205. data/spec/{hamster → lib/hamster}/set/grep_spec.rb +1 -1
  206. data/spec/lib/hamster/set/group_by_spec.rb +60 -0
  207. data/spec/lib/hamster/set/hash_spec.rb +23 -0
  208. data/spec/lib/hamster/set/head_spec.rb +31 -0
  209. data/spec/{hamster → lib/hamster}/set/immutable_spec.rb +0 -0
  210. data/spec/lib/hamster/set/include_spec.rb +61 -0
  211. data/spec/lib/hamster/set/inspect_spec.rb +48 -0
  212. data/spec/lib/hamster/set/intersect_spec.rb +26 -0
  213. data/spec/lib/hamster/set/intersection_spec.rb +53 -0
  214. data/spec/lib/hamster/set/join_spec.rb +65 -0
  215. data/spec/lib/hamster/set/map_spec.rb +60 -0
  216. data/spec/{hamster → lib/hamster}/set/marshal_spec.rb +3 -3
  217. data/spec/{hamster → lib/hamster}/set/maximum_spec.rb +6 -15
  218. data/spec/{hamster → lib/hamster}/set/minimum_spec.rb +6 -16
  219. data/spec/lib/hamster/set/new_spec.rb +54 -0
  220. data/spec/{hamster → lib/hamster}/set/none_spec.rb +15 -15
  221. data/spec/{hamster → lib/hamster}/set/one_spec.rb +14 -16
  222. data/spec/lib/hamster/set/partition_spec.rb +53 -0
  223. data/spec/{hamster → lib/hamster}/set/product_spec.rb +6 -6
  224. data/spec/lib/hamster/set/reduce_spec.rb +56 -0
  225. data/spec/lib/hamster/set/remove_spec.rb +51 -0
  226. data/spec/{hamster/set/each_spec.rb → lib/hamster/set/reverse_each_spec.rb} +8 -7
  227. data/spec/lib/hamster/set/sample_spec.rb +14 -0
  228. data/spec/{hamster → lib/hamster}/set/size_spec.rb +0 -1
  229. data/spec/{hamster → lib/hamster}/set/sorting_spec.rb +17 -13
  230. data/spec/lib/hamster/set/subset_spec.rb +52 -0
  231. data/spec/lib/hamster/set/sum_spec.rb +24 -0
  232. data/spec/lib/hamster/set/superset_spec.rb +52 -0
  233. data/spec/lib/hamster/set/to_a_spec.rb +31 -0
  234. data/spec/lib/hamster/set/to_list_spec.rb +37 -0
  235. data/spec/{hamster → lib/hamster}/set/to_set_spec.rb +2 -6
  236. data/spec/lib/hamster/set/union_spec.rb +55 -0
  237. data/spec/{hamster → lib/hamster}/set/uniq_spec.rb +2 -5
  238. data/spec/lib/hamster/sorted_set/above_spec.rb +52 -0
  239. data/spec/lib/hamster/sorted_set/add_spec.rb +63 -0
  240. data/spec/lib/hamster/sorted_set/at_spec.rb +25 -0
  241. data/spec/lib/hamster/sorted_set/below_spec.rb +52 -0
  242. data/spec/lib/hamster/sorted_set/between_spec.rb +52 -0
  243. data/spec/lib/hamster/sorted_set/clear_spec.rb +35 -0
  244. data/spec/lib/hamster/sorted_set/construction_spec.rb +29 -0
  245. data/spec/lib/hamster/sorted_set/delete_at_spec.rb +19 -0
  246. data/spec/lib/hamster/sorted_set/delete_spec.rb +81 -0
  247. data/spec/{hamster/set → lib/hamster/sorted_set}/difference_spec.rb +5 -9
  248. data/spec/lib/hamster/sorted_set/disjoint_spec.rb +26 -0
  249. data/spec/lib/hamster/sorted_set/drop_spec.rb +29 -0
  250. data/spec/lib/hamster/sorted_set/drop_while_spec.rb +35 -0
  251. data/spec/lib/hamster/sorted_set/each_spec.rb +31 -0
  252. data/spec/lib/hamster/sorted_set/empty_spec.rb +37 -0
  253. data/spec/lib/hamster/sorted_set/eql_spec.rb +121 -0
  254. data/spec/{hamster/set → lib/hamster/sorted_set}/exclusion_spec.rb +4 -9
  255. data/spec/lib/hamster/sorted_set/fetch_spec.rb +65 -0
  256. data/spec/lib/hamster/sorted_set/filter_spec.rb +62 -0
  257. data/spec/lib/hamster/sorted_set/find_index_spec.rb +33 -0
  258. data/spec/lib/hamster/sorted_set/first_spec.rb +21 -0
  259. data/spec/lib/hamster/sorted_set/from_spec.rb +52 -0
  260. data/spec/lib/hamster/sorted_set/group_by_spec.rb +58 -0
  261. data/spec/lib/hamster/sorted_set/include_spec.rb +24 -0
  262. data/spec/lib/hamster/sorted_set/inspect_spec.rb +38 -0
  263. data/spec/lib/hamster/sorted_set/intersect_spec.rb +26 -0
  264. data/spec/lib/hamster/sorted_set/intersection_spec.rb +29 -0
  265. data/spec/lib/hamster/sorted_set/last_spec.rb +37 -0
  266. data/spec/lib/hamster/sorted_set/map_spec.rb +36 -0
  267. data/spec/lib/hamster/sorted_set/marshal_spec.rb +37 -0
  268. data/spec/lib/hamster/sorted_set/minimum_spec.rb +22 -0
  269. data/spec/lib/hamster/sorted_set/new_spec.rb +52 -0
  270. data/spec/lib/hamster/sorted_set/reverse_each_spec.rb +29 -0
  271. data/spec/lib/hamster/sorted_set/sample_spec.rb +14 -0
  272. data/spec/lib/hamster/sorted_set/size_spec.rb +18 -0
  273. data/spec/lib/hamster/sorted_set/slice_spec.rb +241 -0
  274. data/spec/lib/hamster/sorted_set/sorting_spec.rb +45 -0
  275. data/spec/lib/hamster/sorted_set/subset_spec.rb +48 -0
  276. data/spec/lib/hamster/sorted_set/superset_spec.rb +48 -0
  277. data/spec/lib/hamster/sorted_set/take_spec.rb +26 -0
  278. data/spec/lib/hamster/sorted_set/take_while_spec.rb +34 -0
  279. data/spec/lib/hamster/sorted_set/to_set_spec.rb +19 -0
  280. data/spec/lib/hamster/sorted_set/union_spec.rb +28 -0
  281. data/spec/lib/hamster/sorted_set/up_to_spec.rb +52 -0
  282. data/spec/lib/hamster/sorted_set/values_at_spec.rb +34 -0
  283. data/spec/lib/hamster/vector/add_spec.rb +68 -0
  284. data/spec/{hamster → lib/hamster}/vector/any_spec.rb +0 -0
  285. data/spec/lib/hamster/vector/assoc_spec.rb +36 -0
  286. data/spec/lib/hamster/vector/bsearch_spec.rb +58 -0
  287. data/spec/lib/hamster/vector/clear_spec.rb +34 -0
  288. data/spec/lib/hamster/vector/combination_spec.rb +82 -0
  289. data/spec/lib/hamster/vector/compact_spec.rb +30 -0
  290. data/spec/lib/hamster/vector/compare_spec.rb +32 -0
  291. data/spec/lib/hamster/vector/concat_spec.rb +35 -0
  292. data/spec/{hamster → lib/hamster}/vector/copying_spec.rb +3 -6
  293. data/spec/lib/hamster/vector/count_spec.rb +18 -0
  294. data/spec/lib/hamster/vector/delete_at_spec.rb +54 -0
  295. data/spec/lib/hamster/vector/delete_spec.rb +31 -0
  296. data/spec/lib/hamster/vector/drop_spec.rb +35 -0
  297. data/spec/lib/hamster/vector/drop_while_spec.rb +55 -0
  298. data/spec/lib/hamster/vector/each_index_spec.rb +41 -0
  299. data/spec/lib/hamster/vector/each_spec.rb +47 -0
  300. data/spec/lib/hamster/vector/each_with_index_spec.rb +40 -0
  301. data/spec/lib/hamster/vector/empty_spec.rb +44 -0
  302. data/spec/lib/hamster/vector/eql_spec.rb +77 -0
  303. data/spec/lib/hamster/vector/exist_spec.rb +4 -4
  304. data/spec/lib/hamster/vector/exists_spec.rb +4 -4
  305. data/spec/lib/hamster/vector/fetch_spec.rb +65 -0
  306. data/spec/lib/hamster/vector/fill_spec.rb +89 -0
  307. data/spec/lib/hamster/vector/filter_spec.rb +64 -0
  308. data/spec/{hamster → lib/hamster}/vector/first_spec.rb +2 -6
  309. data/spec/lib/hamster/vector/flatten_spec.rb +44 -0
  310. data/spec/lib/hamster/vector/get_spec.rb +75 -0
  311. data/spec/lib/hamster/vector/group_by_spec.rb +58 -0
  312. data/spec/{hamster → lib/hamster}/vector/include_spec.rb +2 -6
  313. data/spec/lib/hamster/vector/insert_spec.rb +69 -0
  314. data/spec/lib/hamster/vector/inspect_spec.rb +50 -0
  315. data/spec/{hamster/set → lib/hamster/vector}/join_spec.rb +23 -18
  316. data/spec/{hamster → lib/hamster}/vector/last_spec.rb +12 -3
  317. data/spec/{hamster → lib/hamster}/vector/length_spec.rb +12 -3
  318. data/spec/lib/hamster/vector/ltlt_spec.rb +20 -2
  319. data/spec/lib/hamster/vector/map_spec.rb +52 -0
  320. data/spec/lib/hamster/vector/marshal_spec.rb +32 -0
  321. data/spec/lib/hamster/vector/maximum_spec.rb +36 -0
  322. data/spec/lib/hamster/vector/minimum_spec.rb +36 -0
  323. data/spec/lib/hamster/vector/multiply_spec.rb +48 -0
  324. data/spec/lib/hamster/vector/new_spec.rb +51 -0
  325. data/spec/lib/hamster/vector/partition_spec.rb +53 -0
  326. data/spec/lib/hamster/vector/permutation_spec.rb +92 -0
  327. data/spec/lib/hamster/vector/pop_spec.rb +27 -0
  328. data/spec/lib/hamster/vector/product_spec.rb +71 -0
  329. data/spec/lib/hamster/vector/reduce_spec.rb +108 -0
  330. data/spec/lib/hamster/vector/remove_spec.rb +44 -0
  331. data/spec/lib/hamster/vector/repeated_combination_spec.rb +78 -0
  332. data/spec/lib/hamster/vector/repeated_permutation_spec.rb +94 -0
  333. data/spec/lib/hamster/vector/reverse_each_spec.rb +32 -0
  334. data/spec/lib/hamster/vector/reverse_spec.rb +22 -0
  335. data/spec/lib/hamster/vector/rindex_spec.rb +37 -0
  336. data/spec/lib/hamster/vector/rotate_spec.rb +74 -0
  337. data/spec/lib/hamster/vector/sample_spec.rb +14 -0
  338. data/spec/{hamster → lib/hamster}/vector/set_spec.rb +48 -14
  339. data/spec/lib/hamster/vector/shift_spec.rb +28 -0
  340. data/spec/lib/hamster/vector/shuffle_spec.rb +44 -0
  341. data/spec/lib/hamster/vector/slice_spec.rb +241 -0
  342. data/spec/lib/hamster/vector/sorting_spec.rb +57 -0
  343. data/spec/{hamster/set → lib/hamster/vector}/sum_spec.rb +3 -9
  344. data/spec/lib/hamster/vector/take_spec.rb +29 -0
  345. data/spec/lib/hamster/vector/take_while_spec.rb +35 -0
  346. data/spec/{hamster → lib/hamster}/vector/to_a_spec.rb +11 -12
  347. data/spec/{hamster → lib/hamster}/vector/to_ary_spec.rb +0 -0
  348. data/spec/{hamster/set → lib/hamster/vector}/to_list_spec.rb +7 -12
  349. data/spec/lib/hamster/vector/to_set_spec.rb +23 -0
  350. data/spec/lib/hamster/vector/transpose_spec.rb +49 -0
  351. data/spec/lib/hamster/vector/uniq_spec.rb +56 -0
  352. data/spec/lib/hamster/vector/unshift_spec.rb +29 -0
  353. data/spec/lib/hamster/vector/values_at_spec.rb +34 -0
  354. data/spec/lib/hamster/vector/zip_spec.rb +58 -0
  355. data/spec/spec_helper.rb +34 -1
  356. metadata +684 -467
  357. data/lib/hamster/core_ext/enumerator.rb +0 -16
  358. data/lib/hamster/experimental/mutable_stack.rb +0 -30
  359. data/lib/hamster/groupable.rb +0 -12
  360. data/lib/hamster/queue.rb +0 -86
  361. data/lib/hamster/sorter.rb +0 -25
  362. data/lib/hamster/stack.rb +0 -77
  363. data/lib/hamster/tuple.rb +0 -24
  364. data/spec/hamster/core_ext/enumerator_spec.rb +0 -19
  365. data/spec/hamster/experimental/mutable_stack/pop_spec.rb +0 -35
  366. data/spec/hamster/experimental/mutable_stack/push_spec.rb +0 -21
  367. data/spec/hamster/hash/any_spec.rb +0 -52
  368. data/spec/hamster/hash/clear_spec.rb +0 -29
  369. data/spec/hamster/hash/construction_spec.rb +0 -27
  370. data/spec/hamster/hash/delete_spec.rb +0 -38
  371. data/spec/hamster/hash/each_spec.rb +0 -30
  372. data/spec/hamster/hash/empty_spec.rb +0 -27
  373. data/spec/hamster/hash/eql_spec.rb +0 -70
  374. data/spec/hamster/hash/except_spec.rb +0 -22
  375. data/spec/hamster/hash/fetch_spec.rb +0 -72
  376. data/spec/hamster/hash/filter_spec.rb +0 -48
  377. data/spec/hamster/hash/find_spec.rb +0 -45
  378. data/spec/hamster/hash/get_spec.rb +0 -55
  379. data/spec/hamster/hash/has_key_spec.rb +0 -26
  380. data/spec/hamster/hash/inspect_spec.rb +0 -24
  381. data/spec/hamster/hash/map_spec.rb +0 -49
  382. data/spec/hamster/hash/merge_spec.rb +0 -30
  383. data/spec/hamster/hash/new_spec.rb +0 -21
  384. data/spec/hamster/hash/put_spec.rb +0 -67
  385. data/spec/hamster/hash/reduce_spec.rb +0 -52
  386. data/spec/hamster/hash/remove_spec.rb +0 -48
  387. data/spec/hamster/hash/slice_spec.rb +0 -26
  388. data/spec/hamster/hash/values_spec.rb +0 -29
  389. data/spec/hamster/list/add_spec.rb +0 -11
  390. data/spec/hamster/list/all_spec.rb +0 -84
  391. data/spec/hamster/list/at_spec.rb +0 -37
  392. data/spec/hamster/list/break_spec.rb +0 -73
  393. data/spec/hamster/list/combinations_spec.rb +0 -41
  394. data/spec/hamster/list/construction_spec.rb +0 -137
  395. data/spec/hamster/list/count_spec.rb +0 -52
  396. data/spec/hamster/list/cycle_spec.rb +0 -36
  397. data/spec/hamster/list/drop_while_spec.rb +0 -47
  398. data/spec/hamster/list/each_slice_spec.rb +0 -64
  399. data/spec/hamster/list/each_spec.rb +0 -56
  400. data/spec/hamster/list/each_with_index_spec.rb +0 -33
  401. data/spec/hamster/list/inits_spec.rb +0 -34
  402. data/spec/hamster/list/inspect_spec.rb +0 -33
  403. data/spec/hamster/list/join_spec.rb +0 -64
  404. data/spec/hamster/list/last_spec.rb +0 -34
  405. data/spec/hamster/list/maximum_spec.rb +0 -58
  406. data/spec/hamster/list/minimum_spec.rb +0 -58
  407. data/spec/hamster/list/partition_spec.rb +0 -63
  408. data/spec/hamster/list/product_spec.rb +0 -34
  409. data/spec/hamster/list/reduce_spec.rb +0 -72
  410. data/spec/hamster/list/slice_spec.rb +0 -40
  411. data/spec/hamster/list/span_spec.rb +0 -75
  412. data/spec/hamster/list/sum_spec.rb +0 -34
  413. data/spec/hamster/list/tail_spec.rb +0 -38
  414. data/spec/hamster/list/tails_spec.rb +0 -34
  415. data/spec/hamster/list/to_a_spec.rb +0 -42
  416. data/spec/hamster/queue/clear_spec.rb +0 -28
  417. data/spec/hamster/queue/construction_spec.rb +0 -34
  418. data/spec/hamster/queue/dequeue_spec.rb +0 -30
  419. data/spec/hamster/queue/empty_spec.rb +0 -35
  420. data/spec/hamster/queue/head_spec.rb +0 -25
  421. data/spec/hamster/queue/inspect_spec.rb +0 -23
  422. data/spec/hamster/queue/to_a_spec.rb +0 -32
  423. data/spec/hamster/queue/to_list_spec.rb +0 -34
  424. data/spec/hamster/set/add_spec.rb +0 -40
  425. data/spec/hamster/set/delete_spec.rb +0 -38
  426. data/spec/hamster/set/empty_spec.rb +0 -25
  427. data/spec/hamster/set/filter_spec.rb +0 -72
  428. data/spec/hamster/set/flatten_spec.rb +0 -47
  429. data/spec/hamster/set/group_by_spec.rb +0 -56
  430. data/spec/hamster/set/hash_spec.rb +0 -20
  431. data/spec/hamster/set/head_spec.rb +0 -28
  432. data/spec/hamster/set/include_spec.rb +0 -27
  433. data/spec/hamster/set/inspect_spec.rb +0 -24
  434. data/spec/hamster/set/intersection_spec.rb +0 -36
  435. data/spec/hamster/set/map_spec.rb +0 -49
  436. data/spec/hamster/set/new_spec.rb +0 -21
  437. data/spec/hamster/set/partition_spec.rb +0 -59
  438. data/spec/hamster/set/reduce_spec.rb +0 -62
  439. data/spec/hamster/set/remove_spec.rb +0 -48
  440. data/spec/hamster/set/subset_spec.rb +0 -31
  441. data/spec/hamster/set/superset_spec.rb +0 -31
  442. data/spec/hamster/set/to_a_spec.rb +0 -32
  443. data/spec/hamster/set/union_spec.rb +0 -35
  444. data/spec/hamster/sorter/immutable_spec.rb +0 -9
  445. data/spec/hamster/stack/clear_spec.rb +0 -28
  446. data/spec/hamster/stack/construction_spec.rb +0 -34
  447. data/spec/hamster/stack/copying_spec.rb +0 -23
  448. data/spec/hamster/stack/empty_spec.rb +0 -23
  449. data/spec/hamster/stack/eql_spec.rb +0 -48
  450. data/spec/hamster/stack/immutable_spec.rb +0 -9
  451. data/spec/hamster/stack/inspect_spec.rb +0 -23
  452. data/spec/hamster/stack/peek_spec.rb +0 -30
  453. data/spec/hamster/stack/pop_spec.rb +0 -31
  454. data/spec/hamster/stack/push_spec.rb +0 -31
  455. data/spec/hamster/stack/size_spec.rb +0 -25
  456. data/spec/hamster/stack/to_a_spec.rb +0 -32
  457. data/spec/hamster/stack/to_ary.rb +0 -37
  458. data/spec/hamster/stack/to_list_spec.rb +0 -25
  459. data/spec/hamster/trie/remove_spec.rb +0 -117
  460. data/spec/hamster/tuple/construction_spec.rb +0 -30
  461. data/spec/hamster/tuple/copying_spec.rb +0 -17
  462. data/spec/hamster/tuple/eql_spec.rb +0 -78
  463. data/spec/hamster/tuple/first_spec.rb +0 -14
  464. data/spec/hamster/tuple/immutable_spec.rb +0 -9
  465. data/spec/hamster/tuple/inspect_spec.rb +0 -14
  466. data/spec/hamster/tuple/last_spec.rb +0 -14
  467. data/spec/hamster/tuple/to_a_spec.rb +0 -30
  468. data/spec/hamster/tuple/to_ary_spec.rb +0 -37
  469. data/spec/hamster/undefined/erase_spec.rb +0 -36
  470. data/spec/hamster/vector/add_spec.rb +0 -56
  471. data/spec/hamster/vector/clear_spec.rb +0 -28
  472. data/spec/hamster/vector/each_spec.rb +0 -35
  473. data/spec/hamster/vector/each_with_index_spec.rb +0 -33
  474. data/spec/hamster/vector/empty_spec.rb +0 -32
  475. data/spec/hamster/vector/eql_spec.rb +0 -53
  476. data/spec/hamster/vector/filter_spec.rb +0 -58
  477. data/spec/hamster/vector/get_spec.rb +0 -58
  478. data/spec/hamster/vector/inspect_spec.rb +0 -33
  479. data/spec/hamster/vector/map_spec.rb +0 -57
  480. data/spec/hamster/vector/new_spec.rb +0 -48
  481. data/spec/hamster/vector/reduce_spec.rb +0 -62
  482. data/spec/lib/hamster/vector/cons_spec.rb +0 -48
@@ -2,6 +2,7 @@ require "forwardable"
2
2
  require "thread"
3
3
 
4
4
  module Hamster
5
+ # @private
5
6
  module ReadCopyUpdate
6
7
  extend Forwardable
7
8
 
@@ -2,122 +2,293 @@ require "forwardable"
2
2
  require "hamster/immutable"
3
3
  require "hamster/undefined"
4
4
  require "hamster/enumerable"
5
- require "hamster/groupable"
6
- require "hamster/sorter"
7
5
  require "hamster/trie"
8
- require "hamster/list"
6
+ require "hamster/sorted_set"
9
7
 
10
8
  module Hamster
11
9
  def self.set(*items)
12
- Set.new(*items)
10
+ items.empty? ? EmptySet : Set.new(items)
13
11
  end
14
12
 
13
+ # `Hamster::Set` is a collection of unordered values with no duplicates. Testing whether
14
+ # an object is present in the `Set` is fast. `Set` is also `Enumerable`, so you can
15
+ # iterate over the members of the set with {#each}, transform them with {#map}, filter
16
+ # them with {#select}, and so on. Some of the `Enumerable` methods are overridden to
17
+ # return Hamster collections.
18
+ #
19
+ # Like the `Set` class in Ruby's standard library, which we will call RubySet,
20
+ # `Hamster::Set` defines equivalency of objects using `#hash` and `#eql?`. No two
21
+ # objects with the same `#hash` code, and which are also `#eql?`, can coexist in the
22
+ # same `Set`. If one is already in the `Set`, attempts to add another one will have
23
+ # no effect.
24
+ #
25
+ # `Set`s have no natural ordering and cannot be compared using `#<=>`. However, they
26
+ # define {#<}, {#>}, {#<=}, and {#>=} as shorthand for {#proper_subset?},
27
+ # {#proper_superset?}, {#subset?}, and {#superset?} (respectively).
28
+ #
29
+ # The basic set-theoretic operations {#union}, {#intersection}, {#difference}, and
30
+ # {#exclusion} work with any `Enumerable` object. They may be more efficient when used
31
+ # with another `Hamster::Set`, or a RubySet.
32
+ #
33
+ # A `Set` can be created in any of the following ways:
34
+ #
35
+ # Hamster.set('Tom', 'Dick', 'Harry')
36
+ # Hamster::Set.new([1, 2, 3]) # any Enumerable can be used to initialize
37
+ # Hamster::Set['A', 'B', 'C', 'D']
38
+ #
39
+ # The latter 2 forms of initialization can be used with your own, custom subclasses
40
+ # of `Hamster::Set`.
41
+ #
42
+ # Unlike RubySet, all methods which you might expect to "modify" a `Hamster::Set`
43
+ # actually return a new set and leave the existing one unchanged.
44
+ #
45
+ # @example
46
+ # require 'hamster/set'
47
+ # set1 = Hamster.set(1, 2) # => Hamster::Set[1, 2]
48
+ # set2 = Hamster::Set[1, 2] # => Hamster::Set[1, 2]
49
+ # set1 == set2 # => true
50
+ # set3 = set1.add("foo") # => Hamster::Set[1, 2, "foo"]
51
+ # set3 - set2 # => Hamster::Set["foo"]
52
+ # set3.subset?(set1) # => false
53
+ # set1.subset?(set3) # => true
54
+ #
15
55
  class Set
16
56
  extend Forwardable
17
57
  include Immutable
18
58
  include Enumerable
19
- include Groupable
20
59
 
21
60
  class << self
22
- alias :alloc :new
23
-
24
- def new(*items)
25
- items.empty? ? empty : alloc(Trie[items.map! { |x| [x, nil] }])
61
+ # Create a new `Set` populated with the given items.
62
+ # @return [Set]
63
+ def [](*items)
64
+ new(items)
26
65
  end
27
66
 
67
+ # Return an empty `Set`. If used on a subclass, returns an empty instance
68
+ # of that class.
69
+ #
70
+ # @return [Set]
28
71
  def empty
29
- @empty ||= self.alloc
72
+ @empty ||= self.new
73
+ end
74
+
75
+ # "Raw" allocation of a new `Set`. Used internally to create a new
76
+ # instance quickly after obtaining a modified {Trie}.
77
+ #
78
+ # @return [Set]
79
+ # @private
80
+ def alloc(trie = EmptyTrie)
81
+ allocate.tap { |s| s.instance_variable_set(:@trie, trie) }
30
82
  end
31
83
  end
32
84
 
33
- def initialize(trie = EmptyTrie)
34
- @trie = trie
85
+ def initialize(items=[])
86
+ @trie = Trie.new(0)
87
+ items.each { |item| @trie.put!(item, nil) }
35
88
  end
36
89
 
90
+ # Return `true` if this `Set` contains no items.
91
+ # @return [Boolean]
37
92
  def empty?
38
93
  @trie.empty?
39
94
  end
40
95
  def_delegator :self, :empty?, :null?
41
96
 
97
+ # Return the number of items in this `Set`.
98
+ # @return [Integer]
42
99
  def size
43
100
  @trie.size
44
101
  end
45
102
  def_delegator :self, :size, :length
46
103
 
104
+ # Return a new `Set` with `item` added. If `item` is already in the set,
105
+ # return `self`.
106
+ #
107
+ # @param item [Object] The object to add
108
+ # @return [Set]
47
109
  def add(item)
48
- transform_unless(include?(item)) { @trie = @trie.put(item, nil) }
110
+ include?(item) ? self : self.class.alloc(@trie.put(item, nil))
49
111
  end
50
112
  def_delegator :self, :add, :<<
51
113
  def_delegator :self, :add, :conj
52
114
  def_delegator :self, :add, :conjoin
53
115
 
116
+ # If `item` is not a member of this `Set`, return a new `Set` with `item` added.
117
+ # Otherwise, return `false`.
118
+ #
119
+ # @param item [Object] The object to add
120
+ # @return [Set, false]
121
+ def add?(item)
122
+ !include?(item) && add(item)
123
+ end
124
+
125
+ # Return a new `Set` with `item` removed. If `item` is not a member of the set,
126
+ # return `self`.
127
+ #
128
+ # @param item [Object] The object to remove
129
+ # @return [Set]
54
130
  def delete(item)
55
131
  trie = @trie.delete(item)
56
- transform_unless(trie.equal?(@trie)) { @trie = trie }
132
+ if trie.equal?(@trie)
133
+ self
134
+ elsif trie.empty?
135
+ self.class.empty
136
+ else
137
+ self.class.alloc(trie)
138
+ end
139
+ end
140
+
141
+ # If `item` is a member of this `Set`, return a new `Set` with `item` removed.
142
+ # Otherwise, return `false`.
143
+ #
144
+ # @param item [Object] The object to remove
145
+ # @return [Set, false]
146
+ def delete?(item)
147
+ include?(item) && delete(item)
57
148
  end
58
149
 
150
+ # Call the block once for each item in this `Set`. No specific iteration order
151
+ # is guaranteed (but the order will be stable for any particular `Set`.)
152
+ #
153
+ # @return [self]
59
154
  def each
60
- return self unless block_given?
61
- @trie.each { |entry| yield(entry.key) }
155
+ return to_enum if not block_given?
156
+ @trie.each { |key, _| yield(key) }
157
+ self
62
158
  end
63
159
 
64
- def map
65
- return self unless block_given?
66
- return self if empty?
67
- transform { @trie = @trie.reduce(EmptyTrie) { |trie, entry| trie.put(yield(entry.key), nil) } }
160
+ # Call the block once for each item in this `Set`. Iteration order will be
161
+ # the opposite of {#each}.
162
+ #
163
+ # @return [self]
164
+ def reverse_each
165
+ return enum_for(:reverse_each) if not block_given?
166
+ @trie.reverse_each { |key, _| yield(key) }
167
+ self
68
168
  end
69
- def_delegator :self, :map, :collect
70
169
 
170
+ # Return a new `Set` with all the items for which the block returns true.
171
+ #
172
+ # @return [Set]
71
173
  def filter
72
- return self unless block_given?
73
- trie = @trie.filter { |entry| yield(entry.key) }
174
+ return enum_for(:filter) unless block_given?
175
+ trie = @trie.filter { |entry| yield(entry[0]) }
74
176
  return self.class.empty if trie.empty?
75
- transform_unless(trie.equal?(@trie)) { @trie = trie }
177
+ trie.equal?(@trie) ? self : self.class.alloc(trie)
178
+ end
179
+
180
+ def_delegator :self, :reduce, :foldr # set is not ordered, so foldr is same as reduce
181
+
182
+ # Call the block once for each item in this `Set`.
183
+ # All the values returned from the block will be gathered into a new `Set`.
184
+ #
185
+ # @return [Set]
186
+ def map
187
+ return enum_for(:map) if not block_given?
188
+ return self if empty?
189
+ self.class.new(super)
76
190
  end
191
+ def_delegator :self, :map, :collect
77
192
 
193
+ # Return `true` if the given item is present in this `Set`. More precisely,
194
+ # return `true` if an object with the same `#hash` code, and which is also `#eql?`
195
+ # to the given object is present.
196
+ #
197
+ # @param object [Object] The object to check for
198
+ # @return [Boolean]
78
199
  def include?(object)
79
200
  @trie.key?(object)
80
201
  end
81
-
82
- def head
83
- find { true }
202
+ def_delegator :self, :include?, :member?
203
+
204
+ # Return a member of this `Set`. The member chosen will be the first one which
205
+ # would be yielded by {#each}. If the set is empty, return `nil`.
206
+ #
207
+ # @return [Object]
208
+ def first
209
+ (entry = @trie.at(0)) && entry[0]
84
210
  end
85
- def_delegator :self, :head, :first
86
-
211
+ def_delegator :self, :first, :head
212
+
213
+ # Return a {SortedSet} which contains the same items as this `Set`, ordered by
214
+ # the given comparator block. The comparator block should take 2 parameters and
215
+ # return 0, 1, or -1 depending on whether the first parameter is equal, greater than,
216
+ # or less than the second.
217
+ #
218
+ # @yield [a, b] A pair of items to be compared
219
+ # @yieldreturn [Integer]
220
+ # @return [SortedSet]
87
221
  def sort(&comparator)
88
- Stream.new { Sorter.new(self).sort(&comparator) }
222
+ SortedSet.new(self.to_a, &comparator)
89
223
  end
90
224
 
91
- def sort_by(&transformer)
92
- return sort unless block_given?
93
- Stream.new { Sorter.new(self).sort_by(&transformer) }
94
- end
95
-
96
- def join(sep = nil)
97
- to_a.join(sep)
225
+ # Return a {SortedSet} which contains the same items as this `Set`, ordered by
226
+ # mapping each item through the provided block to obtain sort keys, and then
227
+ # sorting the keys.
228
+ #
229
+ # @yield [item] The item to obtain a sort key for
230
+ # @yieldreturn [Object]
231
+ # @return [SortedSet]
232
+ def sort_by(&mapper)
233
+ SortedSet.new(self.to_a, &mapper)
98
234
  end
99
235
 
236
+ # Return a new `Set` which contains all the members of both this `Set` and `other`.
237
+ # `other` can be any `Enumerable` object.
238
+ #
239
+ # @example
240
+ # Hamster::Set[1, 2] | Hamster::Set[2, 3] # => Hamster::Set[1, 2, 3]
241
+ #
242
+ # @param other [Enumerable] The collection to merge with
243
+ # @return [Set]
100
244
  def union(other)
101
- trie = other.reduce(@trie) do |a, element|
245
+ if other.is_a?(Hamster::Set) && other.size > size
246
+ small_set = self
247
+ large_set_trie = other.instance_variable_get(:@trie)
248
+ else
249
+ small_set = other
250
+ large_set_trie = @trie
251
+ end
252
+ trie = small_set.reduce(large_set_trie) do |a, element|
102
253
  next a if a.key?(element)
103
254
  a.put(element, nil)
104
255
  end
105
- transform_unless(trie.equal?(@trie)) { @trie = trie }
256
+ trie.equal?(@trie) ? self : self.class.alloc(trie)
106
257
  end
107
258
  def_delegator :self, :union, :|
108
259
  def_delegator :self, :union, :+
109
260
  def_delegator :self, :union, :merge
110
261
 
262
+ # Return a new `Set` which contains all the items which are members of both
263
+ # this `Set` and `other`. `other` can be any `Enumerable` object.
264
+ #
265
+ # @example
266
+ # Hamster::Set[1, 2] & Hamster::Set[2, 3] # => Hamster::Set[2]
267
+ #
268
+ # @param other [Enumerable] The collection to intersect with
269
+ # @return [Set]
111
270
  def intersection(other)
112
- trie = @trie.filter { |entry| other.include?(entry.key) }
113
- transform_unless(trie.equal?(@trie)) { @trie = trie }
271
+ if (other.size < @trie.size) && other.is_a?(Hamster::Set)
272
+ trie = other.instance_variable_get(:@trie).filter { |key, _| include?(key) }
273
+ else
274
+ trie = @trie.filter { |key, _| other.include?(key) }
275
+ end
276
+ trie.equal?(@trie) ? self : self.class.alloc(trie)
114
277
  end
115
278
  def_delegator :self, :intersection, :intersect
116
279
  def_delegator :self, :intersection, :&
117
280
 
281
+ # Return a new `Set` with all the items in `other` removed. `other` can be
282
+ # any `Enumerable` object.
283
+ #
284
+ # @example
285
+ # Hamster::Set[1, 2] - Hamster::Set[2, 3] # => Hamster::Set[1]
286
+ #
287
+ # @param other [Enumerable] The collection to subtract from this set
288
+ # @return [Set]
118
289
  def difference(other)
119
290
  trie = if (@trie.size <= other.size) && (other.is_a?(Hamster::Set) || (defined?(::Set) && other.is_a?(::Set)))
120
- @trie.filter { |entry| !other.include?(entry.key) }
291
+ @trie.filter { |key, _| !other.include?(key) }
121
292
  else
122
293
  other.reduce(@trie) { |trie, item| trie.delete(item) }
123
294
  end
@@ -127,19 +298,88 @@ module Hamster
127
298
  def_delegator :self, :difference, :subtract
128
299
  def_delegator :self, :difference, :-
129
300
 
301
+ # Return a new `Set` which contains all the items which are members of this
302
+ # `Set` or of `other`, but not both. `other` can be any `Enumerable` object.
303
+ #
304
+ # @example
305
+ # Hamster::Set[1, 2] ^ Hamster::Set[2, 3] # => Hamster::Set[1, 3]
306
+ #
307
+ # @param other [Enumerable] The collection to take the exclusive disjunction of
308
+ # @return [Set]
130
309
  def exclusion(other)
131
310
  ((self | other) - (self & other))
132
311
  end
133
312
  def_delegator :self, :exclusion, :^
134
313
 
314
+ # Return `true` if all items in this `Set` are also in `other`.
315
+ #
316
+ # @param other [Set]
317
+ # @return [Boolean]
135
318
  def subset?(other)
319
+ return false if other.size < size
136
320
  all? { |item| other.include?(item) }
137
321
  end
322
+ alias :<= :subset?
138
323
 
324
+ # Return `true` if all items in `other` are also in this `Set`.
325
+ #
326
+ # @param other [Set]
327
+ # @return [Boolean]
139
328
  def superset?(other)
140
329
  other.subset?(self)
141
330
  end
331
+ alias :>= :superset?
332
+
333
+ # Returns `true` if `other` contains all the items in this `Set`, plus at least
334
+ # one item which is not in this set.
335
+ #
336
+ # @param other [Set]
337
+ # @return [Boolean]
338
+ def proper_subset?(other)
339
+ return false if other.size <= size
340
+ all? { |item| other.include?(item) }
341
+ end
342
+ alias :< :proper_subset?
343
+
344
+ # Returns `true` if this `Set` contains all the items in `other`, plus at least
345
+ # one item which is not in `other`.
346
+ #
347
+ # @param other [Set]
348
+ # @return [Boolean]
349
+ def proper_superset?(other)
350
+ other.proper_subset?(self)
351
+ end
352
+ alias :> :proper_superset?
353
+
354
+ # Return `true` if this `Set` and `other` do not share any items.
355
+ #
356
+ # @param other [Set]
357
+ # @return [Boolean]
358
+ def disjoint?(other)
359
+ if size < other.size
360
+ each { |item| return false if other.include?(item) }
361
+ else
362
+ other.each { |item| return false if include?(item) }
363
+ end
364
+ true
365
+ end
142
366
 
367
+ # Return `true` if this `Set` and `other` have at least one item in common.
368
+ #
369
+ # @param other [Set]
370
+ # @return [Boolean]
371
+ def intersect?(other)
372
+ !disjoint?(other)
373
+ end
374
+
375
+ # Recursively insert the contents of any nested `Set`s into this `Set`, and
376
+ # remove them.
377
+ #
378
+ # @example
379
+ # Hamster::Set[Hamster::Set[1, 2], Hamster::Set[3, 4]].flatten
380
+ # # => Hamster::Set[1, 2, 3, 4]
381
+ #
382
+ # @return [Set]
143
383
  def flatten
144
384
  reduce(self.class.empty) do |set, item|
145
385
  next set.union(item.flatten) if item.is_a?(Set)
@@ -147,43 +387,61 @@ module Hamster
147
387
  end
148
388
  end
149
389
 
150
- def group_by(&block)
151
- group_by_with(self.class.empty, &block)
152
- end
153
390
  def_delegator :self, :group_by, :group
391
+ def_delegator :self, :group_by, :classify
154
392
 
393
+ # Return a randomly chosen item from this `Set`. If the set is empty, return `nil`.
394
+ #
395
+ # @return [Object]
396
+ def sample
397
+ empty? ? nil : @trie.at(rand(size))[0]
398
+ end
399
+
400
+ # Return an empty `Set` instance, of the same class as this one. Useful if you
401
+ # have multiple subclasses of `Set` and want to treat them polymorphically.
402
+ #
403
+ # @return [Hash]
155
404
  def clear
156
405
  self.class.empty
157
406
  end
158
407
 
408
+ # Return true if `other` has the same type and contents as this `Set`.
409
+ #
410
+ # @param other [Object] The object to compare with
411
+ # @return [Boolean]
159
412
  def eql?(other)
413
+ return true if other.equal?(self)
160
414
  return false if not instance_of?(other.class)
161
415
  other_trie = other.instance_variable_get(:@trie)
162
416
  return false if @trie.size != other_trie.size
163
- @trie.each do |entry|
164
- return false if !other_trie.key?(entry.key)
417
+ @trie.each do |key, _|
418
+ return false if !other_trie.key?(key)
165
419
  end
166
420
  true
167
421
  end
168
422
  def_delegator :self, :eql?, :==
169
423
 
424
+ # See `Object#hash`.
425
+ # @return [Integer]
170
426
  def hash
171
427
  reduce(0) { |hash, item| (hash << 5) - hash + item.hash }
172
428
  end
173
429
 
430
+ undef :"<=>" # Sets are not ordered, so Enumerable#<=> will give a meaningless result
431
+ undef :each_index # Set members cannot be accessed by 'index', so #each_index is not meaningful
432
+
174
433
  def_delegator :self, :dup, :uniq
175
434
  def_delegator :self, :dup, :nub
176
- def_delegator :self, :dup, :to_set
177
435
  def_delegator :self, :dup, :remove_duplicates
178
436
 
179
- def to_list
180
- reduce(EmptyList) { |list, item| list.cons(item) }
181
- end
182
-
183
- def inspect
184
- "{#{to_a.inspect[1..-2]}}"
437
+ # Return `self`.
438
+ #
439
+ # @return [self]
440
+ def to_set
441
+ self
185
442
  end
186
443
 
444
+ # @private
187
445
  def marshal_dump
188
446
  output = {}
189
447
  each do |key|
@@ -192,6 +450,7 @@ module Hamster
192
450
  output
193
451
  end
194
452
 
453
+ # @private
195
454
  def marshal_load(dictionary)
196
455
  @trie = dictionary.reduce(EmptyTrie) do |trie, key_value|
197
456
  trie.put(key_value.first, nil)
@@ -199,5 +458,9 @@ module Hamster
199
458
  end
200
459
  end
201
460
 
461
+ # The canonical empty `Set`. Returned by `Hamster.set` and `Set[]` when
462
+ # invoked with no arguments; also returned by `Set.empty`. Prefer using this
463
+ # one rather than creating many empty sets using `Set.new`.
464
+ #
202
465
  EmptySet = Hamster::Set.empty
203
466
  end