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,20 +1,19 @@
1
- require "forwardable"
2
1
  require "hamster/set"
3
2
  require "hamster/read_copy_update"
4
3
 
5
4
  module Hamster
6
- def self.mutable_set(*items)
7
- MutableSet.new(set(*items))
8
- end
9
-
5
+ # @api private
10
6
  class MutableSet
11
- extend Forwardable
12
7
  include ReadCopyUpdate
13
8
 
9
+ def self.[](*items)
10
+ MutableSet.new(Set[*items])
11
+ end
12
+
14
13
  def add(item)
15
14
  transform { |set| set.add(item) }
16
15
  end
17
- def_delegator :self, :add, :<<
16
+ alias :<< :add
18
17
 
19
18
  def add?(item)
20
19
  added = false
@@ -1,83 +1,76 @@
1
- require "forwardable"
2
-
3
1
  require "hamster/immutable"
4
2
  require "hamster/undefined"
3
+ require "hamster/enumerable"
5
4
  require "hamster/trie"
6
5
  require "hamster/set"
7
6
  require "hamster/vector"
7
+ require "hamster/associable"
8
8
 
9
9
  module Hamster
10
- def self.hash(pairs = nil, &block)
11
- (pairs.nil? && block.nil?) ? EmptyHash : Hash.new(pairs, &block)
12
- end
13
-
14
- # A `Hamster::Hash` maps from a set of unique keys to corresponding values,
15
- # much like a dictionary maps from words to definitions. Given a key, it can
16
- # efficiently store and retrieve values. Looking up a key given its value is also
17
- # possible, but less efficient. If an existing key is stored again, the new value
18
- # will replace that which was previously stored.
10
+ # A `Hamster::Hash` maps a set of unique keys to corresponding values, much
11
+ # like a dictionary maps from words to definitions. Given a key, it can store
12
+ # and retrieve an associated value in constant time. If an existing key is
13
+ # stored again, the new value will replace the old. It behaves much like
14
+ # Ruby's built-in Hash, which we will call RubyHash for clarity. Like
15
+ # RubyHash, two keys that are `#eql?` to each other and have the same
16
+ # `#hash` are considered identical in a `Hamster::Hash`.
19
17
  #
20
- # It behaves much like Ruby's built-in Hash, which we will call RubyHash
21
- # for clarity. Like RubyHash, `Hamster::Hash` uses `#hash` and `#eql?` to define
22
- # equality between keys. Keys with the same `#hash` code, but which are not `#eql?`
23
- # to each other, can coexist in the same `Hamster::Hash`. To retrieve a previously
24
- # stored value, the key provided must have the same `#hash` code and be `#eql?`
25
- # to the one used for storage.
18
+ # A `Hamster::Hash` can be created in a couple of ways:
26
19
  #
27
- # A `Hamster::Hash` can be created in several ways:
28
- #
29
- # Hamster.hash('Jane Doe' => 10, 'Jim Doe' => 6)
30
20
  # Hamster::Hash.new(font_size: 10, font_family: 'Arial')
31
21
  # Hamster::Hash[first_name: 'John', last_name: 'Smith']
32
22
  #
33
- # If you want to write your own class which inherits from `Hamster::Hash`, you can
34
- # use either of the latter 2 forms of initialization.
35
- #
36
- # Note that any `Enumerable` object which yields 2-element `[key, value]` arrays
37
- # can be used to initialize a `Hamster::Hash`. So this is also possible:
23
+ # Any `Enumerable` object which yields two-element `[key, value]` arrays
24
+ # can be used to initialize a `Hamster::Hash`:
38
25
  #
39
26
  # Hamster::Hash.new([[:first_name, 'John'], [:last_name, 'Smith']])
40
27
  #
41
- # Like RubyHash, key/value pairs can be added using {#store}. Unlike RubyHash,
42
- # a new hash is returned, and the existing one is left unchanged:
28
+ # Key/value pairs can be added using {#put}. A new hash is returned and the
29
+ # existing one is left unchanged:
43
30
  #
44
31
  # hash = Hamster::Hash[a: 100, b: 200]
45
- # hash.store(:c, 500) # => Hamster::Hash[:a => 100, :b => 200, :c => 500]
46
- # hash # => Hamster::Hash[:a => 100, :b => 200]
32
+ # hash.put(:c, 500) # => Hamster::Hash[:a => 100, :b => 200, :c => 500]
33
+ # hash # => Hamster::Hash[:a => 100, :b => 200]
47
34
  #
