hamster 1.0.1.pre.rc3 → 2.0.0

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 (358) hide show
  1. checksums.yaml +4 -4
  2. data/lib/hamster.rb +2 -0
  3. data/lib/hamster/associable.rb +49 -0
  4. data/lib/hamster/core_ext/enumerable.rb +3 -13
  5. data/lib/hamster/core_ext/io.rb +1 -1
  6. data/lib/hamster/core_ext/struct.rb +9 -0
  7. data/lib/hamster/deque.rb +57 -38
  8. data/lib/hamster/enumerable.rb +14 -41
  9. data/lib/hamster/experimental/mutable_queue.rb +5 -8
  10. data/lib/hamster/experimental/mutable_set.rb +6 -7
  11. data/lib/hamster/hash.rb +301 -110
  12. data/lib/hamster/immutable.rb +1 -1
  13. data/lib/hamster/list.rb +479 -194
  14. data/lib/hamster/mutable_hash.rb +6 -7
  15. data/lib/hamster/nested.rb +78 -0
  16. data/lib/hamster/read_copy_update.rb +1 -1
  17. data/lib/hamster/set.rb +198 -88
  18. data/lib/hamster/sorted_set.rb +706 -261
  19. data/lib/hamster/trie.rb +134 -15
  20. data/lib/hamster/vector.rb +571 -140
  21. data/lib/hamster/version.rb +3 -1
  22. data/spec/lib/hamster/associable/associable_spec.rb +150 -0
  23. data/spec/lib/hamster/core_ext/array_spec.rb +1 -1
  24. data/spec/lib/hamster/core_ext/enumerable_spec.rb +2 -2
  25. data/spec/lib/hamster/core_ext/io_spec.rb +1 -1
  26. data/spec/lib/hamster/deque/clear_spec.rb +3 -3
  27. data/spec/lib/hamster/deque/construction_spec.rb +8 -8
  28. data/spec/lib/hamster/deque/copying_spec.rb +1 -1
  29. data/spec/lib/hamster/deque/dequeue_spec.rb +12 -4
  30. data/spec/lib/hamster/deque/empty_spec.rb +14 -16
  31. data/spec/lib/hamster/deque/enqueue_spec.rb +4 -4
  32. data/spec/lib/hamster/deque/first_spec.rb +18 -0
  33. data/spec/lib/hamster/deque/inspect_spec.rb +1 -1
  34. data/spec/lib/hamster/deque/last_spec.rb +9 -11
  35. data/spec/lib/hamster/deque/marshal_spec.rb +6 -6
  36. data/spec/lib/hamster/deque/new_spec.rb +5 -5
  37. data/spec/lib/hamster/deque/pop_spec.rb +15 -3
  38. data/spec/lib/hamster/deque/pretty_print_spec.rb +24 -0
  39. data/spec/lib/hamster/deque/push_spec.rb +37 -0
  40. data/spec/lib/hamster/deque/shift_spec.rb +30 -0
  41. data/spec/lib/hamster/deque/size_spec.rb +1 -1
  42. data/spec/lib/hamster/deque/to_a_spec.rb +2 -2
  43. data/spec/lib/hamster/deque/to_ary_spec.rb +1 -1
  44. data/spec/lib/hamster/deque/to_list_spec.rb +3 -3
  45. data/spec/lib/hamster/deque/unshift_spec.rb +8 -3
  46. data/spec/lib/hamster/experimental/mutable_set/add_qm_spec.rb +3 -3
  47. data/spec/lib/hamster/experimental/mutable_set/add_spec.rb +3 -3
  48. data/spec/lib/hamster/experimental/mutable_set/delete_qm_spec.rb +3 -3
  49. data/spec/lib/hamster/experimental/mutable_set/delete_spec.rb +3 -3
  50. data/spec/lib/hamster/hash/all_spec.rb +32 -34
  51. data/spec/lib/hamster/hash/any_spec.rb +34 -36
  52. data/spec/lib/hamster/hash/assoc_spec.rb +3 -3
  53. data/spec/lib/hamster/hash/clear_spec.rb +4 -4
  54. data/spec/lib/hamster/hash/construction_spec.rb +8 -8
  55. data/spec/lib/hamster/hash/copying_spec.rb +1 -1
  56. data/spec/lib/hamster/hash/default_proc_spec.rb +3 -3
  57. data/spec/lib/hamster/hash/delete_spec.rb +4 -4
  58. data/spec/lib/hamster/hash/each_spec.rb +3 -3
  59. data/spec/lib/hamster/hash/each_with_index_spec.rb +1 -1
  60. data/spec/lib/hamster/hash/empty_spec.rb +13 -15
  61. data/spec/lib/hamster/hash/eql_spec.rb +4 -4
  62. data/spec/lib/hamster/hash/except_spec.rb +7 -7
  63. data/spec/lib/hamster/hash/fetch_spec.rb +10 -10
  64. data/spec/lib/hamster/hash/find_spec.rb +2 -2
  65. data/spec/lib/hamster/hash/flat_map_spec.rb +4 -4
  66. data/spec/lib/hamster/hash/flatten_spec.rb +13 -13
  67. data/spec/lib/hamster/hash/get_spec.rb +7 -7
  68. data/spec/lib/hamster/hash/has_key_spec.rb +3 -3
  69. data/spec/lib/hamster/hash/has_value_spec.rb +4 -4
  70. data/spec/lib/hamster/hash/hash_spec.rb +5 -5
  71. data/spec/lib/hamster/hash/inspect_spec.rb +2 -2
  72. data/spec/lib/hamster/hash/invert_spec.rb +6 -6
  73. data/spec/lib/hamster/hash/key_spec.rb +2 -2
  74. data/spec/lib/hamster/hash/keys_spec.rb +2 -2
  75. data/spec/lib/hamster/hash/map_spec.rb +4 -4
  76. data/spec/lib/hamster/hash/marshal_spec.rb +2 -2
  77. data/spec/lib/hamster/hash/merge_spec.rb +62 -56
  78. data/spec/lib/hamster/hash/min_max_spec.rb +9 -13
  79. data/spec/lib/hamster/hash/new_spec.rb +6 -6
  80. data/spec/lib/hamster/hash/none_spec.rb +3 -3
  81. data/spec/lib/hamster/hash/partition_spec.rb +2 -2
  82. data/spec/lib/hamster/hash/put_spec.rb +29 -7
  83. data/spec/lib/hamster/hash/reduce_spec.rb +4 -4
  84. data/spec/lib/hamster/hash/{remove_spec.rb → reject_spec.rb} +7 -7
  85. data/spec/lib/hamster/hash/reverse_each_spec.rb +1 -1
  86. data/spec/lib/hamster/hash/{filter_spec.rb → select_spec.rb} +6 -6
  87. data/spec/lib/hamster/hash/size_spec.rb +3 -3
  88. data/spec/lib/hamster/hash/slice_spec.rb +4 -4
  89. data/spec/lib/hamster/hash/sort_spec.rb +2 -2
  90. data/spec/lib/hamster/hash/store_spec.rb +29 -7
  91. data/spec/lib/hamster/hash/take_spec.rb +2 -2
  92. data/spec/lib/hamster/hash/to_a_spec.rb +1 -1
  93. data/spec/lib/hamster/hash/to_hash_spec.rb +4 -4
  94. data/spec/lib/hamster/hash/values_at_spec.rb +3 -3
  95. data/spec/lib/hamster/hash/values_spec.rb +2 -2
  96. data/spec/lib/hamster/immutable/new_spec.rb +14 -0
  97. data/spec/lib/hamster/list/add_spec.rb +16 -10
  98. data/spec/lib/hamster/list/all_spec.rb +33 -35
  99. data/spec/lib/hamster/list/any_spec.rb +29 -31
  100. data/spec/lib/hamster/list/append_spec.rb +6 -6
  101. data/spec/lib/hamster/list/at_spec.rb +1 -1
  102. data/spec/lib/hamster/list/break_spec.rb +4 -4
  103. data/spec/lib/hamster/list/cadr_spec.rb +9 -9
  104. data/spec/lib/hamster/list/chunk_spec.rb +5 -5
  105. data/spec/lib/hamster/list/clear_spec.rb +3 -3
  106. data/spec/lib/hamster/list/combination_spec.rb +3 -3
  107. data/spec/lib/hamster/list/compact_spec.rb +3 -3
  108. data/spec/lib/hamster/list/compare_spec.rb +3 -3
  109. data/spec/lib/hamster/list/cons_spec.rb +15 -17
  110. data/spec/lib/hamster/list/construction_spec.rb +20 -27
  111. data/spec/lib/hamster/list/copying_spec.rb +1 -1
  112. data/spec/lib/hamster/list/count_spec.rb +1 -1
  113. data/spec/lib/hamster/list/cycle_spec.rb +4 -4
  114. data/spec/lib/hamster/list/delete_at_spec.rb +4 -4
  115. data/spec/lib/hamster/list/drop_spec.rb +3 -3
  116. data/spec/lib/hamster/list/drop_while_spec.rb +3 -3
  117. data/spec/lib/hamster/list/each_slice_spec.rb +5 -5
  118. data/spec/lib/hamster/list/each_spec.rb +26 -28
  119. data/spec/lib/hamster/list/each_with_index_spec.rb +1 -1
  120. data/spec/lib/hamster/list/empty_spec.rb +13 -15
  121. data/spec/lib/hamster/list/eql_spec.rb +21 -21
  122. data/spec/lib/hamster/list/fill_spec.rb +8 -8
  123. data/spec/lib/hamster/list/find_all_spec.rb +3 -3
  124. data/spec/lib/hamster/list/find_index_spec.rb +1 -1
  125. data/spec/lib/hamster/list/find_spec.rb +1 -1
  126. data/spec/lib/hamster/list/flat_map_spec.rb +2 -2
  127. data/spec/lib/hamster/list/flatten_spec.rb +5 -5
  128. data/spec/lib/hamster/list/grep_spec.rb +4 -4
  129. data/spec/lib/hamster/list/group_by_spec.rb +6 -6
  130. data/spec/lib/hamster/list/hash_spec.rb +2 -2
  131. data/spec/lib/hamster/list/head_spec.rb +1 -1
  132. data/spec/lib/hamster/list/include_spec.rb +2 -2
  133. data/spec/lib/hamster/list/index_spec.rb +38 -0
  134. data/spec/lib/hamster/list/indices_spec.rb +62 -0
  135. data/spec/lib/hamster/list/init_spec.rb +3 -3
  136. data/spec/lib/hamster/list/inits_spec.rb +3 -3
  137. data/spec/lib/hamster/list/insert_spec.rb +1 -1
  138. data/spec/lib/hamster/list/inspect_spec.rb +1 -1
  139. data/spec/lib/hamster/list/intersperse_spec.rb +3 -3
  140. data/spec/lib/hamster/list/join_spec.rb +5 -5
  141. data/spec/lib/hamster/list/last_spec.rb +1 -1
  142. data/spec/lib/hamster/list/ltlt_spec.rb +20 -0
  143. data/spec/lib/hamster/list/map_spec.rb +4 -4
  144. data/spec/lib/hamster/list/maximum_spec.rb +24 -26
  145. data/spec/lib/hamster/list/merge_by_spec.rb +10 -10
  146. data/spec/lib/hamster/list/merge_spec.rb +10 -10
  147. data/spec/lib/hamster/list/minimum_spec.rb +24 -26
  148. data/spec/lib/hamster/list/multithreading_spec.rb +6 -6
  149. data/spec/lib/hamster/list/none_spec.rb +5 -5
  150. data/spec/lib/hamster/list/one_spec.rb +5 -5
  151. data/spec/lib/hamster/list/partition_spec.rb +8 -8
  152. data/spec/lib/hamster/list/permutation_spec.rb +8 -8
  153. data/spec/lib/hamster/list/pop_spec.rb +3 -3
  154. data/spec/lib/hamster/list/product_spec.rb +1 -1
  155. data/spec/lib/hamster/list/reduce_spec.rb +5 -48
  156. data/spec/lib/hamster/list/{remove_spec.rb → reject_spec.rb} +4 -4
  157. data/spec/lib/hamster/list/reverse_spec.rb +3 -3
  158. data/spec/lib/hamster/list/rotate_spec.rb +7 -7
  159. data/spec/lib/hamster/list/sample_spec.rb +1 -1
  160. data/spec/lib/hamster/list/select_spec.rb +3 -3
  161. data/spec/lib/hamster/list/size_spec.rb +1 -1
  162. data/spec/lib/hamster/list/slice_spec.rb +123 -123
  163. data/spec/lib/hamster/list/sorting_spec.rb +5 -5
  164. data/spec/lib/hamster/list/span_spec.rb +5 -5
  165. data/spec/lib/hamster/list/split_at_spec.rb +4 -4
  166. data/spec/lib/hamster/list/subsequences_spec.rb +1 -1
  167. data/spec/lib/hamster/list/sum_spec.rb +1 -1
  168. data/spec/lib/hamster/list/tail_spec.rb +4 -4
  169. data/spec/lib/hamster/list/tails_spec.rb +3 -3
  170. data/spec/lib/hamster/list/take_spec.rb +3 -3
  171. data/spec/lib/hamster/list/take_while_spec.rb +4 -4
  172. data/spec/lib/hamster/list/to_a_spec.rb +2 -2
  173. data/spec/lib/hamster/list/to_ary_spec.rb +1 -1
  174. data/spec/lib/hamster/list/to_list_spec.rb +1 -1
  175. data/spec/lib/hamster/list/to_set_spec.rb +1 -1
  176. data/spec/lib/hamster/list/union_spec.rb +4 -4
  177. data/spec/lib/hamster/list/uniq_spec.rb +23 -19
  178. data/spec/lib/hamster/list/zip_spec.rb +5 -5
  179. data/spec/lib/hamster/nested/construction_spec.rb +103 -0
  180. data/spec/lib/hamster/set/add_spec.rb +13 -11
  181. data/spec/lib/hamster/set/all_spec.rb +32 -34
  182. data/spec/lib/hamster/set/any_spec.rb +32 -34
  183. data/spec/lib/hamster/set/clear_spec.rb +3 -3
  184. data/spec/lib/hamster/set/compact_spec.rb +3 -3
  185. data/spec/lib/hamster/set/construction_spec.rb +3 -3
  186. data/spec/lib/hamster/set/copying_spec.rb +1 -1
  187. data/spec/lib/hamster/set/count_spec.rb +1 -1
  188. data/spec/lib/hamster/set/delete_spec.rb +8 -8
  189. data/spec/lib/hamster/set/difference_spec.rb +8 -8
  190. data/spec/lib/hamster/set/disjoint_spec.rb +1 -1
  191. data/spec/lib/hamster/set/each_spec.rb +2 -2
  192. data/spec/lib/hamster/set/empty_spec.rb +15 -17
  193. data/spec/lib/hamster/set/eqeq_spec.rb +3 -3
  194. data/spec/lib/hamster/set/eql_spec.rb +3 -3
  195. data/spec/lib/hamster/set/exclusion_spec.rb +7 -7
  196. data/spec/lib/hamster/set/find_spec.rb +2 -2
  197. data/spec/lib/hamster/set/first_spec.rb +29 -0
  198. data/spec/lib/hamster/set/flatten_spec.rb +9 -9
  199. data/spec/lib/hamster/set/grep_spec.rb +1 -1
  200. data/spec/lib/hamster/set/group_by_spec.rb +12 -12
  201. data/spec/lib/hamster/set/hash_spec.rb +3 -3
  202. data/spec/lib/hamster/set/include_spec.rb +8 -8
  203. data/spec/lib/hamster/set/inspect_spec.rb +2 -2
  204. data/spec/lib/hamster/set/intersect_spec.rb +1 -1
  205. data/spec/lib/hamster/set/intersection_spec.rb +13 -13
  206. data/spec/lib/hamster/set/join_spec.rb +6 -6
  207. data/spec/lib/hamster/set/map_spec.rb +7 -7
  208. data/spec/lib/hamster/set/marshal_spec.rb +2 -2
  209. data/spec/lib/hamster/set/maximum_spec.rb +22 -24
  210. data/spec/lib/hamster/set/minimum_spec.rb +22 -24
  211. data/spec/lib/hamster/set/new_spec.rb +5 -5
  212. data/spec/lib/hamster/set/none_spec.rb +5 -5
  213. data/spec/lib/hamster/set/one_spec.rb +6 -6
  214. data/spec/lib/hamster/set/partition_spec.rb +5 -5
  215. data/spec/lib/hamster/set/product_spec.rb +2 -2
  216. data/spec/lib/hamster/set/reduce_spec.rb +5 -5
  217. data/spec/lib/hamster/set/{remove_spec.rb → reject_spec.rb} +6 -6
  218. data/spec/lib/hamster/set/reverse_each_spec.rb +1 -1
  219. data/spec/lib/hamster/set/sample_spec.rb +1 -1
  220. data/spec/lib/hamster/set/{filter_spec.rb → select_spec.rb} +11 -11
  221. data/spec/lib/hamster/set/size_spec.rb +1 -1
  222. data/spec/lib/hamster/set/sorting_spec.rb +16 -5
  223. data/spec/lib/hamster/set/subset_spec.rb +2 -2
  224. data/spec/lib/hamster/set/sum_spec.rb +2 -2
  225. data/spec/lib/hamster/set/superset_spec.rb +2 -2
  226. data/spec/lib/hamster/set/to_a_spec.rb +2 -2
  227. data/spec/lib/hamster/set/to_list_spec.rb +2 -2
  228. data/spec/lib/hamster/set/to_set_spec.rb +1 -1
  229. data/spec/lib/hamster/set/union_spec.rb +23 -14
  230. data/spec/lib/hamster/sorted_set/above_spec.rb +11 -11
  231. data/spec/lib/hamster/sorted_set/add_spec.rb +8 -8
  232. data/spec/lib/hamster/sorted_set/at_spec.rb +1 -1
  233. data/spec/lib/hamster/sorted_set/below_spec.rb +11 -11
  234. data/spec/lib/hamster/sorted_set/between_spec.rb +11 -11
  235. data/spec/lib/hamster/sorted_set/clear_spec.rb +11 -2
  236. data/spec/lib/hamster/sorted_set/copying_spec.rb +21 -0
  237. data/spec/lib/hamster/sorted_set/delete_at_spec.rb +4 -4
  238. data/spec/lib/hamster/sorted_set/delete_spec.rb +21 -12
  239. data/spec/lib/hamster/sorted_set/difference_spec.rb +2 -2
  240. data/spec/lib/hamster/sorted_set/disjoint_spec.rb +1 -1
  241. data/spec/lib/hamster/sorted_set/drop_spec.rb +30 -3
  242. data/spec/lib/hamster/sorted_set/drop_while_spec.rb +4 -4
  243. data/spec/lib/hamster/sorted_set/each_spec.rb +16 -18
  244. data/spec/lib/hamster/sorted_set/empty_spec.rb +12 -14
  245. data/spec/lib/hamster/sorted_set/eql_spec.rb +5 -5
  246. data/spec/lib/hamster/sorted_set/exclusion_spec.rb +1 -1
  247. data/spec/lib/hamster/sorted_set/fetch_spec.rb +1 -1
  248. data/spec/lib/hamster/sorted_set/find_index_spec.rb +10 -2
  249. data/spec/lib/hamster/sorted_set/first_spec.rb +10 -12
  250. data/spec/lib/hamster/sorted_set/from_spec.rb +11 -11
  251. data/spec/lib/hamster/sorted_set/group_by_spec.rb +10 -10
  252. data/spec/lib/hamster/sorted_set/include_spec.rb +2 -2
  253. data/spec/lib/hamster/sorted_set/inspect_spec.rb +1 -1
  254. data/spec/lib/hamster/sorted_set/intersect_spec.rb +1 -1
  255. data/spec/lib/hamster/sorted_set/intersection_spec.rb +3 -3
  256. data/spec/lib/hamster/sorted_set/last_spec.rb +1 -1
  257. data/spec/lib/hamster/sorted_set/map_spec.rb +13 -5
  258. data/spec/lib/hamster/sorted_set/marshal_spec.rb +3 -3
  259. data/spec/lib/hamster/sorted_set/maximum_spec.rb +37 -0
  260. data/spec/lib/hamster/sorted_set/minimum_spec.rb +11 -13
  261. data/spec/lib/hamster/sorted_set/new_spec.rb +23 -3
  262. data/spec/lib/hamster/sorted_set/reverse_each_spec.rb +2 -2
  263. data/spec/lib/hamster/sorted_set/{filter_spec.rb → select_spec.rb} +10 -10
  264. data/spec/lib/hamster/sorted_set/size_spec.rb +1 -1
  265. data/spec/lib/hamster/sorted_set/slice_spec.rb +158 -142
  266. data/spec/lib/hamster/sorted_set/sorting_spec.rb +3 -3
  267. data/spec/lib/hamster/sorted_set/subset_spec.rb +2 -2
  268. data/spec/lib/hamster/sorted_set/superset_spec.rb +2 -2
  269. data/spec/lib/hamster/sorted_set/take_spec.rb +32 -3
  270. data/spec/lib/hamster/sorted_set/take_while_spec.rb +4 -4
  271. data/spec/lib/hamster/sorted_set/to_set_spec.rb +1 -1
  272. data/spec/lib/hamster/sorted_set/union_spec.rb +2 -2
  273. data/spec/lib/hamster/sorted_set/up_to_spec.rb +12 -11
  274. data/spec/lib/hamster/sorted_set/values_at_spec.rb +6 -6
  275. data/spec/lib/hamster/vector/add_spec.rb +3 -3
  276. data/spec/lib/hamster/vector/any_spec.rb +1 -1
  277. data/spec/lib/hamster/vector/assoc_spec.rb +11 -1
  278. data/spec/lib/hamster/vector/bsearch_spec.rb +10 -2
  279. data/spec/lib/hamster/vector/clear_spec.rb +3 -3
  280. data/spec/lib/hamster/vector/combination_spec.rb +4 -4
  281. data/spec/lib/hamster/vector/compact_spec.rb +2 -2
  282. data/spec/lib/hamster/vector/compare_spec.rb +3 -3
  283. data/spec/lib/hamster/vector/concat_spec.rb +2 -2
  284. data/spec/lib/hamster/vector/copying_spec.rb +1 -1
  285. data/spec/lib/hamster/vector/delete_at_spec.rb +8 -8
  286. data/spec/lib/hamster/vector/delete_spec.rb +2 -2
  287. data/spec/lib/hamster/vector/drop_spec.rb +10 -3
  288. data/spec/lib/hamster/vector/drop_while_spec.rb +5 -5
  289. data/spec/lib/hamster/vector/each_index_spec.rb +2 -2
  290. data/spec/lib/hamster/vector/each_spec.rb +27 -29
  291. data/spec/lib/hamster/vector/each_with_index_spec.rb +2 -2
  292. data/spec/lib/hamster/vector/empty_spec.rb +11 -13
  293. data/spec/lib/hamster/vector/eql_spec.rb +6 -6
  294. data/spec/lib/hamster/vector/fetch_spec.rb +1 -1
  295. data/spec/lib/hamster/vector/fill_spec.rb +9 -9
  296. data/spec/lib/hamster/vector/first_spec.rb +10 -12
  297. data/spec/lib/hamster/vector/flat_map_spec.rb +51 -0
  298. data/spec/lib/hamster/vector/flatten_spec.rb +15 -0
  299. data/spec/lib/hamster/vector/get_spec.rb +4 -4
  300. data/spec/lib/hamster/vector/group_by_spec.rb +12 -12
  301. data/spec/lib/hamster/vector/include_spec.rb +2 -2
  302. data/spec/lib/hamster/vector/insert_spec.rb +2 -2
  303. data/spec/lib/hamster/vector/inspect_spec.rb +1 -1
  304. data/spec/lib/hamster/vector/join_spec.rb +5 -5
  305. data/spec/lib/hamster/vector/last_spec.rb +1 -1
  306. data/spec/lib/hamster/vector/length_spec.rb +1 -1
  307. data/spec/lib/hamster/vector/ltlt_spec.rb +2 -2
  308. data/spec/lib/hamster/vector/map_spec.rb +5 -5
  309. data/spec/lib/hamster/vector/marshal_spec.rb +2 -2
  310. data/spec/lib/hamster/vector/maximum_spec.rb +20 -22
  311. data/spec/lib/hamster/vector/minimum_spec.rb +20 -22
  312. data/spec/lib/hamster/vector/multiply_spec.rb +4 -4
  313. data/spec/lib/hamster/vector/partition_spec.rb +5 -5
  314. data/spec/lib/hamster/vector/permutation_spec.rb +4 -4
  315. data/spec/lib/hamster/vector/pop_spec.rb +3 -3
  316. data/spec/lib/hamster/vector/product_spec.rb +10 -10
  317. data/spec/lib/hamster/vector/put_spec.rb +175 -0
  318. data/spec/lib/hamster/vector/reduce_spec.rb +5 -57
  319. data/spec/lib/hamster/vector/{remove_spec.rb → reject_spec.rb} +4 -4
  320. data/spec/lib/hamster/vector/repeated_combination_spec.rb +4 -4
  321. data/spec/lib/hamster/vector/repeated_permutation_spec.rb +6 -6
  322. data/spec/lib/hamster/vector/reverse_each_spec.rb +1 -1
  323. data/spec/lib/hamster/vector/reverse_spec.rb +1 -1
  324. data/spec/lib/hamster/vector/rindex_spec.rb +1 -1
  325. data/spec/lib/hamster/vector/rotate_spec.rb +9 -9
  326. data/spec/lib/hamster/vector/sample_spec.rb +1 -1
  327. data/spec/lib/hamster/vector/{filter_spec.rb → select_spec.rb} +8 -8
  328. data/spec/lib/hamster/vector/set_spec.rb +12 -141
  329. data/spec/lib/hamster/vector/shift_spec.rb +3 -3
  330. data/spec/lib/hamster/vector/shuffle_spec.rb +2 -2
  331. data/spec/lib/hamster/vector/slice_spec.rb +137 -137
  332. data/spec/lib/hamster/vector/sorting_spec.rb +5 -5
  333. data/spec/lib/hamster/vector/sum_spec.rb +1 -1
  334. data/spec/lib/hamster/vector/take_spec.rb +17 -3
  335. data/spec/lib/hamster/vector/take_while_spec.rb +4 -4
  336. data/spec/lib/hamster/vector/to_a_spec.rb +1 -1
  337. data/spec/lib/hamster/vector/to_ary_spec.rb +1 -1
  338. data/spec/lib/hamster/vector/to_list_spec.rb +2 -1
  339. data/spec/lib/hamster/vector/to_set_spec.rb +1 -1
  340. data/spec/lib/hamster/vector/uniq_spec.rb +27 -6
  341. data/spec/lib/hamster/vector/unshift_spec.rb +3 -3
  342. data/spec/lib/hamster/vector/values_at_spec.rb +6 -6
  343. data/spec/lib/hamster/vector/zip_spec.rb +2 -2
  344. data/spec/lib/load_spec.rb +42 -0
  345. data/spec/spec_helper.rb +25 -0
  346. metadata +85 -48
  347. data/spec/lib/hamster/deque/head_spec.rb +0 -20
  348. data/spec/lib/hamster/hash/uniq_spec.rb +0 -14
  349. data/spec/lib/hamster/list/elem_index_spec.rb +0 -36
  350. data/spec/lib/hamster/list/elem_indices_spec.rb +0 -31
  351. data/spec/lib/hamster/list/filter_spec.rb +0 -71
  352. data/spec/lib/hamster/list/find_indices_spec.rb +0 -37
  353. data/spec/lib/hamster/set/foreach_spec.rb +0 -40
  354. data/spec/lib/hamster/set/head_spec.rb +0 -31
  355. data/spec/lib/hamster/set/uniq_spec.rb +0 -14
  356. data/spec/lib/hamster/sorted_set/construction_spec.rb +0 -29
  357. data/spec/lib/hamster/vector/exist_spec.rb +0 -70
  358. data/spec/lib/hamster/vector/exists_spec.rb +0 -70
