hamster 1.0.1.pre.rc3 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
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