48
- # You also use {#put}. The difference is that {#put} can optionally take a block which
49
- # is used to calculate the value to be stored:
35
+ # {#put} can also take a block, which is used to calculate the value to be
36
+ # stored.
50
37
  #
51
- # hash.put(:a) { hash[:b] + 100 } # => Hamster::Hash[:a => 300, :b => 200]
38
+ # hash.put(:a) { |current| current + 200 } # => Hamster::Hash[:a => 300, :b => 200]
52
39
  #
53
- # Since it is immutable, all methods which you might expect to "modify" a `Hamster::Hash`
54
- # actually return a new hash and leave the existing one unchanged. This means that the
55
- # `hash[key] = value` syntax used with RubyHashes *cannot* be used with `Hamster::Hash`.
40
+ # Since it is immutable, all methods which you might expect to "modify" a
41
+ # `Hamster::Hash` actually return a new hash and leave the existing one
42
+ # unchanged. This means that the `hash[key] = value` syntax from RubyHash
43
+ # *cannot* be used with `Hamster::Hash`.
56
44
  #
57
- # While a `Hamster::Hash` can iterate over its keys (or values), it does not
58
- # guarantee any specific iteration order (unlike RubyHash). Likewise, methods like
59
- # {#flatten} do not guarantee which order the returned key/value pairs will appear
60
- # in.
45
+ # Nested data structures can easily be updated using {#update_in}:
61
46
  #
62
- # Like RubyHash, a `Hamster::Hash` can have a default block which is used when
63
- # looking up a key which does not exist in the hash. Unlike RubyHash, the default
64
- # block will only be passed the missing key, not the hash itself:
47
+ # hash = Hamster::Hash["a" => Hamster::Vector[Hamster::Hash["c" => 42]]]
48
+ # hash.update_in("a", 0, "c") { |value| value + 5 }
49
+ # # => Hamster::Hash["a" => Hamster::Hash["b" => Hamster::Hash["c" => 47]]]
65
50
  #
66
- # hash = Hamster::Hash.new { |n| n * 10 }
67
- # hash[5] # => 50
51
+ # While a `Hamster::Hash` can iterate over its keys or values, it does not
52
+ # guarantee any specific iteration order (unlike RubyHash). Methods like
53
+ # {#flatten} do not guarantee the order of returned key/value pairs.
68
54
  #
69
- # A default block can only be set when creating a `Hamster::Hash` with `Hamster::Hash.new` or
70
- # {Hamster.hash Hamster.hash}, not with {Hamster::Hash.[] Hamster::Hash[]}. Default blocks
71
- # do not survive marshalling and unmarshalling.
55
+ # Like RubyHash, a `Hamster::Hash` can have a default block which is used
56
+ # when looking up a key that does not exist. Unlike RubyHash, the default
57
+ # block will only be passed the missing key, without the hash itself:
72
58
  #
59
+ # hash = Hamster::Hash.new { |missing_key| missing_key * 10 }
60
+ # hash[5] # => 50
73
61
  class Hash
74
- extend Forwardable
75
62
  include Immutable
76
63
  include Enumerable
64
+ include Associable
77
65
 
78
66
  class << self
79
67
  # Create a new `Hash` populated with the given key/value pairs.
80
68
  #
69
+ # @example
70
+ # Hamster::Hash["A" => 1, "B" => 2] # => Hamster::Hash["A" => 1, "B" => 2]
71
+ # Hamster::Hash[["A", 1], ["B", 2]] # => Hamster::Hash["A" => 1, "B" => 2]
72
+ #
73
+ # @param pairs [::Enumerable] initial content of hash. An empty hash is returned if not provided.
81
74
  # @return [Hash]
82
75
  def [](pairs = nil)
83
76
  (pairs.nil? || pairs.empty?) ? empty : new(pairs)
@@ -104,6 +97,9 @@ module Hamster
104
97
  end
105
98
  end
106
99
 
100
+ # @param pairs [::Enumerable] initial content of hash. An empty hash is returned if not provided.
101
+ # @yield [key] Optional _default block_ to be stored and used to calculate the default value of a missing key. It will not be yielded during this method. It will not be preserved when marshalling.
102
+ # @yieldparam key Key that was not present in the hash.
107
103
  def initialize(pairs = nil, &block)
108
104
  @trie = pairs ? Trie[pairs] : EmptyTrie
109
105
  @default = block
@@ -118,11 +114,14 @@ module Hamster
118
114
 
119
115
  # Return the number of key/value pairs in this `Hash`.
120
116
  #