@@ -1,16 +1,15 @@
1
- require "forwardable"
2
1
  require "hamster/hash"
3
2
  require "hamster/read_copy_update"
4
3
 
5
4
  module Hamster
6
- def self.mutable_hash(pairs = {}, &block)
7
- MutableHash.new(hash(pairs, &block))
8
- end
9
-
5
+ # @api private
10
6
  class MutableHash
11
- extend Forwardable
12
7
  include ReadCopyUpdate
13
8
 
9
+ def self.[](pairs = {})
10
+ MutableHash.new(Hash[pairs])
11
+ end
12
+
14
13
  def put(key, value = Undefined, &block)
15
14
  transform { |hash| hash.put(key, value, &block) }
16
15
  end
@@ -19,7 +18,7 @@ module Hamster
19
18
  put(key, value)
20
19
  value
21
20
  end
22
- def_delegator :self, :store, :[]=
21
+ alias :[]= :store
23
22
 
24
23
  def delete(key)
25
24
  old_value = nil
@@ -0,0 +1,78 @@
1
+ require "set"
2
+ require "hamster/hash"
3
+ require "hamster/set"
4
+ require "hamster/vector"
5
+ require "hamster/sorted_set"
6
+ require "hamster/list"
7
+ require "hamster/deque"
8
+ require "hamster/core_ext/struct"
9
+
10
+ module Hamster
11
+ class << self
12
+
13
+ # Create a Hamster immutable data structure with nested Hamster data
14
+ # structure from a nested Ruby object `obj`. This method recursively
15
+ # "walks" the Ruby object, converting Ruby `Hash` to {Hamster::Hash}, Ruby
16
+ # `Array` to {Hamster::Vector}, Ruby `Set` to {Hamster::Set}, and Ruby
17
+ # `SortedSet` to {Hamster::SortedSet}. Other objects are left as-is.
18
+ #
19
+ # @example
20
+ # h = Hamster.from({ "a" => [1, 2], "b" => "c" })
21
+ # # => Hamster::Hash["a" => Hamster::Vector[1, 2], "b" => "c"]
22
+ #
23
+ # @return [Hash, Vector, Set, SortedSet, Object]
24
+ def from(obj)
25
+ case obj
26
+ when ::Hash
27
+ res = obj.map { |key, value| [from(key), from(value)] }
28
+ Hamster::Hash.new(res)
29
+ when Hamster::Hash
30
+ obj.map { |key, value| [from(key), from(value)] }
31
+ when ::Struct
32
+ from(obj.to_h)
33
+ when ::Array
34
+ res = obj.map { |element| from(element) }
35
+ Hamster::Vector.new(res)
36
+ when ::SortedSet
37
+ # This clause must go before ::Set clause, since ::SortedSet is a ::Set.
38
+ res = obj.map { |element| from(element) }
39
+ Hamster::SortedSet.new(res)
40
+ when ::Set
41
+ res = obj.map { |element| from(element) }
42
+ Hamster::Set.new(res)
43
+ when Hamster::Vector, Hamster::Set, Hamster::SortedSet
44
+ obj.map { |element| from(element) }
45
+ else
46
+ obj
47
+ end
48
+ end
49
+
50
+ # Create a Ruby object from Hamster data. This method recursively "walks"
51
+ # the Hamster object, converting {Hamster::Hash} to Ruby `Hash`,
52
+ # {Hamster::Vector} and {Hamster::Deque} to Ruby `Array`, {Hamster::Set}
53
+ # to Ruby `Set`, and {Hamster::SortedSet} to Ruby `SortedSet`. Other
54
+ # objects are left as-is.
55
+ #
56
+ # @example
57
+ # h = Hamster.to_ruby(Hamster.from({ "a" => [1, 2], "b" => "c" }))
58
+ # # => { "a" => [1, 2], "b" => "c" }
59
+ #
60
+ # @return [::Hash, ::Array, ::Set, ::SortedSet, Object]
61
+ def to_ruby(obj)
62
+ case obj
63
+ when Hamster::Hash, ::Hash
64
+ obj.each_with_object({}) { |keyval, hash| hash[to_ruby(keyval[0])] = to_ruby(keyval[1]) }
65
+ when Hamster::Vector, ::Array
66
+ obj.each_with_object([]) { |element, arr| arr << to_ruby(element) }
67
+ when Hamster::Set, ::Set
68
+ obj.each_with_object(::Set.new) { |element, set| set << to_ruby(element) }
69
+ when Hamster::SortedSet, ::SortedSet
70
+ obj.each_with_object(::SortedSet.new) { |element, set| set << to_ruby(element) }
71
+ when Hamster::Deque
72
+ obj.to_a.tap { |arr| arr.map! { |element| to_ruby(element) }}
73
+ else
74
+ obj
75
+ end
76
+ end
77
+ end
78
+ end
@@ -14,7 +14,7 @@ module Hamster
14
14
  def eql?(other)