117
+ # @example
118
+ # Hamster::Hash["A" => 1, "B" => 2, "C" => 3].size # => 3
119
+ #
121
120
  # @return [Integer]
122
121
  def size
123
122
  @trie.size
124
123
  end
125
- def_delegator :self, :size, :length
124
+ alias :length :size
126
125
 
127
126
  # Return `true` if this `Hash` contains no key/value pairs.
128
127
  #
@@ -130,34 +129,50 @@ module Hamster
130
129
  def empty?
131
130
  @trie.empty?
132
131
  end
133
- def_delegator :self, :empty?, :null?
134
132
 
135
133
  # Return `true` if the given key object is present in this `Hash`. More precisely,
136
134
  # return `true` if a key with the same `#hash` code, and which is also `#eql?`
137
135
  # to the given key object is present.
138
136
  #
137
+ # @example
138
+ # Hamster::Hash["A" => 1, "B" => 2, "C" => 3].key?("B") # => true
139
+ #
139
140
  # @param key [Object] The key to check for
140
141
  # @return [Boolean]
141
142
  def key?(key)
142
143
  @trie.key?(key)
143
144
  end
144
- def_delegator :self, :key?, :has_key?
145
- def_delegator :self, :key?, :include?
146
- def_delegator :self, :key?, :member?
145
+ alias :has_key? :key?
146
+ alias :include? :key?
147
+ alias :member? :key?
147
148
 
148
149
  # Return `true` if this `Hash` has one or more keys which map to the provided value.
149
150
  #
151
+ # @example
152
+ # Hamster::Hash["A" => 1, "B" => 2, "C" => 3].value?(2) # => true
153
+ #
150
154
  # @param value [Object] The value to check for
151
155
  # @return [Boolean]
152
156
  def value?(value)
153
157
  each { |k,v| return true if value == v }
154
158
  false
155
159
  end
156
- def_delegator :self, :value?, :has_value?
160
+ alias :has_value? :value?
157
161
 
158
162
  # Retrieve the value corresponding to the provided key object. If not found, and
159
163
  # this `Hash` has a default block, the default block is called to provide the
160
- # value.
164
+ # value. Otherwise, return `nil`.
165
+ #
166
+ # @example
167
+ # h = Hamster::Hash["A" => 1, "B" => 2, "C" => 3]
168
+ # h["B"] # => 2
169
+ # h.get("B") # => 2
170
+ # h.get("Elephant") # => nil
171
+ #
172
+ # # Hamster Hash with a default proc:
173
+ # h = Hamster::Hash.new("A" => 1, "B" => 2, "C" => 3) { |key| key.size }
174
+ # h.get("B") # => 2
175
+ # h.get("Elephant") # => 8
161
176
  #
162
177
  # @param key [Object] The key to look up
163
178
  # @return [Object]
@@ -169,7 +184,7 @@ module Hamster
169
184
  @default.call(key)
170
185
  end
171
186
  end
172
- def_delegator :self, :get, :[]
187
+ alias :[] :get
173
188
 
174
189
  # Retrieve the value corresponding to the given key object, or use the provided
175
190
  # default value or block, or otherwise raise a `KeyError`.
@@ -190,6 +205,19 @@ module Hamster
190
205
  # @param key [Object] The key to look up
191
206
  # @param default [Object] Object to return if the key is not found
192
207
  #
208
+ # @example
209
+ # h = Hamster::Hash["A" => 1, "B" => 2, "C" => 3]
210
+ # h.fetch("B") # => 2
211
+ # h.fetch("Elephant") # => KeyError: key not found: "Elephant"
212
+ #
213
+ # # with a default value:
214
+ # h.fetch("B", 99) # => 2
215
+ # h.fetch("Elephant", 99) # => 99
216
+ #
217
+ # # with a block:
218
+ # h.fetch("B") { |key| key.size } # => 2
219
+ # h.fetch("Elephant") { |key| key.size } # => 8
220
+ #
193
221
  # @return [Object]
194
222
  def fetch(key, default = Undefined)
195
223
  entry = @trie.get(key)
@@ -213,36 +241,70 @@ module Hamster
213
241
  # returns will replace the existing value. This is useful for "transforming"
214
242
  # the value associated with a certain key.
215
243
  #
216
- # Avoid mutating objects which are used as keys. `String`s are an exception --
244
+ # Avoid mutating objects which are used as keys. `String`s are an exception:
217
245
  # unfrozen `String`s which are used as keys are internally duplicated and