15
15
  instance_of?(other.class) && @content.eql?(other.instance_variable_get(:@content))
16
16
  end
17
- def_delegator :self, :eql?, :==
17
+ alias :== :eql?
18
18
 
19
19
  def_delegator :@content, :inspect
20
20
  def_delegator :@content, :to_s
@@ -1,17 +1,15 @@
1
- require "forwardable"
2
1
  require "hamster/immutable"
3
2
  require "hamster/undefined"
4
3
  require "hamster/enumerable"
4
+ require "hamster/hash"
5
5
  require "hamster/trie"
6
6
  require "hamster/sorted_set"
7
+ require "set"
7
8
 
8
9
  module Hamster
9
- def self.set(*items)
10
- items.empty? ? EmptySet : Set.new(items)
11
- end
12
10
 
13
11
  # `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
12
+ # an object is present in the `Set` can be done in constant time. `Set` is also `Enumerable`, so you can
15
13
  # iterate over the members of the set with {#each}, transform them with {#map}, filter
16
14
  # them with {#select}, and so on. Some of the `Enumerable` methods are overridden to
17
15
  # return Hamster collections.
@@ -24,15 +22,13 @@ module Hamster
24
22
  #
25
23
  # `Set`s have no natural ordering and cannot be compared using `#<=>`. However, they