218
- # frozen.
246
+ # frozen. This matches RubyHash's behaviour.
247
+ #
248
+ # @example
249
+ # h = Hamster::Hash["A" => 1, "B" => 2]
250
+ # h.put("C", 3)
251
+ # # => Hamster::Hash["A" => 1, "B" => 2, "C" => 3]
252
+ # h.put("B") { |value| value * 10 }
253
+ # # => Hamster::Hash["A" => 1, "B" => 20]
219
254
  #
220
255
  # @param key [Object] The key to store
221
256
  # @param value [Object] The value to associate it with
222
- # @yield [value] The previously stored value
257
+ # @yield [value] The previously stored value, or `nil` if none.
223
258
  # @yieldreturn [Object] The new value to store
224
259
  # @return [Hash]
225
260
  def put(key, value = yield(get(key)))
226
- self.class.alloc(@trie.put(key, value), @default)
261
+ new_trie = @trie.put(key, value)
262
+ if new_trie.equal?(@trie)
263
+ self
264
+ else
265
+ self.class.alloc(new_trie, @default)
266
+ end
227
267
  end
228
268
 
229
- # Return a new `Hash` with the existing key/value associations, plus an association
230
- # between the provided key and value. If an equivalent key is already present, its
231
- # associated value will be replaced with the provided one.
269
+ # Return a new `Hash` with a deeply nested value modified to the result of
270
+ # the given code block. When traversing the nested `Hash`es and `Vector`s,
271
+ # non-existing keys are created with empty `Hash` values.
232
272
  #
233
- # Avoid mutating objects which are used as keys. `String`s are an exception --
234
- # unfrozen `String`s which are used as keys are internally duplicated and
235
- # frozen.
273
+ # The code block receives the existing value of the deeply nested key (or
274
+ # `nil` if it doesn't exist). This is useful for "transforming" the value
275
+ # associated with a certain key.
276
+ #
277
+ # Note that the original `Hash` and sub-`Hash`es and sub-`Vector`s are left
278
+ # unmodified; new data structure copies are created along the path wherever
279
+ # needed.
280
+ #
281
+ # @example
282
+ # hash = Hamster::Hash["a" => Hamster::Hash["b" => Hamster::Hash["c" => 42]]]
283
+ # hash.update_in("a", "b", "c") { |value| value + 5 }
284
+ # # => Hamster::Hash["a" => Hamster::Hash["b" => Hamster::Hash["c" => 47]]]
285
+ #
286
+ # @param key_path [::Array<Object>] List of keys which form the path to the key to be modified
287
+ # @yield [value] The previously stored value
288
+ # @yieldreturn [Object] The new value to store
289
+ # @return [Hash]
290
+
291
+ # An alias for {#put} to match RubyHash's API. Does not support {#put}'s
292
+ # block form.
236
293
  #
294
+ # @see #put
237
295
  # @param key [Object] The key to store
238
296
  # @param value [Object] The value to associate it with
239
297
  # @return [Hash]
240
298
  def store(key, value)
241
- self.class.alloc(@trie.put(key, value), @default)
299
+ put(key, value)
242
300
  end
243
301
 
244
- # Return a new `Hash` with the association for `key` removed. If `key` is not
245
- # present, return `self`.
302
+ # Return a new `Hash` with `key` removed. If `key` is not present, return
303
+ # `self`.
304
+ #
305
+ # @example
306
+ # Hamster::Hash["A" => 1, "B" => 2, "C" => 3].delete("B")
307
+ # # => Hamster::Hash["A" => 1, "C" => 3]
246
308
  #
247
309
  # @param key [Object] The key to remove
248
310
  # @return [Hash]
@@ -251,20 +313,38 @@ module Hamster
251
313
  end
252
314
 
253
315
  # Call the block once for each key/value pair in this `Hash`, passing the key/value
254
- # pair as parameters. No specific iteration order is guaranteed (but the order will
255
- # be stable for any particular `Hash`.)
316
+ # pair as parameters. No specific iteration order is guaranteed, though the order will
317
+ # be stable for any particular `Hash`.
256
318
  #
319
+ # @example
320
+ # Hamster::Hash["A" => 1, "B" => 2, "C" => 3].each { |k, v| puts "k=#{k} v=#{v}" }
321
+ #
322
+ # k=A v=1
323
+ # k=C v=3
324
+ # k=B v=2
325
+ # # => Hamster::Hash["A" => 1, "B" => 2, "C" => 3]
326
+ #
327
+ # @yield [key, value] Once for each key/value pair.
257
328
  # @return [self]
258
329
  def each(&block)
259
330
  return to_enum if not block_given?
260
331
  @trie.each(&block)
261
332
  self
262
333
  end
263
- def_delegator :self, :each, :each_pair
334
+ alias :each_pair :each
264
335
 
265
336
  # Call the block once for each key/value pair in this `Hash`, passing the key/value
266
337
  # pair as parameters. Iteration order will be the opposite of {#each}.
267
338
  #
339
+ # @example
340
+ # Hamster::Hash["A" => 1, "B" => 2, "C" => 3].reverse_each { |k, v| puts "k=#{k} v=#{v}" }
341
+ #
342
+ # k=B v=2
343
+ # k=C v=3
344
+ # k=A v=1
345
+ # # => Hamster::Hash["A" => 1, "B" => 2, "C" => 3]
346
+ #
347
+ # @yield [key, value] Once for each key/value pair.
268
348
  # @return [self]
269
349
  def reverse_each(&block)
270
350
  return enum_for(:reverse_each) if not block_given?
@@ -273,8 +353,17 @@ module Hamster
273
353
  end
274
354
 
275
355
  # Call the block once for each key/value pair in this `Hash`, passing the key as a
276
- # parameter.
356
+ # parameter. Ordering guarantees are the same as {#each}.
277
357
  #
358
+ # @example
359
+ # Hamster::Hash["A" => 1, "B" => 2, "C" => 3].each_key { |k| puts "k=#{k}" }
360
+ #
361
+ # k=A
362
+ # k=C
363
+ # k=B
364
+ # # => Hamster::Hash["A" => 1, "B" => 2, "C" => 3]
365
+ #
366
+ # @yield [key] Once for each key/value pair.
278
367
  # @return [self]
279
368
  def each_key
280
369
  return enum_for(:each_key) if not block_given?
@@ -283,8 +372,17 @@ module Hamster
283
372
  end
284
373
 
285
374
  # Call the block once for each key/value pair in this `Hash`, passing the value as a
286
- # parameter.
375
+ # parameter. Ordering guarantees are the same as {#each}.
376
+ #
377
+ # @example
378
+ # Hamster::Hash["A" => 1, "B" => 2, "C" => 3].each_value { |v| puts "v=#{v}" }
287
379
  #
380
+ # v=1
381
+ # v=3
382
+ # v=2
383
+ # # => Hamster::Hash["A" => 1, "B" => 2, "C" => 3]
384
+ #
385
+ # @yield [value] Once for each key/value pair.
288
386
  # @return [self]
289
387
  def each_value
290
388
  return enum_for(:each_value) if not block_given?
@@ -296,48 +394,72 @@ module Hamster
296
394
  # pair as parameters. The block should return a `[key, value]` array each time.
297
395
  # All the returned `[key, value]` arrays will be gathered into a new `Hash`.
298
396
  #
397
+ # @example
398
+ # h = Hamster::Hash["A" => 1, "B" => 2, "C" => 3]
399
+ # h.map { |k, v| ["new-#{k}", v * v] }
400
+ # # => Hash["new-C" => 9, "new-B" => 4, "new-A" => 1]
401
+ #
402
+ # @yield [key, value] Once for each key/value pair.
299
403
  # @return [Hash]
300
404
  def map
301
405
  return enum_for(:map) unless block_given?
302
406
  return self if empty?
303
407
  self.class.new(super, &@default)
304
408
  end
305
- def_delegator :self, :map, :collect
306
-
307
- def_delegator :self, :reduce, :foldr
409
+ alias :collect :map
308
410
 
309
411
  # Return a new `Hash` with all the key/value pairs for which the block returns true.
310
412
  #
413
+ # @example
414
+ # h = Hamster::Hash["A" => 1, "B" => 2, "C" => 3]
415
+ # h.select { |k, v| v >= 2 }
416
+ # # => Hamster::Hash["B" => 2, "C" => 3]
417
+ #
418
+ # @yield [key, value] Once for each key/value pair.
419
+ # @yieldreturn Truthy if this pair should be present in the new `Hash`.
311
420
  # @return [Hash]
312
- def filter(&block)
313
- return enum_for(:filter) unless block_given?
314
- derive_new_hash(@trie.filter(&block))
421
+ def select(&block)
422
+ return enum_for(:select) unless block_given?
423
+ derive_new_hash(@trie.select(&block))
315
424
  end
425
+ alias :find_all :select
426
+ alias :keep_if :select
316
427
 
317
428
  # Yield `[key, value]` pairs until one is found for which the block returns true.
318
429
  # Return that `[key, value]` pair. If the block never returns true, return `nil`.
319
430
  #