26
24
  # define {#<}, {#>}, {#<=}, and {#>=} as shorthand for {#proper_subset?},
27
- # {#proper_superset?}, {#subset?}, and {#superset?} (respectively).
25
+ # {#proper_superset?}, {#subset?}, and {#superset?} respectively.
28
26
  #
29
27
  # 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.
28
+ # {#exclusion} work with any `Enumerable` object.
32
29
  #
33
- # A `Set` can be created in any of the following ways:
30
+ # A `Set` can be created in either of the following ways:
34
31
  #
35
- # Hamster.set('Tom', 'Dick', 'Harry')
36
32
  # Hamster::Set.new([1, 2, 3]) # any Enumerable can be used to initialize
37
33
  # Hamster::Set['A', 'B', 'C', 'D']
38
34
  #
@@ -43,8 +39,7 @@ module Hamster
43
39
  # actually return a new set and leave the existing one unchanged.
44
40
  #
45
41
  # @example
46
- # require 'hamster/set'
47
- # set1 = Hamster.set(1, 2) # => Hamster::Set[1, 2]
42
+ # set1 = Hamster::Set[1, 2] # => Hamster::Set[1, 2]
48
43
  # set2 = Hamster::Set[1, 2] # => Hamster::Set[1, 2]
49
44
  # set1 == set2 # => true