431
+ # @example
432
+ # h = Hamster::Hash["A" => 1, "B" => 2, "C" => 3]
433
+ # h.find { |k, v| v.even? }
434
+ # # => ["B", 2]
435
+ #
320
436
  # @return [Array]
437
+ # @yield [key, value] At most once for each key/value pair, until the block returns `true`.
438
+ # @yieldreturn Truthy to halt iteration and return the yielded key/value pair.
321
439
  def find
322
440
  return enum_for(:find) unless block_given?
323
441
  each { |entry| return entry if yield entry }
324
442
  nil
325
443
  end
326
- def_delegator :self, :find, :detect
327
-
328
- def_delegator :self, :max, :maximum
329
- def_delegator :self, :min, :minimum
444
+ alias :detect :find
330
445
 
331
446
  # Return a new `Hash` containing all the key/value pairs from this `Hash` and
332
447
  # `other`. If no block is provided, the value for entries with colliding keys
333
- # will be that from `other`. Otherwie, the value for each duplicate key is
334
- # determined by called the block with the key, its value in this `Hash`, and
335
- # its value in `other`.
448
+ # will be that from `other`. Otherwise, the value for each duplicate key is
449
+ # determined by calling the block.
336
450
  #
337
451
  # `other` can be a `Hamster::Hash`, a built-in Ruby `Hash`, or any `Enumerable`
338
452
  # object which yields `[key, value]` pairs.
339
453
  #
340
- # @param other [Enumerable] The collection to merge with
454
+ # @example
455
+ # h1 = Hamster::Hash["A" => 1, "B" => 2, "C" => 3]
456
+ # h2 = Hamster::Hash["C" => 70, "D" => 80]
457
+ # h1.merge(h2)
458
+ # # => Hamster::Hash["C" => 70, "A" => 1, "D" => 80, "B" => 2]
459
+ # h1.merge(h2) { |key, v1, v2| v1 + v2 }
460
+ # # => Hamster::Hash["C" => 73, "A" => 1, "D" => 80, "B" => 2]
461
+ #
462
+ # @param other [::Enumerable] The collection to merge with
341
463
  # @yieldparam key [Object] The key which was present in both collections
342
464
  # @yieldparam my_value [Object] The associated value from this `Hash`
343
465
  # @yieldparam other_value [Object] The associated value from the other collection
@@ -353,17 +475,38 @@ module Hamster
353
475
  end
354
476
  end
355
477
  else
356
- other.reduce(@trie) { |trie, (key, value)| trie.put(key, value) }
478
+ @trie.bulk_put(other)
357
479
  end
358
480
 
359
481
  derive_new_hash(trie)
360
482
  end
361
- def_delegator :self, :merge, :+
362
483
 
363
- # Return a {Vector} which contains all the `[key, value]` pairs in this `Hash`
364
- # as 2-element Arrays, either in their natural sorted order as determined by
365
- # `#<=>`, or if an optional block is supplied, by using the block as a comparator.
366
- # See `Enumerable#sort`.
484
+ # Retrieve the value corresponding to the given key object, or use the provided
485
+ # default value or block, or otherwise raise a `KeyError`.
486
+ #
487
+ # @overload fetch(key)
488
+ # Retrieve the value corresponding to the given key, or raise a `KeyError`
489
+ # if it is not found.
490
+ # @param key [Object] The key to look up
491
+ # @overload fetch(key) { |key| ... }
492
+
493
+ # Return a sorted {Vector} which contains all the `[key, value]` pairs in
494
+ # this `Hash` as two-element `Array`s.
495
+ #
496
+ # @overload sort
497
+ # Uses `#<=>` to determine sorted order.
498
+ # @overload sort { |(k1, v1), (k2, v2)| ... }
499
+ # Uses the block as a comparator to determine sorted order.
500
+ #
501
+ # @example
502
+ # h = Hamster::Hash["Dog" => 1, "Elephant" => 2, "Lion" => 3]
503
+ # h.sort { |(k1, v1), (k2, v2)| k1.size <=> k2.size }
504
+ # # => Hamster::Vector[["Dog", 1], ["Lion", 3], ["Elephant", 2]]
505
+ # @yield [(k1, v1), (k2, v2)] Any number of times with different pairs of key/value associations.
506
+ # @yieldreturn [Integer] Negative if the first pair should be sorted
507
+ # lower, positive if the latter pair, or 0 if equal.
508
+ #
509
+ # @see ::Enumerable#sort
367
510
  #
368
511
  # @return [Vector]
369
512
  def sort