50
45
  # set3 = set1.add("foo") # => Hamster::Set[1, 2, "foo"]
@@ -53,7 +48,6 @@ module Hamster
53
48
  # set1.subset?(set3) # => true
54
49
  #
55
50
  class Set
56
- extend Forwardable
57
51
  include Immutable
58
52
  include Enumerable
59
53
 
@@ -61,7 +55,7 @@ module Hamster
61
55
  # Create a new `Set` populated with the given items.
62
56
  # @return [Set]
63
57
  def [](*items)
64
- new(items)
58
+ items.empty? ? empty : new(items)
65
59
  end
66
60
 
67
61
  # Return an empty `Set`. If used on a subclass, returns an empty instance
@@ -92,30 +86,35 @@ module Hamster
92
86
  def empty?
93
87
  @trie.empty?
94
88
  end
95
- def_delegator :self, :empty?, :null?
96
89
 
97
90
  # Return the number of items in this `Set`.
98
91
  # @return [Integer]
99
92
  def size
100
93
  @trie.size
101
94
  end
102
- def_delegator :self, :size, :length
95
+ alias :length :size
103
96
 
104
97
  # Return a new `Set` with `item` added. If `item` is already in the set,
105
98
  # return `self`.
106
99
  #
100
+ # @example
101
+ # Hamster::Set[1, 2, 3].add(4) # => Hamster::Set[1, 2, 4, 3]
102
+ # Hamster::Set[1, 2, 3].add(2) # => Hamster::Set[1, 2, 3]
103
+ #
107
104
  # @param item [Object] The object to add
108
105
  # @return [Set]
109
106
  def add(item)
110
107
  include?(item) ? self : self.class.alloc(@trie.put(item, nil))
111
108
  end
112
- def_delegator :self, :add, :<<
113
- def_delegator :self, :add, :conj
114
- def_delegator :self, :add, :conjoin
109
+ alias :<< :add
115
110
 
116
111
  # If `item` is not a member of this `Set`, return a new `Set` with `item` added.
117
112
  # Otherwise, return `false`.
118
113
  #
114
+ # @example
115
+ # Hamster::Set[1, 2, 3].add?(4) # => Hamster::Set[1, 2, 4, 3]
116
+ # Hamster::Set[1, 2, 3].add?(2) # => false
117
+ #
119
118
  # @param item [Object] The object to add
120
119
  # @return [Set, false]
121
120
  def add?(item)
@@ -125,22 +124,24 @@ module Hamster
125
124
  # Return a new `Set` with `item` removed. If `item` is not a member of the set,
126
125
  # return `self`.
127
126
  #
127
+ # @example
128
+ # Hamster::Set[1, 2, 3].delete(1) # => Hamster::Set[2, 3]
129
+ # Hamster::Set[1, 2, 3].delete(99) # => Hamster::Set[1, 2, 3]
130
+ #
128
131
  # @param item [Object] The object to remove
129
132
  # @return [Set]
130
133
  def delete(item)
131
134
  trie = @trie.delete(item)
132
- if trie.equal?(@trie)
133
- self
134
- elsif trie.empty?
135
- self.class.empty
136
- else
137
- self.class.alloc(trie)
138
- end
135
+ new_trie(trie)
139
136
  end
140
137
 
141
138
  # If `item` is a member of this `Set`, return a new `Set` with `item` removed.
142
139
  # Otherwise, return `false`.
143
140
  #
141
+ # @example
142
+ # Hamster::Set[1, 2, 3].delete?(1) # => Hamster::Set[2, 3]
143
+ # Hamster::Set[1, 2, 3].delete?(99) # => false
144
+ #
144
145
  # @param item [Object] The object to remove
145
146
  # @return [Set, false]
146
147
  def delete?(item)
@@ -148,9 +149,18 @@ module Hamster
148
149
  end
149
150
 
150
151
  # 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
+ # is guaranteed, but the order will be stable for any particular `Set`. If
153
+ # no block is given, an `Enumerator` is returned instead.
152
154
  #
153
- # @return [self]
155
+ # @example
156
+ # Hamster::Set["Dog", "Elephant", "Lion"].each { |e| puts e }
157
+ # Elephant
158
+ # Dog
159
+ # Lion
160
+ # # => Hamster::Set["Dog", "Elephant", "Lion"]
161
+ #
162
+ # @yield [item] Once for each item.
163
+ # @return [self, Enumerator]
154
164
  def each
155
165
  return to_enum if not block_given?
156
166
  @trie.each { |key, _| yield(key) }
@@ -158,8 +168,17 @@ module Hamster
158
168
  end
159
169
 
160
170
  # Call the block once for each item in this `Set`. Iteration order will be
161
- # the opposite of {#each}.
171
+ # the opposite of {#each}. If no block is given, an `Enumerator` is
172
+ # returned instead.
162
173
  #
174
+ # @example
175
+ # Hamster::Set["Dog", "Elephant", "Lion"].reverse_each { |e| puts e }
176
+ # Lion
177
+ # Dog
178
+ # Elephant
179
+ # # => Hamster::Set["Dog", "Elephant", "Lion"]
180
+ #
181
+ # @yield [item] Once for each item.
163
182
  # @return [self]
164
183
  def reverse_each
165
184
  return enum_for(:reverse_each) if not block_given?
@@ -169,65 +188,93 @@ module Hamster
169
188
 
170
189
  # Return a new `Set` with all the items for which the block returns true.
171
190
  #
191
+ # @example
192
+ # Hamster::Set["Elephant", "Dog", "Lion"].select { |e| e.size >= 4 }
193
+ # # => Hamster::Set["Elephant", "Lion"]
194
+ # @yield [item] Once for each item.
172
195
  # @return [Set]
173
- def filter
174
- return enum_for(:filter) unless block_given?
175
- trie = @trie.filter { |entry| yield(entry[0]) }
176
- return self.class.empty if trie.empty?
177
- trie.equal?(@trie) ? self : self.class.alloc(trie)
196
+ def select
197
+ return enum_for(:select) unless block_given?
198
+ trie = @trie.select { |key, _| yield(key) }
199
+ new_trie(trie)
178
200
  end
201
+ alias :find_all :select
202
+ alias :keep_if :select
179
203
 
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`.
204
+ # Call the block once for each item in this `Set`. All the values returned
205
+ # from the block will be gathered into a new `Set`. If no block is given,
206
+ # an `Enumerator` is returned instead.
184
207
  #
208
+ # @example
209
+ # Hamster::Set["Cat", "Elephant", "Dog", "Lion"].map { |e| e.size }
210
+ # # => Hamster::Set[8, 4, 3]
211
+ #
212
+ # @yield [item] Once for each item.
185
213
  # @return [Set]
186
214
  def map
187
215
  return enum_for(:map) if not block_given?
188
216
  return self if empty?
189
217
  self.class.new(super)
190
218
  end
191
- def_delegator :self, :map, :collect
219
+ alias :collect :map
192
220
 
193
221
  # Return `true` if the given item is present in this `Set`. More precisely,
194
222
  # return `true` if an object with the same `#hash` code, and which is also `#eql?`