@@ -371,11 +514,19 @@ module Hamster
371
514
  end
372
515
 
373
516
  # Return a {Vector} which contains all the `[key, value]` pairs in this `Hash`
374
- # as 2-element Arrays. The order which the pairs will appear in is determined by
517
+ # as two-element Arrays. The order which the pairs will appear in is determined by
375
518
  # passing each pair to the code block to obtain a sort key object, and comparing
376
519
  # the sort keys using `#<=>`.
377
- # See `Enumerable#sort_by`.
378
520
  #
521
+ # @see ::Enumerable#sort_by
522
+ #
523
+ # @example
524
+ # h = Hamster::Hash["Dog" => 1, "Elephant" => 2, "Lion" => 3]
525
+ # h.sort_by { |key, value| key.size }
526
+ # # => Hamster::Vector[["Dog", 1], ["Lion", 3], ["Elephant", 2]]
527
+ #
528
+ # @yield [key, value] Once for each key/value pair.
529
+ # @yieldreturn a sort key object for the yielded pair.
379
530
  # @return [Vector]
380
531
  def sort_by
381
532
  Vector.new(super)
@@ -383,6 +534,10 @@ module Hamster
383
534
 
384
535
  # Return a new `Hash` with the associations for all of the given `keys` removed.
385
536
  #
537
+ # @example
538
+ # h = Hamster::Hash["A" => 1, "B" => 2, "C" => 3]
539
+ # h.except("A", "C") # => Hamster::Hash["B" => 2]
540
+ #
386
541
  # @param keys [Array] The keys to remove
387
542
  # @return [Hash]
388
543
  def except(*keys)
@@ -390,10 +545,12 @@ module Hamster
390
545
  end
391
546
 
392
547
  # Return a new `Hash` with only the associations for the `wanted` keys retained.
393
- # If any of the `wanted` keys are not present in this `Hash`, they will not be present
394
- # in the returned `Hash` either.
395
548
  #
396
- # @param wanted [Array] The keys to retain
549
+ # @example
550
+ # h = Hamster::Hash["A" => 1, "B" => 2, "C" => 3]
551
+ # h.slice("B", "C") # => Hamster::Hash["B" => 2, "C" => 3]
552
+ #
553
+ # @param wanted [::Enumerable] The keys to retain
397
554
  # @return [Hash]
398
555
  def slice(*wanted)
399
556
  trie = Trie.new(0)
@@ -404,6 +561,10 @@ module Hamster
404
561
  # Return a {Vector} of the values which correspond to the `wanted` keys.
405
562
  # If any of the `wanted` keys are not present in this `Hash`, they will be skipped.
406
563
  #
564
+ # @example
565
+ # h = Hamster::Hash["A" => 1, "B" => 2, "C" => 3]
566
+ # h.values_at("B", "A", "D") # => Hamster::Vector[2, 1]
567
+ #
407
568
  # @param wanted [Array] The keys to retrieve
408
569
  # @return [Vector]
409
570
  def values_at(*wanted)
@@ -412,7 +573,11 @@ module Hamster
412
573
  Vector.new(array.freeze)
413
574
  end
414
575
 
415
- # Return a new {Set} populated with the keys from this `Hash`.
576
+ # Return a new {Set} containing the keys from this `Hash`.
577
+ #
578
+ # @example
579
+ # Hamster::Hash["A" => 1, "B" => 2, "C" => 3, "D" => 2].keys
580
+ # # => Hamster::Set["D", "C", "B", "A"]
416
581
  #
417
582
  # @return [Set]
418
583
  def keys
@@ -421,14 +586,23 @@ module Hamster
421
586
 
422
587
  # Return a new {Vector} populated with the values from this `Hash`.
423
588
  #
589
+ # @example
590
+ # Hamster::Hash["A" => 1, "B" => 2, "C" => 3, "D" => 2].values
591
+ # # => Hamster::Vector[2, 3, 2, 1]
592
+ #
424
593
  # @return [Vector]
425
594
  def values
426
595
  Vector.new(each_value.to_a.freeze)
427
596
  end
428
597
 
429
- # Return a new `Hash` created by using our keys as values, and values as keys.
598
+ # Return a new `Hash` created by using keys as values and values as keys.
430
599
  # If there are multiple values which are equivalent (as determined by `#hash` and
431
- # `#eql?`), only one out of each group of equivalent values will be retained.
600
+ # `#eql?`), only one out of each group of equivalent values will be
601
+ # retained. Which one specifically is undefined.
602
+ #
603
+ # @example
604
+ # Hamster::Hash["A" => 1, "B" => 2, "C" => 3, "D" => 2].invert
605
+ # # => Hamster::Hash[1 => "A", 3 => "C", 2 => "B"]
432
606
  #
433
607
  # @return [Hash]
434
608
  def invert
@@ -447,6 +621,13 @@ module Hamster
447
621
  # As a special case, if `level` is 0, each `[key, value]` pair will be a
448
622
  # separate element in the returned {Vector}.
449
623
  #
624
+ # @example
625
+ # h = Hamster::Hash["A" => 1, "B" => [2, 3, 4]]
626
+ # h.flatten
627
+ # # => Hamster::Vector["A", 1, "B", [2, 3, 4]]
628
+ # h.flatten(2)
629
+ # # => Hamster::Vector["A", 1, "B", 2, 3, 4]
630
+ #
450
631
  # @param level [Integer] The number of times to recursively flatten the `[key, value]` pairs in this `Hash`.
451
632
  # @return [Vector]
452
633
  def flatten(level = 1)
@@ -461,6 +642,9 @@ module Hamster
461
642
  # When a matching key is found, return the `[key, value]` pair as an array.
462
643
  # Return `nil` if no match is found.
463
644
  #
645
+ # @example
646
+ # Hamster::Hash["A" => 1, "B" => 2, "C" => 3].assoc("B") # => ["B", 2]
647
+ #
464
648
  # @param obj [Object] The key to search for (using #==)
465
649
  # @return [Array]
466
650
  def assoc(obj)
@@ -472,6 +656,9 @@ module Hamster
472
656
  # When a matching value is found, return the `[key, value]` pair as an array.
473
657
  # Return `nil` if no match is found.
474
658
  #
659
+ # @example
660
+ # Hamster::Hash["A" => 1, "B" => 2, "C" => 3].rassoc(2) # => ["B", 2]
661
+ #
475
662
  # @param obj [Object] The value to search for (using #==)
476
663
  # @return [Array]
477
664
  def rassoc(obj)
@@ -483,6 +670,9 @@ module Hamster
483
670
  # When a matching value is found, return its associated key object.
484
671
  # Return `nil` if no match is found.
485
672
  #
673
+ # @example
674
+ # Hamster::Hash["A" => 1, "B" => 2, "C" => 3].key(2) # => "B"
675
+ #
486
676
  # @param value [Object] The value to search for (using #==)
487
677
  # @return [Object]
488
678
  def key(value)
@@ -493,6 +683,10 @@ module Hamster
493
683
  # Return a randomly chosen `[key, value]` pair from this `Hash`. If the hash is empty,
494
684
  # return `nil`.
495
685
  #
686
+ # @example
687
+ # Hamster::Hash["A" => 1, "B" => 2, "C" => 3].sample
688
+ # # => ["C", 3]
689
+ #
496
690
  # @return [Array]
497
691
  def sample
498
692
  @trie.at(rand(size))
@@ -537,14 +731,10 @@ module Hamster
537
731
  end
538
732
  end
539
733
 
540
- def_delegator :self, :dup, :uniq
541
- def_delegator :self, :dup, :nub
542
- def_delegator :self, :dup, :remove_duplicates
543
-
544
734
  # Return the contents of this `Hash` as a programmer-readable `String`. If all the
545
735
  # keys and values are serializable as Ruby literal strings, the returned string can
546
- # be passed to `eval` to reconstitute an equivalent `Hash`. However, the default
547
- # block (if there is one) will be lost when doing this.
736
+ # be passed to `eval` to reconstitute an equivalent `Hash`. The default
737
+ # block (if there is one) will be lost when doing this, however.
548
738
  #
549
739
  # @return [String]
550
740
  def inspect
@@ -590,7 +780,7 @@ module Hamster
590
780
  end
591
781
  output
592
782
  end
593
- def_delegator :self, :to_hash, :to_h
783
+ alias :to_h :to_hash
594
784
 
595
785
  # @return [::Hash]
596
786
  # @private
@@ -623,9 +813,10 @@ module Hamster
623
813
  end
624
814
  end
625
815
 
626
- # The canonical empty `Hash`. Returned by `Hamster.hash` and `Hash[]` when
816
+ # The canonical empty `Hash`. Returned by `Hash[]` when
627
817
  # invoked with no arguments; also returned by `Hash.empty`. Prefer using this
628
818
  # one rather than creating many empty hashes using `Hash.new`.
629
819
  #
820
+ # @private
630
821
  EmptyHash = Hamster::Hash.empty
631
822
  end