195
223
  # to the given object is present.
196
224
  #
225
+ # @example
226
+ # Hamster::Set["A", "B", "C"].include?("B") # => true
227
+ # Hamster::Set["A", "B", "C"].include?("Z") # => false
228
+ #
197
229
  # @param object [Object] The object to check for
198
230
  # @return [Boolean]
199
231
  def include?(object)
200
232
  @trie.key?(object)
201
233
  end
202
- def_delegator :self, :include?, :member?
234
+ alias :member? :include?
203
235
 
204
236
  # Return a member of this `Set`. The member chosen will be the first one which
205
237
  # would be yielded by {#each}. If the set is empty, return `nil`.
206
238
  #
239
+ # @example
240
+ # Hamster::Set["A", "B", "C"].first # => "C"
241
+ #
207
242
  # @return [Object]
208
243
  def first
209
244
  (entry = @trie.at(0)) && entry[0]
210
245
  end
211
- def_delegator :self, :first, :head
212
246
 
213
247
  # 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.
248
+ # the given comparator block.
217
249
  #
218
- # @yield [a, b] A pair of items to be compared
219
- # @yieldreturn [Integer]
250
+ # @example
251
+ # Hamster::Set["Elephant", "Dog", "Lion"].sort
252
+ # # => Hamster::SortedSet["Dog", "Elephant", "Lion"]
253
+ # Hamster::Set["Elephant", "Dog", "Lion"].sort { |a,b| a.size <=> b.size }
254
+ # # => Hamster::SortedSet["Dog", "Lion", "Elephant"]
255
+ #
256
+ # @yield [a, b] Any number of times with different pairs of elements.
257
+ # @yieldreturn [Integer] Negative if the first element should be sorted
258
+ # lower, positive if the latter element, or 0 if
259
+ # equal.
220
260
  # @return [SortedSet]
221
261
  def sort(&comparator)
222
262
  SortedSet.new(self.to_a, &comparator)
223
263
  end
224
264
 
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.
265
+ # Return a {SortedSet} which contains the same items as this `Set`, ordered
266
+ # by mapping each item through the provided block to obtain sort keys, and
267
+ # then sorting the keys.
228
268
  #
229
- # @yield [item] The item to obtain a sort key for
230
- # @yieldreturn [Object]
269
+ # @example
270
+ # Hamster::Set["Elephant", "Dog", "Lion"].sort_by { |e| e.size }
271
+ # # => Hamster::SortedSet["Dog", "Lion", "Elephant"]
272
+ #
273
+ # @yield [item] Once for each item to create the set, and then potentially
274
+ # again depending on what operations are performed on the
275
+ # returned {SortedSet}. As such, it is recommended that the
276
+ # block be a pure function.
277
+ # @yieldreturn [Object] sort key for the item
231
278
  # @return [SortedSet]
232
279
  def sort_by(&mapper)
233
280
  SortedSet.new(self.to_a, &mapper)
@@ -242,22 +289,29 @@ module Hamster
242
289
  # @param other [Enumerable] The collection to merge with
243
290
  # @return [Set]
244
291
  def union(other)
245
- if other.is_a?(Hamster::Set) && other.size > size
246
- small_set = self
247
- large_set_trie = other.instance_variable_get(:@trie)
292
+ if other.is_a?(Hamster::Set)
293
+ if other.size > size
294
+ small_set_pairs = @trie
295
+ large_set_trie = other.instance_variable_get(:@trie)
296
+ else
297
+ small_set_pairs = other.instance_variable_get(:@trie)
298
+ large_set_trie = @trie
299
+ end
248
300
  else
249
- small_set = other
301
+ if other.respond_to?(:lazy)
302
+ small_set_pairs = other.lazy.map { |e| [e, nil] }
303
+ else
304
+ small_set_pairs = other.map { |e| [e, nil] }
305
+ end
250
306
  large_set_trie = @trie
251
307
  end
252
- trie = small_set.reduce(large_set_trie) do |a, element|
253
- next a if a.key?(element)
254
- a.put(element, nil)
255
- end
256
- trie.equal?(@trie) ? self : self.class.alloc(trie)
308
+
309
+ trie = large_set_trie.bulk_put(small_set_pairs)
310
+ new_trie(trie)
257
311
  end
258
- def_delegator :self, :union, :|
259
- def_delegator :self, :union, :+
260
- def_delegator :self, :union, :merge
312
+ alias :| :union
313
+ alias :+ :union
314
+ alias :merge :union
261
315
 
262
316
  # Return a new `Set` which contains all the items which are members of both
263
317
  # this `Set` and `other`. `other` can be any `Enumerable` object.
@@ -268,15 +322,19 @@ module Hamster
268
322
  # @param other [Enumerable] The collection to intersect with
269
323
  # @return [Set]
270
324
  def intersection(other)
271
- if (other.size < @trie.size) && other.is_a?(Hamster::Set)
272
- trie = other.instance_variable_get(:@trie).filter { |key, _| include?(key) }
325
+ if other.size < @trie.size
326
+ if other.is_a?(Hamster::Set)
327
+ trie = other.instance_variable_get(:@trie).select { |key, _| include?(key) }
328
+ else
329
+ trie = Trie.new(0)
330
+ other.each { |obj| trie.put!(obj, nil) if include?(obj) }
331
+ end
273
332
  else
274
- trie = @trie.filter { |key, _| other.include?(key) }
333
+ trie = @trie.select { |key, _| other.include?(key) }
275
334
  end
276
- trie.equal?(@trie) ? self : self.class.alloc(trie)
335
+ new_trie(trie)
277
336
  end
278
- def_delegator :self, :intersection, :intersect
279
- def_delegator :self, :intersection, :&
337
+ alias :& :intersection
280
338
 
281
339
  # Return a new `Set` with all the items in `other` removed. `other` can be
282
340
  # any `Enumerable` object.
@@ -288,15 +346,14 @@ module Hamster
288
346
  # @return [Set]
289
347
  def difference(other)
290
348
  trie = if (@trie.size <= other.size) && (other.is_a?(Hamster::Set) || (defined?(::Set) && other.is_a?(::Set)))
291
- @trie.filter { |key, _| !other.include?(key) }
349
+ @trie.select { |key, _| !other.include?(key) }
292
350
  else
293
- other.reduce(@trie) { |trie, item| trie.delete(item) }
351
+ @trie.bulk_delete(other)
294
352
  end
295
- trie.empty? ? self.class.empty : self.class.alloc(trie)
353
+ new_trie(trie)
296
354
  end
297
- def_delegator :self, :difference, :diff
298
- def_delegator :self, :difference, :subtract
299
- def_delegator :self, :difference, :-
355
+ alias :subtract :difference
356
+ alias :- :difference
300
357
 
301
358
  # Return a new `Set` which contains all the items which are members of this
302
359
  # `Set` or of `other`, but not both. `other` can be any `Enumerable` object.
@@ -309,20 +366,39 @@ module Hamster
309
366
  def exclusion(other)
310
367
  ((self | other) - (self & other))
311
368
  end
312
- def_delegator :self, :exclusion, :^
369
+ alias :^ :exclusion
313
370
 
314
371
  # Return `true` if all items in this `Set` are also in `other`.
315
372
  #
373
+ # @example
374
+ # Hamster::Set[2, 3].subset?(Hamster::Set[1, 2, 3]) # => true
375
+ #
316
376
  # @param other [Set]
317
377
  # @return [Boolean]
318
378
  def subset?(other)
319
379
  return false if other.size < size
380
+
381
+ # This method has the potential to be very slow if 'other' is a large Array, so to avoid that,
382
+ # we convert those Arrays to Sets before checking presence of items
383
+ # Time to convert Array -> Set is linear in array.size
384
+ # Time to check for presence of all items in an Array is proportional to set.size * array.size
385
+ # Note that both sides of that equation have array.size -- hence those terms cancel out,
386
+ # and the break-even point is solely dependent on the size of this collection
387
+ # After doing some benchmarking to estimate the constants, it appears break-even is at ~190 items
388
+ # We also check other.size, to avoid the more expensive #is_a? checks in cases where it doesn't matter
389
+ #
390
+ if other.size >= 150 && @trie.size >= 190 && !(other.is_a?(Hamster::Set) || other.is_a?(::Set))
391
+ other = ::Set.new(other)
392
+ end
320
393
  all? { |item| other.include?(item) }
321
394
  end
322
395
  alias :<= :subset?
323
396
 
324
397
  # Return `true` if all items in `other` are also in this `Set`.
325
398
  #
399
+ # @example
400
+ # Hamster::Set[1, 2, 3].superset?(Hamster::Set[2, 3]) # => true
401
+ #
326
402
  # @param other [Set]
327
403
  # @return [Boolean]
328
404
  def superset?(other)
@@ -333,10 +409,18 @@ module Hamster
333
409
  # Returns `true` if `other` contains all the items in this `Set`, plus at least
334
410
  # one item which is not in this set.
335
411
  #
412
+ # @example
413
+ # Hamster::Set[2, 3].proper_subset?(Hamster::Set[1, 2, 3]) # => true
414
+ # Hamster::Set[1, 2, 3].proper_subset?(Hamster::Set[1, 2, 3]) # => false
415
+ #
336
416
  # @param other [Set]
337
417
  # @return [Boolean]
338
418
  def proper_subset?(other)
339
419
  return false if other.size <= size
420
+ # See comments above
421
+ if other.size >= 150 && @trie.size >= 190 && !(other.is_a?(Hamster::Set) || other.is_a?(::Set))
422
+ other = ::Set.new(other)
423
+ end
340
424
  all? { |item| other.include?(item) }
341
425
  end
342
426
  alias :< :proper_subset?
@@ -344,6 +428,10 @@ module Hamster
344
428
  # Returns `true` if this `Set` contains all the items in `other`, plus at least
345
429
  # one item which is not in `other`.
346
430
  #
431
+ # @example
432
+ # Hamster::Set[1, 2, 3].proper_superset?(Hamster::Set[2, 3]) # => true
433
+ # Hamster::Set[1, 2, 3].proper_superset?(Hamster::Set[1, 2, 3]) # => false
434
+ #
347
435
  # @param other [Set]
348
436
  # @return [Boolean]
349
437
  def proper_superset?(other)
@@ -353,19 +441,29 @@ module Hamster
353
441
 
354
442
  # Return `true` if this `Set` and `other` do not share any items.
355
443
  #
444
+ # @example
445
+ # Hamster::Set[1, 2].disjoint?(Hamster::Set[8, 9]) # => true
446
+ #
356
447
  # @param other [Set]
357
448
  # @return [Boolean]
358
449
  def disjoint?(other)
359
- if size < other.size
360
- each { |item| return false if other.include?(item) }
361
- else
450
+ if other.size <= size
362
451
  other.each { |item| return false if include?(item) }
452
+ else
453
+ # See comment on #subset?
454
+ if other.size >= 150 && @trie.size >= 190 && !(other.is_a?(Hamster::Set) || other.is_a?(::Set))
455
+ other = ::Set.new(other)
456
+ end
457
+ each { |item| return false if other.include?(item) }
363
458
  end
364
459
  true
365
460
  end
366
461
 
367
462
  # Return `true` if this `Set` and `other` have at least one item in common.
368
463
  #
464
+ # @example
465
+ # Hamster::Set[1, 2].intersect?(Hamster::Set[2, 3]) # => true
466
+ #
369
467
  # @param other [Set]
370
468
  # @return [Boolean]
371
469
  def intersect?(other)
@@ -387,11 +485,14 @@ module Hamster
387
485
  end
388
486
  end
389
487
 
390
- def_delegator :self, :group_by, :group
391
- def_delegator :self, :group_by, :classify
488
+ alias :group :group_by
489
+ alias :classify :group_by
392
490
 
393
491
  # Return a randomly chosen item from this `Set`. If the set is empty, return `nil`.
394
492
  #
493
+ # @example
494
+ # Hamster::Set[1, 2, 3, 4, 5].sample # => 3
495
+ #
395
496
  # @return [Object]
396
497
  def sample
397
498
  empty? ? nil : @trie.at(rand(size))[0]
@@ -400,7 +501,7 @@ module Hamster
400
501
  # Return an empty `Set` instance, of the same class as this one. Useful if you
401
502
  # have multiple subclasses of `Set` and want to treat them polymorphically.
402
503
  #
403
- # @return [Hash]
504
+ # @return [Set]
404
505
  def clear
405
506
  self.class.empty
406
507
  end
@@ -419,7 +520,7 @@ module Hamster
419
520
  end
420
521
  true
421
522
  end
422
- def_delegator :self, :eql?, :==
523
+ alias :== :eql?
423
524
 
424
525
  # See `Object#hash`.
425
526
  # @return [Integer]
@@ -430,10 +531,6 @@ module Hamster
430
531
  undef :"<=>" # Sets are not ordered, so Enumerable#<=> will give a meaningless result
431
532
  undef :each_index # Set members cannot be accessed by 'index', so #each_index is not meaningful
432
533
 
433
- def_delegator :self, :dup, :uniq
434
- def_delegator :self, :dup, :nub
435
- def_delegator :self, :dup, :remove_duplicates
436
-
437
534
  # Return `self`.
438
535
  #
439
536
  # @return [self]
@@ -456,11 +553,24 @@ module Hamster
456
553
  trie.put(key_value.first, nil)
457
554
  end
458
555
  end
556
+
557
+ private
558
+
559
+ def new_trie(trie)
560
+ if trie.empty?
561
+ self.class.empty
562
+ elsif trie.equal?(@trie)
563
+ self
564
+ else
565
+ self.class.alloc(trie)
566
+ end
567
+ end
459
568
  end
460
569
 
461
- # The canonical empty `Set`. Returned by `Hamster.set` and `Set[]` when
570
+ # The canonical empty `Set`. Returned by `Set[]` when
462
571
  # invoked with no arguments; also returned by `Set.empty`. Prefer using this
463
572
  # one rather than creating many empty sets using `Set.new`.
464
573
  #
574
+ # @private
465
575
  EmptySet = Hamster::Set.empty
466
576
  end