hamster 1.0.0 → 1.0.1.pre.rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (509) hide show
  1. checksums.yaml +4 -4
  2. data/lib/hamster.rb +2 -3
  3. data/lib/hamster/core_ext.rb +1 -0
  4. data/lib/hamster/core_ext/enumerable.rb +17 -17
  5. data/lib/hamster/core_ext/enumerator.rb +16 -0
  6. data/lib/hamster/core_ext/io.rb +17 -15
  7. data/lib/hamster/enumerable.rb +107 -123
  8. data/lib/hamster/experimental/mutable_queue.rb +6 -2
  9. data/lib/hamster/experimental/mutable_set.rb +3 -1
  10. data/lib/hamster/experimental/mutable_stack.rb +30 -0
  11. data/lib/hamster/hash.rb +95 -713
  12. data/lib/hamster/immutable.rb +0 -4
  13. data/lib/hamster/list.rb +242 -1062
  14. data/lib/hamster/mutable_hash.rb +3 -1
  15. data/lib/hamster/queue.rb +87 -0
  16. data/lib/hamster/read_copy_update.rb +1 -2
  17. data/lib/hamster/set.rb +73 -478
  18. data/lib/hamster/sorter.rb +25 -0
  19. data/lib/hamster/stack.rb +75 -0
  20. data/lib/hamster/trie.rb +48 -199
  21. data/lib/hamster/tuple.rb +39 -0
  22. data/lib/hamster/undefined.rb +3 -1
  23. data/lib/hamster/vector.rb +72 -1326
  24. data/lib/hamster/version.rb +1 -1
  25. data/spec/hamster/core_ext/array_spec.rb +20 -0
  26. data/spec/{lib/hamster → hamster}/core_ext/enumerable_spec.rb +0 -5
  27. data/spec/hamster/core_ext/enumerator_spec.rb +19 -0
  28. data/spec/{lib/hamster → hamster}/core_ext/io_spec.rb +0 -0
  29. data/spec/hamster/experimental/mutable_set/add_qm_spec.rb +47 -0
  30. data/spec/hamster/experimental/mutable_set/add_spec.rb +51 -0
  31. data/spec/hamster/experimental/mutable_set/delete_qm_spec.rb +47 -0
  32. data/spec/hamster/experimental/mutable_set/delete_spec.rb +47 -0
  33. data/spec/hamster/experimental/mutable_stack/pop_spec.rb +41 -0
  34. data/spec/hamster/experimental/mutable_stack/push_spec.rb +41 -0
  35. data/spec/hamster/hash/all_spec.rb +59 -0
  36. data/spec/hamster/hash/any_spec.rb +67 -0
  37. data/spec/hamster/hash/clear_spec.rb +36 -0
  38. data/spec/hamster/hash/construction_spec.rb +35 -0
  39. data/spec/{lib/hamster → hamster}/hash/copying_spec.rb +12 -3
  40. data/spec/hamster/hash/delete_spec.rb +47 -0
  41. data/spec/hamster/hash/each_spec.rb +41 -0
  42. data/spec/hamster/hash/empty_spec.rb +27 -0
  43. data/spec/hamster/hash/eql_spec.rb +62 -0
  44. data/spec/hamster/hash/except_spec.rb +31 -0
  45. data/spec/hamster/hash/fetch_spec.rb +95 -0
  46. data/spec/hamster/hash/filter_spec.rb +63 -0
  47. data/spec/hamster/hash/find_spec.rb +58 -0
  48. data/spec/hamster/hash/get_spec.rb +55 -0
  49. data/spec/hamster/hash/has_key_spec.rb +35 -0
  50. data/spec/hamster/hash/hash_spec.rb +52 -0
  51. data/spec/{lib/hamster → hamster}/hash/immutable_spec.rb +3 -0
  52. data/spec/hamster/hash/inspect_spec.rb +32 -0
  53. data/spec/hamster/hash/keys_spec.rb +21 -0
  54. data/spec/hamster/hash/map_spec.rb +64 -0
  55. data/spec/{lib/hamster → hamster}/hash/marshal_spec.rb +3 -3
  56. data/spec/hamster/hash/merge_spec.rb +36 -0
  57. data/spec/{lib/hamster → hamster}/hash/none_spec.rb +14 -12
  58. data/spec/hamster/hash/put_spec.rb +65 -0
  59. data/spec/hamster/hash/reduce_spec.rb +60 -0
  60. data/spec/hamster/hash/remove_spec.rb +63 -0
  61. data/spec/{lib/hamster → hamster}/hash/size_spec.rb +2 -2
  62. data/spec/hamster/hash/slice_spec.rb +26 -0
  63. data/spec/hamster/hash/uniq_spec.rb +23 -0
  64. data/spec/hamster/hash/values_spec.rb +34 -0
  65. data/spec/{lib/hamster → hamster}/immutable/copying_spec.rb +8 -1
  66. data/spec/{lib/hamster → hamster}/immutable/immutable_spec.rb +14 -1
  67. data/spec/{lib/hamster → hamster}/immutable/memoize_spec.rb +3 -2
  68. data/spec/{lib/hamster → hamster}/immutable/new_spec.rb +0 -0
  69. data/spec/{lib/hamster → hamster}/immutable/transform_spec.rb +0 -0
  70. data/spec/{lib/hamster → hamster}/immutable/transform_unless_spec.rb +0 -0
  71. data/spec/hamster/list/add_spec.rb +16 -0
  72. data/spec/hamster/list/all_spec.rb +111 -0
  73. data/spec/hamster/list/any_spec.rb +79 -0
  74. data/spec/{lib/hamster → hamster}/list/append_spec.rb +22 -11
  75. data/spec/hamster/list/at_spec.rb +49 -0
  76. data/spec/hamster/list/break_spec.rb +85 -0
  77. data/spec/{lib/hamster → hamster}/list/cadr_spec.rb +17 -6
  78. data/spec/{lib/hamster → hamster}/list/chunk_spec.rb +17 -6
  79. data/spec/{lib/hamster → hamster}/list/clear_spec.rb +16 -5
  80. data/spec/hamster/list/combinations_spec.rb +51 -0
  81. data/spec/{lib/hamster → hamster}/list/compact_spec.rb +17 -6
  82. data/spec/hamster/list/cons_spec.rb +41 -0
  83. data/spec/hamster/list/construction_spec.rb +166 -0
  84. data/spec/{lib/hamster → hamster}/list/copying_spec.rb +16 -4
  85. data/spec/hamster/list/count_spec.rb +66 -0
  86. data/spec/hamster/list/cycle_spec.rb +45 -0
  87. data/spec/{lib/hamster → hamster}/list/drop_spec.rb +17 -6
  88. data/spec/hamster/list/drop_while_spec.rb +59 -0
  89. data/spec/hamster/list/each_slice_spec.rb +80 -0
  90. data/spec/hamster/list/each_spec.rb +72 -0
  91. data/spec/hamster/list/each_with_index_spec.rb +42 -0
  92. data/spec/hamster/list/elem_index_spec.rb +58 -0
  93. data/spec/hamster/list/elem_indices_spec.rb +45 -0
  94. data/spec/hamster/list/empty_spec.rb +47 -0
  95. data/spec/hamster/list/eql_spec.rb +78 -0
  96. data/spec/hamster/list/filter_spec.rb +70 -0
  97. data/spec/{lib/hamster → hamster}/list/find_all_spec.rb +2 -3
  98. data/spec/{lib/hamster → hamster}/list/find_index_spec.rb +27 -5
  99. data/spec/hamster/list/find_indices_spec.rb +45 -0
  100. data/spec/{lib/hamster → hamster}/list/find_spec.rb +33 -11
  101. data/spec/{lib/hamster → hamster}/list/flat_map_spec.rb +0 -0
  102. data/spec/{lib/hamster → hamster}/list/flatten_spec.rb +17 -6
  103. data/spec/{lib/hamster → hamster}/list/grep_spec.rb +33 -10
  104. data/spec/{lib/hamster → hamster}/list/group_by_spec.rb +44 -9
  105. data/spec/{lib/hamster → hamster}/list/hash_spec.rb +12 -4
  106. data/spec/{lib/hamster → hamster}/list/head_spec.rb +18 -3
  107. data/spec/{lib/hamster → hamster}/list/include_spec.rb +27 -6
  108. data/spec/{lib/hamster → hamster}/list/init_spec.rb +17 -6
  109. data/spec/hamster/list/inits_spec.rb +42 -0
  110. data/spec/hamster/list/inspect_spec.rb +43 -0
  111. data/spec/{lib/hamster → hamster}/list/intersperse_spec.rb +17 -6
  112. data/spec/hamster/list/join_spec.rb +81 -0
  113. data/spec/hamster/list/last_spec.rb +44 -0
  114. data/spec/{lib/hamster → hamster}/list/map_spec.rb +35 -12
  115. data/spec/hamster/list/maximum_spec.rb +77 -0
  116. data/spec/{lib/hamster → hamster}/list/merge_by_spec.rb +32 -5
  117. data/spec/{lib/hamster → hamster}/list/merge_spec.rb +20 -1
  118. data/spec/hamster/list/minimum_spec.rb +77 -0
  119. data/spec/{lib/hamster → hamster}/list/none_spec.rb +39 -12
  120. data/spec/{lib/hamster → hamster}/list/one_spec.rb +38 -13
  121. data/spec/hamster/list/partition_spec.rb +75 -0
  122. data/spec/{lib/hamster → hamster}/list/pop_spec.rb +1 -1
  123. data/spec/hamster/list/product_spec.rb +44 -0
  124. data/spec/hamster/list/reduce_spec.rb +73 -0
  125. data/spec/{lib/hamster/list/reject_spec.rb → hamster/list/remove_spec.rb} +35 -11
  126. data/spec/{lib/hamster → hamster}/list/reverse_spec.rb +25 -8
  127. data/spec/{lib/hamster → hamster}/list/select_spec.rb +2 -3
  128. data/spec/{lib/hamster → hamster}/list/size_spec.rb +26 -5
  129. data/spec/hamster/list/slice_spec.rb +50 -0
  130. data/spec/{lib/hamster → hamster}/list/sorting_spec.rb +34 -11
  131. data/spec/hamster/list/span_spec.rb +86 -0
  132. data/spec/{lib/hamster → hamster}/list/split_at_spec.rb +23 -14
  133. data/spec/hamster/list/sum_spec.rb +44 -0
  134. data/spec/hamster/list/tail_spec.rb +48 -0
  135. data/spec/hamster/list/tails_spec.rb +42 -0
  136. data/spec/{lib/hamster → hamster}/list/take_spec.rb +17 -6
  137. data/spec/{lib/hamster → hamster}/list/take_while_spec.rb +18 -11
  138. data/spec/hamster/list/to_a_spec.rb +54 -0
  139. data/spec/{lib/hamster → hamster}/list/to_ary_spec.rb +4 -1
  140. data/spec/{lib/hamster → hamster}/list/to_list_spec.rb +16 -4
  141. data/spec/hamster/list/to_set_spec.rb +33 -0
  142. data/spec/{lib/hamster → hamster}/list/union_spec.rb +23 -6
  143. data/spec/hamster/list/uniq_spec.rb +45 -0
  144. data/spec/{lib/hamster → hamster}/list/zip_spec.rb +9 -2
  145. data/spec/hamster/queue/clear_spec.rb +36 -0
  146. data/spec/hamster/queue/construction_spec.rb +43 -0
  147. data/spec/hamster/queue/dequeue_spec.rb +40 -0
  148. data/spec/hamster/queue/empty_spec.rb +47 -0
  149. data/spec/{lib/hamster/deque → hamster/queue}/enqueue_spec.rb +21 -8
  150. data/spec/hamster/queue/head_spec.rb +35 -0
  151. data/spec/hamster/queue/inspect_spec.rb +31 -0
  152. data/spec/{lib/hamster/deque → hamster/queue}/size_spec.rb +20 -5
  153. data/spec/hamster/queue/to_a_spec.rb +42 -0
  154. data/spec/{lib/hamster/deque → hamster/queue}/to_ary_spec.rb +6 -6
  155. data/spec/hamster/queue/to_list_spec.rb +44 -0
  156. data/spec/hamster/set/add_spec.rb +51 -0
  157. data/spec/hamster/set/all_spec.rb +67 -0
  158. data/spec/hamster/set/any_spec.rb +67 -0
  159. data/spec/hamster/set/clear_spec.rb +36 -0
  160. data/spec/{lib/hamster → hamster}/set/compact_spec.rb +16 -5
  161. data/spec/{lib/hamster → hamster}/set/construction_spec.rb +17 -5
  162. data/spec/{lib/hamster → hamster}/set/copying_spec.rb +12 -3
  163. data/spec/{lib/hamster → hamster}/set/count_spec.rb +28 -11
  164. data/spec/hamster/set/delete_spec.rb +47 -0
  165. data/spec/{lib/hamster/sorted_set → hamster/set}/difference_spec.rb +21 -7
  166. data/spec/{lib/hamster/set/reverse_each_spec.rb → hamster/set/each_spec.rb} +7 -8
  167. data/spec/hamster/set/empty_spec.rb +35 -0
  168. data/spec/{lib/hamster → hamster}/set/eqeq_spec.rb +0 -0
  169. data/spec/{lib/hamster → hamster}/set/eql_spec.rb +1 -7
  170. data/spec/{lib/hamster/sorted_set → hamster/set}/exclusion_spec.rb +20 -5
  171. data/spec/hamster/set/filter_spec.rb +79 -0
  172. data/spec/{lib/hamster → hamster}/set/find_spec.rb +25 -8
  173. data/spec/hamster/set/flatten_spec.rb +49 -0
  174. data/spec/hamster/set/foreach_spec.rb +39 -0
  175. data/spec/{lib/hamster → hamster}/set/grep_spec.rb +1 -1
  176. data/spec/hamster/set/group_by_spec.rb +65 -0
  177. data/spec/hamster/set/hash_spec.rb +20 -0
  178. data/spec/hamster/set/head_spec.rb +39 -0
  179. data/spec/{lib/hamster → hamster}/set/immutable_spec.rb +4 -1
  180. data/spec/hamster/set/include_spec.rb +35 -0
  181. data/spec/hamster/set/inspect_spec.rb +32 -0
  182. data/spec/hamster/set/intersection_spec.rb +46 -0
  183. data/spec/{lib/hamster/vector → hamster/set}/join_spec.rb +33 -23
  184. data/spec/hamster/set/map_spec.rb +64 -0
  185. data/spec/{lib/hamster → hamster}/set/marshal_spec.rb +9 -4
  186. data/spec/hamster/set/maximum_spec.rb +65 -0
  187. data/spec/hamster/set/minimum_spec.rb +65 -0
  188. data/spec/{lib/hamster → hamster}/set/none_spec.rb +30 -15
  189. data/spec/{lib/hamster → hamster}/set/one_spec.rb +29 -14
  190. data/spec/hamster/set/partition_spec.rb +71 -0
  191. data/spec/{lib/hamster → hamster}/set/product_spec.rb +15 -7
  192. data/spec/hamster/set/reduce_spec.rb +87 -0
  193. data/spec/hamster/set/remove_spec.rb +63 -0
  194. data/spec/{lib/hamster → hamster}/set/size_spec.rb +10 -1
  195. data/spec/{lib/hamster → hamster}/set/sorting_spec.rb +16 -18
  196. data/spec/hamster/set/subset_spec.rb +39 -0
  197. data/spec/{lib/hamster/vector → hamster/set}/sum_spec.rb +18 -4
  198. data/spec/hamster/set/superset_spec.rb +39 -0
  199. data/spec/hamster/set/to_a_spec.rb +42 -0
  200. data/spec/{lib/hamster/vector → hamster/set}/to_list_spec.rb +23 -8
  201. data/spec/{lib/hamster → hamster}/set/to_set_spec.rb +15 -3
  202. data/spec/hamster/set/union_spec.rb +45 -0
  203. data/spec/hamster/set/uniq_spec.rb +23 -0
  204. data/spec/hamster/sorter/immutable_spec.rb +12 -0
  205. data/spec/hamster/stack/clear_spec.rb +36 -0
  206. data/spec/hamster/stack/construction_spec.rb +43 -0
  207. data/spec/hamster/stack/copying_spec.rb +31 -0
  208. data/spec/hamster/stack/empty_spec.rb +31 -0
  209. data/spec/hamster/stack/eql_spec.rb +60 -0
  210. data/spec/hamster/stack/immutable_spec.rb +12 -0
  211. data/spec/hamster/stack/inspect_spec.rb +31 -0
  212. data/spec/hamster/stack/peek_spec.rb +40 -0
  213. data/spec/hamster/stack/pop_spec.rb +41 -0
  214. data/spec/hamster/stack/push_spec.rb +41 -0
  215. data/spec/hamster/stack/size_spec.rb +35 -0
  216. data/spec/hamster/stack/to_a_spec.rb +42 -0
  217. data/spec/hamster/stack/to_ary.rb +37 -0
  218. data/spec/hamster/stack/to_list_spec.rb +33 -0
  219. data/spec/hamster/trie/remove_spec.rb +117 -0
  220. data/spec/hamster/tuple/copying_spec.rb +24 -0
  221. data/spec/hamster/tuple/eql_spec.rb +61 -0
  222. data/spec/hamster/tuple/first_spec.rb +19 -0
  223. data/spec/hamster/tuple/immutable_spec.rb +12 -0
  224. data/spec/hamster/tuple/inspect_spec.rb +19 -0
  225. data/spec/hamster/tuple/last_spec.rb +19 -0
  226. data/spec/hamster/tuple/to_a_spec.rb +38 -0
  227. data/spec/hamster/tuple/to_ary_spec.rb +38 -0
  228. data/spec/hamster/undefined/erase_spec.rb +47 -0
  229. data/spec/hamster/vector/add_spec.rb +48 -0
  230. data/spec/{lib/hamster → hamster}/vector/any_spec.rb +0 -0
  231. data/spec/hamster/vector/clear_spec.rb +35 -0
  232. data/spec/{lib/hamster → hamster}/vector/copying_spec.rb +14 -4
  233. data/spec/hamster/vector/each_spec.rb +45 -0
  234. data/spec/hamster/vector/each_with_index_spec.rb +41 -0
  235. data/spec/hamster/vector/empty_spec.rb +34 -0
  236. data/spec/hamster/vector/eql_spec.rb +64 -0
  237. data/spec/hamster/vector/filter_spec.rb +62 -0
  238. data/spec/hamster/vector/first_spec.rb +35 -0
  239. data/spec/hamster/vector/get_spec.rb +80 -0
  240. data/spec/{lib/hamster → hamster}/vector/include_spec.rb +17 -4
  241. data/spec/hamster/vector/inspect_spec.rb +33 -0
  242. data/spec/{lib/hamster → hamster}/vector/last_spec.rb +3 -12
  243. data/spec/{lib/hamster → hamster}/vector/length_spec.rb +3 -12
  244. data/spec/hamster/vector/map_spec.rb +63 -0
  245. data/spec/{lib/hamster → hamster}/vector/reduce_spec.rb +47 -16
  246. data/spec/hamster/vector/set_spec.rb +113 -0
  247. data/spec/{lib/hamster → hamster}/vector/to_a_spec.rb +12 -11
  248. data/spec/{lib/hamster → hamster}/vector/to_ary_spec.rb +0 -0
  249. data/spec/lib/hamster/vector/cons_spec.rb +48 -0
  250. data/spec/lib/hamster/vector/exist_spec.rb +70 -0
  251. data/spec/lib/hamster/vector/exists_spec.rb +70 -0
  252. data/spec/lib/hamster/vector/ltlt_spec.rb +2 -20
  253. data/spec/spec_helper.rb +5 -36
  254. metadata +510 -723
  255. data/lib/hamster/deque.rb +0 -252
  256. data/lib/hamster/nested.rb +0 -36
  257. data/lib/hamster/sorted_set.rb +0 -1397
  258. data/spec/lib/hamster/core_ext/array_spec.rb +0 -14
  259. data/spec/lib/hamster/deque/clear_spec.rb +0 -34
  260. data/spec/lib/hamster/deque/construction_spec.rb +0 -30
  261. data/spec/lib/hamster/deque/copying_spec.rb +0 -20
  262. data/spec/lib/hamster/deque/dequeue_spec.rb +0 -35
  263. data/spec/lib/hamster/deque/empty_spec.rb +0 -40
  264. data/spec/lib/hamster/deque/first_spec.rb +0 -18
  265. data/spec/lib/hamster/deque/inspect_spec.rb +0 -24
  266. data/spec/lib/hamster/deque/last_spec.rb +0 -18
  267. data/spec/lib/hamster/deque/marshal_spec.rb +0 -34
  268. data/spec/lib/hamster/deque/new_spec.rb +0 -44
  269. data/spec/lib/hamster/deque/pop_spec.rb +0 -33
  270. data/spec/lib/hamster/deque/pretty_print_spec.rb +0 -24
  271. data/spec/lib/hamster/deque/random_modification_spec.rb +0 -34
  272. data/spec/lib/hamster/deque/to_a_spec.rb +0 -27
  273. data/spec/lib/hamster/deque/to_list_spec.rb +0 -26
  274. data/spec/lib/hamster/deque/unshift_spec.rb +0 -26
  275. data/spec/lib/hamster/experimental/mutable_set/add_qm_spec.rb +0 -39
  276. data/spec/lib/hamster/experimental/mutable_set/add_spec.rb +0 -37
  277. data/spec/lib/hamster/experimental/mutable_set/delete_qm_spec.rb +0 -38
  278. data/spec/lib/hamster/experimental/mutable_set/delete_spec.rb +0 -37
  279. data/spec/lib/hamster/hash/all_spec.rb +0 -54
  280. data/spec/lib/hamster/hash/any_spec.rb +0 -54
  281. data/spec/lib/hamster/hash/assoc_spec.rb +0 -52
  282. data/spec/lib/hamster/hash/clear_spec.rb +0 -43
  283. data/spec/lib/hamster/hash/construction_spec.rb +0 -39
  284. data/spec/lib/hamster/hash/default_proc_spec.rb +0 -73
  285. data/spec/lib/hamster/hash/delete_spec.rb +0 -40
  286. data/spec/lib/hamster/hash/each_spec.rb +0 -78
  287. data/spec/lib/hamster/hash/each_with_index_spec.rb +0 -30
  288. data/spec/lib/hamster/hash/empty_spec.rb +0 -44
  289. data/spec/lib/hamster/hash/eql_spec.rb +0 -70
  290. data/spec/lib/hamster/hash/except_spec.rb +0 -43
  291. data/spec/lib/hamster/hash/fetch_spec.rb +0 -58
  292. data/spec/lib/hamster/hash/find_spec.rb +0 -44
  293. data/spec/lib/hamster/hash/flat_map_spec.rb +0 -36
  294. data/spec/lib/hamster/hash/flatten_spec.rb +0 -99
  295. data/spec/lib/hamster/hash/get_spec.rb +0 -80
  296. data/spec/lib/hamster/hash/has_key_spec.rb +0 -32
  297. data/spec/lib/hamster/hash/has_value_spec.rb +0 -28
  298. data/spec/lib/hamster/hash/hash_spec.rb +0 -30
  299. data/spec/lib/hamster/hash/inspect_spec.rb +0 -31
  300. data/spec/lib/hamster/hash/invert_spec.rb +0 -31
  301. data/spec/lib/hamster/hash/key_spec.rb +0 -28
  302. data/spec/lib/hamster/hash/keys_spec.rb +0 -17
  303. data/spec/lib/hamster/hash/map_spec.rb +0 -46
  304. data/spec/lib/hamster/hash/merge_spec.rb +0 -83
  305. data/spec/lib/hamster/hash/min_max_spec.rb +0 -46
  306. data/spec/lib/hamster/hash/new_spec.rb +0 -71
  307. data/spec/lib/hamster/hash/partition_spec.rb +0 -36
  308. data/spec/lib/hamster/hash/pretty_print_spec.rb +0 -35
  309. data/spec/lib/hamster/hash/put_spec.rb +0 -103
  310. data/spec/lib/hamster/hash/reduce_spec.rb +0 -36
  311. data/spec/lib/hamster/hash/reject_spec.rb +0 -62
  312. data/spec/lib/hamster/hash/reverse_each_spec.rb +0 -28
  313. data/spec/lib/hamster/hash/sample_spec.rb +0 -14
  314. data/spec/lib/hamster/hash/select_spec.rb +0 -58
  315. data/spec/lib/hamster/hash/slice_spec.rb +0 -45
  316. data/spec/lib/hamster/hash/sort_spec.rb +0 -27
  317. data/spec/lib/hamster/hash/store_spec.rb +0 -76
  318. data/spec/lib/hamster/hash/take_spec.rb +0 -36
  319. data/spec/lib/hamster/hash/to_a_spec.rb +0 -14
  320. data/spec/lib/hamster/hash/to_hash_spec.rb +0 -22
  321. data/spec/lib/hamster/hash/update_in_spec.rb +0 -80
  322. data/spec/lib/hamster/hash/values_at_spec.rb +0 -14
  323. data/spec/lib/hamster/hash/values_spec.rb +0 -25
  324. data/spec/lib/hamster/list/add_spec.rb +0 -26
  325. data/spec/lib/hamster/list/all_spec.rb +0 -58
  326. data/spec/lib/hamster/list/any_spec.rb +0 -50
  327. data/spec/lib/hamster/list/at_spec.rb +0 -30
  328. data/spec/lib/hamster/list/break_spec.rb +0 -70
  329. data/spec/lib/hamster/list/combination_spec.rb +0 -34
  330. data/spec/lib/hamster/list/compare_spec.rb +0 -31
  331. data/spec/lib/hamster/list/cons_spec.rb +0 -26
  332. data/spec/lib/hamster/list/construction_spec.rb +0 -111
  333. data/spec/lib/hamster/list/count_spec.rb +0 -37
  334. data/spec/lib/hamster/list/cycle_spec.rb +0 -29
  335. data/spec/lib/hamster/list/delete_at_spec.rb +0 -19
  336. data/spec/lib/hamster/list/delete_spec.rb +0 -17
  337. data/spec/lib/hamster/list/drop_while_spec.rb +0 -39
  338. data/spec/lib/hamster/list/each_slice_spec.rb +0 -52
  339. data/spec/lib/hamster/list/each_spec.rb +0 -41
  340. data/spec/lib/hamster/list/each_with_index_spec.rb +0 -29
  341. data/spec/lib/hamster/list/empty_spec.rb +0 -24
  342. data/spec/lib/hamster/list/eql_spec.rb +0 -62
  343. data/spec/lib/hamster/list/fill_spec.rb +0 -50
  344. data/spec/lib/hamster/list/index_spec.rb +0 -34
  345. data/spec/lib/hamster/list/indices_spec.rb +0 -62
  346. data/spec/lib/hamster/list/inits_spec.rb +0 -29
  347. data/spec/lib/hamster/list/insert_spec.rb +0 -47
  348. data/spec/lib/hamster/list/inspect_spec.rb +0 -30
  349. data/spec/lib/hamster/list/join_spec.rb +0 -64
  350. data/spec/lib/hamster/list/last_spec.rb +0 -24
  351. data/spec/lib/hamster/list/ltlt_spec.rb +0 -20
  352. data/spec/lib/hamster/list/maximum_spec.rb +0 -40
  353. data/spec/lib/hamster/list/minimum_spec.rb +0 -40
  354. data/spec/lib/hamster/list/multithreading_spec.rb +0 -48
  355. data/spec/lib/hamster/list/partition_spec.rb +0 -116
  356. data/spec/lib/hamster/list/permutation_spec.rb +0 -56
  357. data/spec/lib/hamster/list/product_spec.rb +0 -24
  358. data/spec/lib/hamster/list/reduce_spec.rb +0 -54
  359. data/spec/lib/hamster/list/rotate_spec.rb +0 -37
  360. data/spec/lib/hamster/list/sample_spec.rb +0 -14
  361. data/spec/lib/hamster/list/slice_spec.rb +0 -230
  362. data/spec/lib/hamster/list/span_spec.rb +0 -77
  363. data/spec/lib/hamster/list/subsequences_spec.rb +0 -24
  364. data/spec/lib/hamster/list/sum_spec.rb +0 -24
  365. data/spec/lib/hamster/list/tail_spec.rb +0 -31
  366. data/spec/lib/hamster/list/tails_spec.rb +0 -29
  367. data/spec/lib/hamster/list/to_a_spec.rb +0 -40
  368. data/spec/lib/hamster/list/to_set_spec.rb +0 -19
  369. data/spec/lib/hamster/list/transpose_spec.rb +0 -20
  370. data/spec/lib/hamster/list/uniq_spec.rb +0 -30
  371. data/spec/lib/hamster/nested/construction_spec.rb +0 -44
  372. data/spec/lib/hamster/set/add_spec.rb +0 -76
  373. data/spec/lib/hamster/set/all_spec.rb +0 -52
  374. data/spec/lib/hamster/set/any_spec.rb +0 -52
  375. data/spec/lib/hamster/set/clear_spec.rb +0 -34
  376. data/spec/lib/hamster/set/delete_spec.rb +0 -72
  377. data/spec/lib/hamster/set/difference_spec.rb +0 -50
  378. data/spec/lib/hamster/set/disjoint_spec.rb +0 -26
  379. data/spec/lib/hamster/set/each_spec.rb +0 -46
  380. data/spec/lib/hamster/set/empty_spec.rb +0 -45
  381. data/spec/lib/hamster/set/exclusion_spec.rb +0 -48
  382. data/spec/lib/hamster/set/first_spec.rb +0 -29
  383. data/spec/lib/hamster/set/flatten_spec.rb +0 -47
  384. data/spec/lib/hamster/set/group_by_spec.rb +0 -60
  385. data/spec/lib/hamster/set/hash_spec.rb +0 -23
  386. data/spec/lib/hamster/set/include_spec.rb +0 -61
  387. data/spec/lib/hamster/set/inspect_spec.rb +0 -48
  388. data/spec/lib/hamster/set/intersect_spec.rb +0 -26
  389. data/spec/lib/hamster/set/intersection_spec.rb +0 -53
  390. data/spec/lib/hamster/set/join_spec.rb +0 -65
  391. data/spec/lib/hamster/set/map_spec.rb +0 -60
  392. data/spec/lib/hamster/set/maximum_spec.rb +0 -37
  393. data/spec/lib/hamster/set/minimum_spec.rb +0 -37
  394. data/spec/lib/hamster/set/new_spec.rb +0 -54
  395. data/spec/lib/hamster/set/partition_spec.rb +0 -53
  396. data/spec/lib/hamster/set/reduce_spec.rb +0 -56
  397. data/spec/lib/hamster/set/reject_spec.rb +0 -51
  398. data/spec/lib/hamster/set/sample_spec.rb +0 -14
  399. data/spec/lib/hamster/set/select_spec.rb +0 -74
  400. data/spec/lib/hamster/set/subset_spec.rb +0 -52
  401. data/spec/lib/hamster/set/sum_spec.rb +0 -24
  402. data/spec/lib/hamster/set/superset_spec.rb +0 -52
  403. data/spec/lib/hamster/set/to_a_spec.rb +0 -31
  404. data/spec/lib/hamster/set/to_list_spec.rb +0 -37
  405. data/spec/lib/hamster/set/union_spec.rb +0 -64
  406. data/spec/lib/hamster/sorted_set/above_spec.rb +0 -52
  407. data/spec/lib/hamster/sorted_set/add_spec.rb +0 -63
  408. data/spec/lib/hamster/sorted_set/at_spec.rb +0 -25
  409. data/spec/lib/hamster/sorted_set/below_spec.rb +0 -52
  410. data/spec/lib/hamster/sorted_set/between_spec.rb +0 -52
  411. data/spec/lib/hamster/sorted_set/clear_spec.rb +0 -44
  412. data/spec/lib/hamster/sorted_set/construction_spec.rb +0 -29
  413. data/spec/lib/hamster/sorted_set/delete_at_spec.rb +0 -19
  414. data/spec/lib/hamster/sorted_set/delete_spec.rb +0 -90
  415. data/spec/lib/hamster/sorted_set/disjoint_spec.rb +0 -26
  416. data/spec/lib/hamster/sorted_set/drop_spec.rb +0 -56
  417. data/spec/lib/hamster/sorted_set/drop_while_spec.rb +0 -35
  418. data/spec/lib/hamster/sorted_set/each_spec.rb +0 -29
  419. data/spec/lib/hamster/sorted_set/empty_spec.rb +0 -35
  420. data/spec/lib/hamster/sorted_set/eql_spec.rb +0 -121
  421. data/spec/lib/hamster/sorted_set/fetch_spec.rb +0 -65
  422. data/spec/lib/hamster/sorted_set/find_index_spec.rb +0 -41
  423. data/spec/lib/hamster/sorted_set/first_spec.rb +0 -19
  424. data/spec/lib/hamster/sorted_set/from_spec.rb +0 -52
  425. data/spec/lib/hamster/sorted_set/group_by_spec.rb +0 -58
  426. data/spec/lib/hamster/sorted_set/include_spec.rb +0 -24
  427. data/spec/lib/hamster/sorted_set/inspect_spec.rb +0 -38
  428. data/spec/lib/hamster/sorted_set/intersect_spec.rb +0 -26
  429. data/spec/lib/hamster/sorted_set/intersection_spec.rb +0 -29
  430. data/spec/lib/hamster/sorted_set/last_spec.rb +0 -37
  431. data/spec/lib/hamster/sorted_set/map_spec.rb +0 -36
  432. data/spec/lib/hamster/sorted_set/marshal_spec.rb +0 -37
  433. data/spec/lib/hamster/sorted_set/maximum_spec.rb +0 -37
  434. data/spec/lib/hamster/sorted_set/minimum_spec.rb +0 -20
  435. data/spec/lib/hamster/sorted_set/new_spec.rb +0 -52
  436. data/spec/lib/hamster/sorted_set/reverse_each_spec.rb +0 -29
  437. data/spec/lib/hamster/sorted_set/sample_spec.rb +0 -14
  438. data/spec/lib/hamster/sorted_set/select_spec.rb +0 -62
  439. data/spec/lib/hamster/sorted_set/size_spec.rb +0 -18
  440. data/spec/lib/hamster/sorted_set/slice_spec.rb +0 -257
  441. data/spec/lib/hamster/sorted_set/sorting_spec.rb +0 -45
  442. data/spec/lib/hamster/sorted_set/subset_spec.rb +0 -48
  443. data/spec/lib/hamster/sorted_set/superset_spec.rb +0 -48
  444. data/spec/lib/hamster/sorted_set/take_spec.rb +0 -55
  445. data/spec/lib/hamster/sorted_set/take_while_spec.rb +0 -34
  446. data/spec/lib/hamster/sorted_set/to_set_spec.rb +0 -19
  447. data/spec/lib/hamster/sorted_set/union_spec.rb +0 -28
  448. data/spec/lib/hamster/sorted_set/up_to_spec.rb +0 -52
  449. data/spec/lib/hamster/sorted_set/values_at_spec.rb +0 -34
  450. data/spec/lib/hamster/vector/add_spec.rb +0 -68
  451. data/spec/lib/hamster/vector/assoc_spec.rb +0 -36
  452. data/spec/lib/hamster/vector/bsearch_spec.rb +0 -58
  453. data/spec/lib/hamster/vector/clear_spec.rb +0 -34
  454. data/spec/lib/hamster/vector/combination_spec.rb +0 -82
  455. data/spec/lib/hamster/vector/compact_spec.rb +0 -30
  456. data/spec/lib/hamster/vector/compare_spec.rb +0 -32
  457. data/spec/lib/hamster/vector/concat_spec.rb +0 -35
  458. data/spec/lib/hamster/vector/count_spec.rb +0 -18
  459. data/spec/lib/hamster/vector/delete_at_spec.rb +0 -54
  460. data/spec/lib/hamster/vector/delete_spec.rb +0 -31
  461. data/spec/lib/hamster/vector/drop_spec.rb +0 -42
  462. data/spec/lib/hamster/vector/drop_while_spec.rb +0 -55
  463. data/spec/lib/hamster/vector/each_index_spec.rb +0 -41
  464. data/spec/lib/hamster/vector/each_spec.rb +0 -45
  465. data/spec/lib/hamster/vector/each_with_index_spec.rb +0 -40
  466. data/spec/lib/hamster/vector/empty_spec.rb +0 -42
  467. data/spec/lib/hamster/vector/eql_spec.rb +0 -77
  468. data/spec/lib/hamster/vector/fetch_spec.rb +0 -65
  469. data/spec/lib/hamster/vector/fill_spec.rb +0 -89
  470. data/spec/lib/hamster/vector/first_spec.rb +0 -19
  471. data/spec/lib/hamster/vector/flat_map_spec.rb +0 -51
  472. data/spec/lib/hamster/vector/flatten_spec.rb +0 -44
  473. data/spec/lib/hamster/vector/get_spec.rb +0 -75
  474. data/spec/lib/hamster/vector/group_by_spec.rb +0 -58
  475. data/spec/lib/hamster/vector/insert_spec.rb +0 -69
  476. data/spec/lib/hamster/vector/inspect_spec.rb +0 -50
  477. data/spec/lib/hamster/vector/map_spec.rb +0 -52
  478. data/spec/lib/hamster/vector/marshal_spec.rb +0 -32
  479. data/spec/lib/hamster/vector/maximum_spec.rb +0 -34
  480. data/spec/lib/hamster/vector/minimum_spec.rb +0 -34
  481. data/spec/lib/hamster/vector/multiply_spec.rb +0 -48
  482. data/spec/lib/hamster/vector/new_spec.rb +0 -51
  483. data/spec/lib/hamster/vector/partition_spec.rb +0 -53
  484. data/spec/lib/hamster/vector/permutation_spec.rb +0 -92
  485. data/spec/lib/hamster/vector/pop_spec.rb +0 -27
  486. data/spec/lib/hamster/vector/product_spec.rb +0 -71
  487. data/spec/lib/hamster/vector/reject_spec.rb +0 -44
  488. data/spec/lib/hamster/vector/repeated_combination_spec.rb +0 -78
  489. data/spec/lib/hamster/vector/repeated_permutation_spec.rb +0 -94
  490. data/spec/lib/hamster/vector/reverse_each_spec.rb +0 -32
  491. data/spec/lib/hamster/vector/reverse_spec.rb +0 -22
  492. data/spec/lib/hamster/vector/rindex_spec.rb +0 -37
  493. data/spec/lib/hamster/vector/rotate_spec.rb +0 -74
  494. data/spec/lib/hamster/vector/sample_spec.rb +0 -14
  495. data/spec/lib/hamster/vector/select_spec.rb +0 -64
  496. data/spec/lib/hamster/vector/set_spec.rb +0 -175
  497. data/spec/lib/hamster/vector/shift_spec.rb +0 -28
  498. data/spec/lib/hamster/vector/shuffle_spec.rb +0 -44
  499. data/spec/lib/hamster/vector/slice_spec.rb +0 -241
  500. data/spec/lib/hamster/vector/sorting_spec.rb +0 -57
  501. data/spec/lib/hamster/vector/take_spec.rb +0 -43
  502. data/spec/lib/hamster/vector/take_while_spec.rb +0 -35
  503. data/spec/lib/hamster/vector/to_set_spec.rb +0 -23
  504. data/spec/lib/hamster/vector/transpose_spec.rb +0 -49
  505. data/spec/lib/hamster/vector/uniq_spec.rb +0 -56
  506. data/spec/lib/hamster/vector/unshift_spec.rb +0 -29
  507. data/spec/lib/hamster/vector/update_in_spec.rb +0 -83
  508. data/spec/lib/hamster/vector/values_at_spec.rb +0 -34
  509. data/spec/lib/hamster/vector/zip_spec.rb +0 -58
@@ -1,5 +1,7 @@
1
1
  module Hamster
2
- # @private
3
2
  module Undefined
3
+ def self.erase(value)
4
+ value unless value.equal?(self)
5
+ end
4
6
  end
5
7
  end
@@ -1,1409 +1,155 @@
1
+ require "forwardable"
2
+ require "hamster/undefined"
1
3
  require "hamster/immutable"
2
4
  require "hamster/enumerable"
3
- require "hamster/hash"
4
5
 
5
6
  module Hamster
6
- # Create a new `Vector` populated with the given items.
7
- # [Vector]
8
7
  def self.vector(*items)
9
- items.empty? ? EmptyVector : Vector.new(items.freeze)
8
+ items.reduce(EmptyVector) { |vector, item| vector.add(item) }
10
9
  end
11
10
 
12
- # A `Vector` is an ordered, integer-indexed collection of objects. Like `Array`,
13
- # `Vector` indexing starts at 0. Also like `Array`, negative indexes count back
14
- # from the end of the `Vector`.
15
- #
16
- # `Vector`'s interface is modeled after that of `Array`, minus all the methods
17
- # which do destructive updates. Some methods which modify `Array`s destructively
18
- # (like {#insert} or {#delete_at}) are included, but they return new `Vectors`
19
- # and leave the existing one unchanged.
20
- #
21
- # ### Creating New Vectors
22
- #
23
- # Hamster.vector('a', 'b', 'c')
24
- # Hamster::Vector.new([:first, :second, :third])
25
- # Hamster::Vector[1, 2, 3, 4, 5]
26
- #
27
- # ### Retrieving Items from Vectors
28
- #
29
- # require 'hamster/vector'
30
- # vector = Hamster.vector(1, 2, 3, 4, 5)
31
- # vector[0] # => 1
32
- # vector[-1] # => 5
33
- # vector[0,3] # => Hamster::Vector[1, 2, 3]
34
- # vector[1..-1] # => Hamster::Vector[2, 3, 4, 5]
35
- # vector.first # => 1
36
- # vector.last # => 5
37
- #
38
- # ### Creating Modified Vectors
39
- #
40
- # vector.add(6) # => Hamster::Vector[1, 2, 3, 4, 5, 6]
41
- # vector.insert(1, :a, :b) # => Hamster::Vector[1, :a, :b, 2, 3, 4, 5]
42
- # vector.delete_at(2) # => Hamster::Vector[1, 2, 4, 5]
43
- # vector + [6, 7] # => Hamster::Vector[1, 2, 3, 4, 5, 6, 7]
44
- #
45
- # Other `Array`-like methods like {#select}, {#map}, {#shuffle}, {#uniq}, {#reverse},
46
- # {#rotate}, {#flatten}, {#sort}, {#sort_by}, {#take}, {#drop}, {#take_while},
47
- # {#drop_while}, {#fill}, {#product}, and {#transpose} are also supported.
48
- #
49
11
  class Vector
12
+ extend Forwardable
50
13
  include Immutable
51
14
  include Enumerable
52
15
 
53
- # @private
54
16
  BLOCK_SIZE = 32
55
- # @private
56
17
  INDEX_MASK = BLOCK_SIZE - 1
57
- # @private
58
18
  BITS_PER_LEVEL = 5
59
19
 
60
- # Return the number of items in this `Vector`
61
- # @return [Integer]
62
20
  attr_reader :size
63
- alias :length :size
21
+ def_delegator :self, :size, :length
64
22
 
65
- class << self
66
- # Create a new `Vector` populated with the given items.
67
- # @return [Vector]
68
- def [](*items)
69
- new(items.freeze)
70
- end
71
-
72
- # Return an empty `Vector`. If used on a subclass, returns an empty instance
73
- # of that class.
74
- #
75
- # @return [Vector]
76
- def empty
77
- @empty ||= self.new
78
- end
79
-
80
- # "Raw" allocation of a new `Vector`. Used internally to create a new
81
- # instance quickly after building a modified trie.
82
- #
83
- # @return [Vector]
84
- # @private
85
- def alloc(root, size, levels)
86
- obj = allocate
87
- obj.instance_variable_set(:@root, root)
88
- obj.instance_variable_set(:@size, size)
89
- obj.instance_variable_set(:@levels, levels)
90
- obj
91
- end
23
+ def initialize
24
+ @levels = 0
25
+ @root = []
26
+ @size = 0
92
27
  end
93
28
 
94
- def initialize(items=[].freeze)
95
- items = items.to_a
96
- if items.size <= 32
97
- items = items.dup.freeze if !items.frozen?
98
- @root, @size, @levels = items, items.size, 0
99
- else
100
- root, size, levels = items, items.size, 0
101
- while root.size > 32
102
- root = root.each_slice(32).to_a
103
- levels += 1
104
- end
105
- @root, @size, @levels = root.freeze, size, levels
106
- end
107
- end
108
-
109
- # Return `true` if this `Vector` contains no items.
110
- #
111
- # @return [Boolean]
112
29
  def empty?
113
30
  @size == 0
114
31
  end
32
+ def_delegator :self, :empty?, :null?
115
33
 
116
- # Return the first item in the `Vector`. If the vector is empty, return `nil`.
117
- #
118
- # @example
119
- # Hamster::Vector["A", "B", "C"].first # => "A"
120
- #
121
- # @return [Object]
122
34
  def first
123
35
  get(0)
124
36
  end
37
+ def_delegator :self, :first, :head
125
38
 
126
- # Return the last item in the `Vector`. If the vector is empty, return `nil`.
127
- #
128
- # @example
129
- # Hamster::Vector["A", "B", "C"].last # => "C"
130
- #
131
- # @return [Object]
132
39
  def last
133
40
  get(-1)
134
41
  end
135
42
 
136
- # Return a new `Vector` with `item` added after the last occupied position.
137
- #
138
- # @example
139
- # Hamster::Vector[1, 2].add(99) # => Hamster::Vector[1, 2, 99]
140
- #
141
- # @param item [Object] The object to insert at the end of the vector
142
- # @return [Vector]
143
43
  def add(item)
144
- update_root(@size, item)
145
- end
146
- alias :<< :add
147
- alias :push :add
148
-
149
- # Return a new `Vector` with the item at `index` replaced by `item`. If the
150
- # `item` argument is missing, but an optional code block is provided, it will
151
- # be passed the existing item and what the block returns will replace it.
152
- #
153
- # @example
154
- # Hamster::Vector[1, 2, 3, 4].set(2, 99)
155
- # # => Hamster::Vector[1, 2, 99, 4]
156
- # Hamster::Vector[1, 2, 3, 4].set(2) { |v| v * 10 }
157
- # # => Hamster::Vector[1, 2, 30, 4]
158
- #
159
- # @param index [Integer] The index to update
160
- # @param item [Object] The object to insert into that position
161
- # @return [Vector]
162
- def set(index, item = yield(get(index)))
163
- raise IndexError, "index #{index} outside of vector bounds" if index < -@size
164
- index += @size if index < 0
165
- if index > @size
166
- suffix = Array.new(index - @size, nil)
167
- suffix << item
168
- replace_suffix(@size, suffix)
169
- else
170
- update_root(index, item)
171
- end
172
- end
173
-
174
- # Return a new `Vector` with a deeply nested value modified to the result
175
- # of the given code block. When traversing the nested `Vector`s and
176
- # `Hash`es, non-existing keys are created with empty `Hash` values.
177
- #
178
- # The code block receives the existing value of the deeply nested key (or
179
- # `nil` if it doesn't exist). This is useful for "transforming" the value
180
- # associated with a certain key.
181
- #
182
- # Note that the original `Vector` and sub-`Vector`s and sub-`Hash`es are
183
- # left unmodified; new data structure copies are created along the path
184
- # wherever needed.
185
- #
186
- # @example
187
- # v = Hamster::Vector[123, 456, 789, Hamster::Hash["a" => Hamster::Vector[5, 6, 7]]]
188
- # v.update_in(3, "a", 1) { |value| value + 9 }
189
- # # => Hamster::Vector[123, 456, 789, Hamster::Hash["a" => Hamster::Vector[5, 15, 7]]]
190
- #
191
- # @param key_path [Object(s)] List of keys which form the path to the key to be modified
192
- # @yield [value] The previously stored value
193
- # @yieldreturn [Object] The new value to store
194
- # @return [Hash]
195
- def update_in(*key_path, &block)
196
- if key_path.empty?
197
- raise ArgumentError, "must have at least one key in path"
198
- end
199
- key = key_path[0]
200
- if key_path.size == 1
201
- new_value = block.call(get(key))
202
- else
203
- value = fetch(key, EmptyHash)
204
- new_value = value.update_in(*key_path[1..-1], &block)
205
- end
206
- set(key, new_value)
207
- end
208
-
209
- # Retrieve the item at `index`. If there is none (either the provided index
210
- # is too high or too low), return `nil`.
211
- #
212
- # @example
213
- # v = Hamster::Vector["A", "B", "C", "D"]
214
- # v.get(2) # => "C"
215
- # v.get(-1) # => "D"
216
- # v.get(4) # => nil
217
- #
218
- # @param index [Integer] The index to retrieve
219
- # @return [Object]
220
- def get(index)
221
- return nil if @size == 0
222
- index += @size if index < 0
223
- return nil if index >= @size || index < 0
224
- leaf_node_for(@root, @levels * BITS_PER_LEVEL, index)[index & INDEX_MASK]
225
- end
226
- alias :at :get
227
-
228
- # Retrieve the value at `index`, or use the provided default value or block,
229
- # or otherwise raise an `IndexError`.
230
- #
231
- # @overload fetch(index)
232
- # Retrieve the value at the given index, or raise an `IndexError` if it is
233
- # not found.
234
- # @param index [Integer] The index to look up
235
- # @overload fetch(index) { |index| ... }
236
- # Retrieve the value at the given index, or call the optional
237
- # code block (with the non-existent index) and get its return value.
238
- # @yield [index] The index which does not exist
239
- # @yieldreturn [Object] Object to return instead
240
- # @param index [Integer] The index to look up
241
- # @overload fetch(index, default)
242
- # Retrieve the value at the given index, or else return the provided
243
- # `default` value.
244
- # @param index [Integer] The index to look up
245
- # @param default [Object] Object to return if the key is not found
246
- #
247
- # @example
248
- # v = Hamster::Vector["A", "B", "C", "D"]
249
- # v.fetch(2) # => "C"
250
- # v.fetch(-1) # => "D"
251
- # v.fetch(4) # => IndexError: index 4 outside of vector bounds
252
- # # With default value:
253
- # v.fetch(2, "Z") # => "C"
254
- # v.fetch(4, "Z") # => "Z"
255
- # # With block:
256
- # v.fetch(2) { |i| i * i } # => "C"
257
- # v.fetch(4) { |i| i * i } # => 16
258
- #
259
- # @return [Object]
260
- def fetch(index, default = (missing_default = true))
261
- if index >= -@size && index < @size
262
- get(index)
263
- elsif block_given?
264
- yield(index)
265
- elsif !missing_default
266
- default
267
- else
268
- raise IndexError, "index #{index} outside of vector bounds"
269
- end
270
- end
271
-
272
- # Element reference. Return the item at a specific index, or a specified,
273
- # contiguous range of items (as a new `Vector`).
274
- #
275
- # @overload vector[index]
276
- # Return the item at `index`.
277
- # @param index [Integer] The index to retrieve.
278
- # @overload vector[start, length]
279
- # Return a subvector starting at index `start` and continuing for `length` elements.
280
- # @param start [Integer] The index to start retrieving items from.
281
- # @param length [Integer] The number of items to retrieve.
282
- # @overload vector[range]
283
- # Return a subvector specified by the given `range` of indices.
284
- # @param range [Range] The range of indices to retrieve.
285
- #
286
- # @example
287
- # v = Hamster::Vector["A", "B", "C", "D", "E", "F"]
288
- # v[2] # => "C"
289
- # v[-1] # => "D"
290
- # v[6] # => nil
291
- # v[2, 2] # => Hamster::Vector["C", "D"]
292
- # v[2..3] # => Hamster::Vector["C", "D"]
293
- #
294
- # @return [Object]
295
- def [](arg, length = (missing_length = true))
296
- if missing_length
297
- if arg.is_a?(Range)
298
- from, to = arg.begin, arg.end
299
- from += @size if from < 0
300
- to += @size if to < 0
301
- to += 1 if !arg.exclude_end?
302
- length = to - from
303
- length = 0 if length < 0
304
- subsequence(from, length)
305
- else
306
- get(arg)
307
- end
308
- else
309
- arg += @size if arg < 0
310
- subsequence(arg, length)
44
+ transform do
45
+ update_leaf_node(@size, item)
46
+ @size += 1
311
47
  end
312
48
  end
313
- alias :slice :[]
49
+ def_delegator :self, :add, :<<
50
+ def_delegator :self, :add, :cons
314
51
 
315
- # Return a new `Vector` with the given values inserted before the element at `index`.
316
- #
317
- # @example
318
- # Hamster::Vector["A", "B", "C", "D"].insert(2, "X", "Y", "Z")
319
- # # => Hamster::Vector["A", "B", "X", "Y", "Z", "C", "D"]
320
- #
321
- # @param index [Integer] The index where the new items should go
322
- # @param items [Array] The items to add
323
- # @return [Vector]
324
- def insert(index, *items)
325
- raise IndexError if index < -@size
326
- index += @size if index < 0
52
+ # def delete(index)
53
+ # end
327
54
 
328
- if index < @size
329
- suffix = flatten_suffix(@root, @levels * BITS_PER_LEVEL, index, [])
330
- suffix.unshift(*items)
331
- elsif index == @size
332
- suffix = items
333
- else
334
- suffix = Array.new(index - @size, nil).concat(items)
335
- index = @size
55
+ def set(index, item = Undefined)
56
+ return set(index, yield(get(index))) if item.equal?(Undefined)
57
+ raise IndexError if empty? || index == @size
58
+ raise IndexError if index.abs > @size
59
+ return set(@size + index, item) if index < 0
60
+ transform do
61
+ update_leaf_node(index, item)
336
62
  end
337
-
338
- replace_suffix(index, suffix)
339
- end
340
-
341
- # Return a new `Vector` with the element at `index` removed. If the given `index`
342
- # does not exist, return `self`.
343
- #
344
- # @example
345
- # Hamster::Vector["A", "B", "C", "D"].delete_at(2)
346
- # # => Hamster::Vector["A", "B", "D"]
347
- #
348
- # @param index [Integer] The index to remove
349
- # @return [Vector]
350
- def delete_at(index)
351
- return self if index >= @size || index < -@size
352
- index += @size if index < 0
353
-
354
- suffix = flatten_suffix(@root, @levels * BITS_PER_LEVEL, index, [])
355
- replace_suffix(index, suffix.tap { |a| a.shift })
356
63
  end
357
64
 
358
- # Return a new `Vector` with the last element removed. If empty, just return `self`.
359
- #
360
- # @example
361
- # Hamster::Vector["A", "B", "C"].pop # => Hamster::Vector["A", "B"]
362
- #
363
- # @return [Vector]
364
- def pop
365
- return self if @size == 0
366
- replace_suffix(@size-1, [])
367
- end
368
-
369
- # Return a new `Vector` with `obj` inserted before the first element, moving
370
- # the other elements upwards.
371
- #
372
- # @example
373
- # Hamster::Vector["A", "B"].unshift("Z") # => Hamster::Vector["Z", "A", "B"]
374
- #
375
- # @param obj [Object] The value to prepend
376
- # @return [Vector]
377
- def unshift(obj)
378
- insert(0, obj)
379
- end
380
-
381
- # Return a new `Vector` with the first element removed. If empty, just return `self`.
382
- #
383
- # @example
384
- # Hamster::Vector["A", "B", "C"].shift # => Hamster::Vector["B", "C"]
385
- #
386
- # @return [Vector]
387
- def shift
388
- delete_at(0)
65
+ def get(index)
66
+ return nil if empty? || index == @size
67
+ return nil if index.abs > @size
68
+ return get(@size + index) if index < 0
69
+ leaf_node_for(@root, root_index_bits, index)[index & INDEX_MASK]
389
70
  end
71
+ def_delegator :self, :get, :[]
72
+ def_delegator :self, :get, :at
390
73
 
391
- # Call the given block once for each item in the vector, passing each
392
- # item from first to last successively to the block.
393
- #
394
- # @example
395
- # Hamster::Vector["A", "B", "C"].each { |e| puts "Element: #{e}" }
396
- #
397
- # Element: A
398
- # Element: B
399
- # Element: C
400
- # # => Hamster::Vector["A", "B", "C"]
401
- #
402
- # @return [self]
403
74
  def each(&block)
404
- return to_enum unless block_given?
405
- traverse_depth_first(@root, @levels, &block)
406
- self
407
- end
408
-
409
- # Call the given block once for each item in the vector, passing each
410
- # item starting from the last, and counting back to the first, successively to
411
- # the block.
412
- #
413
- # @example
414
- # Hamster::Vector["A", "B", "C"].reverse_each { |e| puts "Element: #{e}" }
415
- #
416
- # Element: C
417
- # Element: B
418
- # Element: A
419
- #
420
- # @return [self]
421
- def reverse_each(&block)
422
- return enum_for(:reverse_each) unless block_given?
423
- reverse_traverse_depth_first(@root, @levels, &block)
424
- self
425
- end
426
-
427
- # Return a new `Vector` containing all elements for which the given block returns
428
- # true.
429
- #
430
- # @example
431
- # Hamster::Vector["Bird", "Cow", "Elephant"].select { |e| e.size >= 4 }
432
- # # => Hamster::Vector["Bird", "Elephant"]
433
- #
434
- # @return [Vector]
435
- def select
436
- return enum_for(:select) unless block_given?
437
- reduce(self.class.empty) { |vector, item| yield(item) ? vector.add(item) : vector }
438
- end
439
- alias :find_all :select
440
- alias :keep_if :select
441
-
442
- # Return a new `Vector` with all items which are equal to `obj` removed.
443
- # `#==` is used for checking equality.
444
- #
445
- # @example
446
- # Hamster::Vector["C", "B", "A", "B"].delete("B") # => Hamster::Vector["C", "A"]
447
- #
448
- # @param obj [Object] The object to remove (every occurrence)
449
- # @return [Vector]
450
- def delete(obj)
451
- select { |item| item != obj }
452
- end
453
-
454
- # Invoke the given block once for each item in the vector, and return a new
455
- # `Vector` containing the values returned by the block.
456
- #
457
- # @example
458
- # Hamster::Vector[3, 2, 1].map { |e| e * e } # => Hamster::Vector[9, 4, 1]
459
- #
460
- # @return [Vector]
461
- def map
462
- return enum_for(:map) if not block_given?
463
- return self if empty?
464
- self.class.new(super)
465
- end
466
- alias :collect :map
467
-
468
- # Return a new `Vector` with the concatenated results of running the block once
469
- # for every element in this `Vector`.
470
- #
471
- # @example
472
- # Hamster.vector(1, 2, 3).flat_map { |x| [x, -x] }
473
- # # => Hamster::Vector[1, -1, 2, -2, 3, -3]
474
- #
475
- # @return [Vector]
476
- def flat_map
477
- return enum_for(:flat_map) if not block_given?
478
- return self if empty?
479
- self.class.new(super)
480
- end
481
-
482
- # Return a new `Vector` with the same elements as this one, but randomly permuted.
483
- #
484
- # @example
485
- # Hamster::Vector[1, 2, 3, 4].shuffle # => Hamster::Vector[4, 1, 3, 2]
486
- #
487
- # @return [Vector]
488
- def shuffle
489
- self.class.new(((array = to_a).frozen? ? array.shuffle : array.shuffle!).freeze)
490
- end
491
-
492
- # Return a new `Vector` with no duplicate elements, as determined by `#hash` and
493
- # `#eql?`. For each group of equivalent elements, only the first will be retained.
494
- #
495
- # @example
496
- # Hamster::Vector["A", "B", "C", "B"].uniq # => Hamster::Vector["A", "B", "C"]
497
- #
498
- # @return [Vector]
499
- def uniq
500
- self.class.new(((array = to_a).frozen? ? array.uniq : array.uniq!).freeze)
501
- end
502
-
503
- # Return a new `Vector` with the same elements as this one, but in reverse order.
504
- #
505
- # @example
506
- # Hamster::Vector["A", "B", "C"].reverse # => Hamster::Vector["C", "B", "A"]
507
- #
508
- # @return [Vector]
509
- def reverse
510
- self.class.new(((array = to_a).frozen? ? array.reverse : array.reverse!).freeze)
511
- end
512
-
513
- # Return a new `Vector` with the same elements, but rotated so that the one at
514
- # index `count` is the first element of the new vector. If `count` is positive,
515
- # the elements will be shifted left, and those shifted past the lowest position
516
- # will be moved to the end. If `count` is negative, the elements will be shifted
517
- # right, and those shifted past the last position will be moved to the beginning.
518
- #
519
- # @example
520
- # v = Hamster::Vector["A", "B", "C", "D", "E", "F"]
521
- # v.rotate(2) # => Hamster::Vector["C", "D", "E", "F", "A", "B"]
522
- # v.rotate(-1) # => Hamster::Vector["F", "A", "B", "C", "D", "E"]
523
- #
524
- # @param count [Integer] The number of positions to shift items by
525
- # @return [Vector]
526
- def rotate(count = 1)
527
- return self if (count % @size) == 0
528
- self.class.new(((array = to_a).frozen? ? array.rotate(count) : array.rotate!(count)).freeze)
529
- end
530
-
531
- # Return a new `Vector` with all nested vectors and arrays recursively "flattened
532
- # out", that is, their elements inserted into the new `Vector` in the place where
533
- # the nested array/vector originally was. If an optional `level` argument is
534
- # provided, the flattening will only be done recursively that number of times.
535
- # A `level` of 0 means not to flatten at all, 1 means to only flatten nested
536
- # arrays/vectors which are directly contained within this `Vector`.
537
- #
538
- # @example
539
- # v = Hamster::Vector["A", Hamster::Vector["B", "C", Hamster::Vector["D"]]]
540
- # v.flatten(1)
541
- # # => Hamster::Vector["A", "B", "C", Hamster::Vector["D"]]
542
- # v.flatten
543
- # # => Hamster::Vector["A", "B", "C", "D"]
544
- #
545
- # @param level [Integer] The depth to which flattening should be applied
546
- # @return [Vector]
547
- def flatten(level = -1)
548
- return self if level == 0
549
- self.class.new(((array = to_a).frozen? ? array.flatten(level) : array.flatten!(level)).freeze)
550
- end
551
-
552
- # Return a new `Vector` built by concatenating this one with `other`. `other`
553
- # can be any object which is convertible to an `Array` using `#to_a`.
554
- #
555
- # @example
556
- # Hamster::Vector["A", "B", "C"] + ["D", "E"]
557
- # # => Hamster::Vector["A", "B", "C", "D", "E"]
558
- #
559
- # @param other [Enumerable] The collection to concatenate onto this vector
560
- # @return [Vector]
561
- def +(other)
562
- other = other.to_a
563
- other = other.dup if other.frozen?
564
- replace_suffix(@size, other)
565
- end
566
- alias :concat :+
567
-
568
- # `others` should be arrays and/or vectors. The corresponding elements from this
569
- # `Vector` and each of `others` (that is, the elements with the same indices)
570
- # will be gathered into arrays.
571
- #
572
- # If an optional block is provided, each such array will be passed successively
573
- # to the block. Otherwise, a new `Vector` of all those arrays will be returned.
574
- #
575
- # @example
576
- # v1 = Hamster::Vector["A", "B", "C"]
577
- # v2 = Hamster::Vector[1, 2, 3]
578
- # v1.zip(v2)
579
- # # => Hamster::Vector[["A", 1], ["B", 2], ["C", 3]]
580
- #
581
- # @param others [Array] The arrays/vectors to zip together with this one
582
- # @return [Vector, nil]
583
- def zip(*others)
584
- if block_given?
585
- super
586
- else
587
- self.class.new(super)
588
- end
589
- end
590
-
591
- # Return a new `Vector` with the same items, but sorted. The sort order will
592
- # be determined by comparing items using `#<=>`, or if an optional code block
593
- # is provided, by using it as a comparator. The block should accept 2 parameters,
594
- # and should return 0, 1, or -1 if the first parameter is equal to, greater than,
595
- # or less than the second parameter (respectively).
596
- #
597
- # @example
598
- # Hamster::Vector["Elephant", "Dog", "Lion"].sort
599
- # # => Hamster::Vector["Dog", "Elephant", "Lion"]
600
- # Hamster::Vector["Elephant", "Dog", "Lion"].sort { |a,b| a.size <=> b.size }
601
- # # => Hamster::Vector["Dog", "Lion", "Elephant"]
602
- #
603
- # @return [Vector]
604
- def sort
605
- self.class.new(super)
606
- end
607
-
608
- # Return a new `Vector` with the same items, but sorted. The sort order will be
609
- # determined by mapping the items through the given block to obtain sort keys,
610
- # and then sorting the keys according to their natural sort order.
611
- #
612
- # @example
613
- # Hamster::Vector["Elephant", "Dog", "Lion"].sort_by { |e| e.size }
614
- # # => Hamster::Vector["Dog", "Lion", "Elephant"]
615
- #
616
- # @return [Vector]
617
- def sort_by
618
- self.class.new(super)
619
- end
620
-
621
- # Drop the first `n` elements and return the rest in a new `Vector`.
622
- #
623
- # @example
624
- # Hamster::Vector["A", "B", "C", "D", "E", "F"].drop(2)
625
- # # => Hamster::Vector["C", "D", "E", "F"]
626
- #
627
- # @param n [Integer] The number of elements to remove
628
- # @return [Vector]
629
- def drop(n)
630
- return self if n == 0
631
- return self.class.empty if n >= @size
632
- raise ArgumentError, "attempt to drop negative size" if n < 0
633
- self.class.new(flatten_suffix(@root, @levels * BITS_PER_LEVEL, n, []))
634
- end
635
-
636
- # Return only the first `n` elements in a new `Vector`.
637
- #
638
- # @example
639
- # Hamster::Vector["A", "B", "C", "D", "E", "F"].take(4)
640
- # # => Hamster::Vector["A", "B", "C", "D"]
641
- #
642
- # @param n [Integer] The number of elements to retain
643
- # @return [Vector]
644
- def take(n)
645
- return self if n >= @size
646
- self.class.new(super)
647
- end
648
-
649
- # Drop elements up to, but not including, the first element for which the
650
- # block returns `nil` or `false`. Gather the remaining elements into a new
651
- # `Vector`. If no block is given, an `Enumerator` is returned instead.
652
- #
653
- # @example
654
- # Hamster::Vector[1, 3, 5, 7, 6, 4, 2].drop_while { |e| e < 5 }
655
- # # => Hamster::Vector[5, 7, 6, 4, 2]
656
- #
657
- # @return [Vector, Enumerator]
658
- def drop_while
659
- return enum_for(:drop_while) if not block_given?
660
- self.class.new(super)
661
- end
662
-
663
- # Gather elements up to, but not including, the first element for which the
664
- # block returns `nil` or `false`, and return them in a new `Vector`. If no block
665
- # is given, an `Enumerator` is returned instead.
666
- #
667
- # @example
668
- # Hamster::Vector[1, 3, 5, 7, 6, 4, 2].take_while { |e| e < 5 }
669
- # # => Hamster::Vector[1, 3]
670
- #
671
- # @return [Vector, Enumerator]
672
- def take_while
673
- return enum_for(:take_while) if not block_given?
674
- self.class.new(super)
675
- end
676
-
677
- # Repetition. Return a new `Vector` built by concatenating `times` copies
678
- # of this one together.
679
- #
680
- # @example
681
- # Hamster::Vector["A", "B"] * 3
682
- # # => Hamster::Vector["A", "B", "A", "B", "A", "B"]
683
- #
684
- # @param times [Integer] The number of times to repeat the elements in this vector
685
- # @return [Vector]
686
- def *(times)
687
- return self.class.empty if times == 0
688
- return self if times == 1
689
- result = (to_a * times)
690
- result.is_a?(Array) ? self.class.new(result) : result
691
- end
692
-
693
- # Replace a range of indexes with the given object.
694
- #
695
- # @overload fill(obj)
696
- # Return a new `Vector` of the same size, with every index set to `obj`.
697
- # @overload fill(obj, start)
698
- # Return a new `Vector` with all indexes from `start` to the end of the
699
- # vector set to `obj`.
700
- # @overload fill(obj, start, length)
701
- # Return a new `Vector` with `length` indexes, beginning from `start`,
702
- # set to `obj`.
703
- #
704
- # @example
705
- # v = Hamster::Vector["A", "B", "C", "D", "E", "F"]
706
- # v.fill("Z")
707
- # # => Hamster::Vector["Z", "Z", "Z", "Z", "Z", "Z"]
708
- # v.fill("Z", 3)
709
- # # => Hamster::Vector["A", "B", "C", "Z", "Z", "Z"]
710
- # v.fill("Z", 3, 2)
711
- # # => Hamster::Vector["A", "B", "C", "Z", "Z", "F"]
712
- #
713
- # @return [Vector]
714
- def fill(obj, index = 0, length = nil)
715
- raise IndexError if index < -@size
716
- index += @size if index < 0
717
- length ||= @size - index # to the end of the array, if no length given
718
-
719
- if index < @size
720
- suffix = flatten_suffix(@root, @levels * BITS_PER_LEVEL, index, [])
721
- suffix.fill(obj, 0, length)
722
- elsif index == @size
723
- suffix = Array.new(length, obj)
724
- else
725
- suffix = Array.new(index - @size, nil).concat(Array.new(length, obj))
726
- index = @size
727
- end
728
-
729
- replace_suffix(index, suffix)
730
- end
731
-
732
- # When invoked with a block, yields all combinations of length `n` of items
733
- # from the `Vector`, and then returns `self`. There is no guarantee about
734
- # which order the combinations will be yielded in.
735
- #
736
- # If no block is given, an `Enumerator` is returned instead.
737
- #
738
- # @example
739
- # v = Hamster::Vector[5, 6, 7, 8]
740
- # v.combination(3) { |c| puts "Combination: #{c}" }
741
- #
742
- # Combination: [5, 6, 7]
743
- # Combination: [5, 6, 8]
744
- # Combination: [5, 7, 8]
745
- # Combination: [6, 7, 8]
746
- # #=> Hamster::Vector[5, 6, 7, 8]
747
- #
748
- # @return [self, Enumerator]
749
- def combination(n)
750
- return enum_for(:combination, n) if not block_given?
751
- return self if n < 0 || @size < n
752
- if n == 0
753
- yield []
754
- elsif n == 1
755
- each { |item| yield [item] }
756
- elsif n == @size
757
- yield self.to_a
758
- else
759
- combos = lambda do |result,index,remaining|
760
- while @size - index > remaining
761
- if remaining == 1
762
- yield result.dup << get(index)
763
- else
764
- combos[result.dup << get(index), index+1, remaining-1]
765
- end
766
- index += 1
767
- end
768
- index.upto(@size-1) { |i| result << get(i) }
769
- yield result
770
- end
771
- combos[[], 0, n]
772
- end
773
- self
774
- end
775
-
776
- # When invoked with a block, yields all repeated combinations of length `n` of
777
- # items from the `Vector`, and then returns `self`. A "repeated combination" is
778
- # one in which any item from the `Vector` can appear consecutively any number of
779
- # times.
780
- #
781
- # There is no guarantee about which order the combinations will be yielded in.
782
- #
783
- # If no block is given, an `Enumerator` is returned instead.
784
- #
785
- # @example
786
- # v = Hamster::Vector[5, 6, 7, 8]
787
- # v.repeated_combination(2) { |c| puts "Combination: #{c}" }
788
- #
789
- # Combination: [5, 5]
790
- # Combination: [5, 6]
791
- # Combination: [5, 7]
792
- # Combination: [5, 8]
793
- # Combination: [6, 6]
794
- # Combination: [6, 7]
795
- # Combination: [6, 8]
796
- # Combination: [7, 7]
797
- # Combination: [7, 8]
798
- # Combination: [8, 8]
799
- # # => Hamster::Vector[5, 6, 7, 8]
800
- #
801
- # @return [self, Enumerator]
802
- def repeated_combination(n)
803
- return enum_for(:repeated_combination, n) if not block_given?
804
- if n < 0
805
- # yield nothing
806
- elsif n == 0
807
- yield []
808
- elsif n == 1
809
- each { |item| yield [item] }
810
- elsif @size == 0
811
- # yield nothing
812
- else
813
- combos = lambda do |result,index,remaining|
814
- while index < @size-1
815
- if remaining == 1
816
- yield result.dup << get(index)
817
- else
818
- combos[result.dup << get(index), index, remaining-1]
819
- end
820
- index += 1
821
- end
822
- item = get(index)
823
- remaining.times { result << item }
824
- yield result
825
- end
826
- combos[[], 0, n]
827
- end
828
- self
829
- end
830
-
831
- # Yields all permutations of length `n` of items from the `Vector`, and then
832
- # returns `self`. If no length `n` is specified, permutations of all elements
833
- # will be yielded.
834
- #
835
- # There is no guarantee about which order the permutations will be yielded in.
836
- #
837
- # If no block is given, an `Enumerator` is returned instead.
838
- #
839
- # @example
840
- # v = Hamster::Vector[5, 6, 7]
841
- # v.permutation(2) { |p| puts "Permutation: #{p}" }
842
- #
843
- # Permutation: [5, 6]
844
- # Permutation: [5, 7]
845
- # Permutation: [6, 5]
846
- # Permutation: [6, 7]
847
- # Permutation: [7, 5]
848
- # Permutation: [7, 6]
849
- # # => Hamster::Vector[5, 6, 7]
850
- #
851
- # @return [self, Enumerator]
852
- def permutation(n = @size)
853
- return enum_for(:permutation, n) if not block_given?
854
- if n < 0 || @size < n
855
- # yield nothing
856
- elsif n == 0
857
- yield []
858
- elsif n == 1
859
- each { |item| yield [item] }
860
- else
861
- used, result = [], []
862
- perms = lambda do |index|
863
- 0.upto(@size-1) do |i|
864
- if !used[i]
865
- result[index] = get(i)
866
- if index < n-1
867
- used[i] = true
868
- perms[index+1]
869
- used[i] = false
870
- else
871
- yield result.dup
872
- end
873
- end
874
- end
875
- end
876
- perms[0]
877
- end
878
- self
879
- end
880
-
881
- # When invoked with a block, yields all repeated permutations of length `n` of
882
- # items from the `Vector`, and then returns `self`. A "repeated permutation" is
883
- # one where any item from the `Vector` can appear any number of times, and in
884
- # any position (not just consecutively)
885
- #
886
- # If no length `n` is specified, permutations of all elements will be yielded.
887
- # There is no guarantee about which order the permutations will be yielded in.
888
- #
889
- # If no block is given, an `Enumerator` is returned instead.
890
- #
891
- # @example
892
- # v = Hamster::Vector[5, 6, 7]
893
- # v.repeated_permutation(2) { |p| puts "Permutation: #{p}" }
894
- #
895
- # Permutation: [5, 5]
896
- # Permutation: [5, 6]
897
- # Permutation: [5, 7]
898
- # Permutation: [6, 5]
899
- # Permutation: [6, 6]
900
- # Permutation: [6, 7]
901
- # Permutation: [7, 5]
902
- # Permutation: [7, 6]
903
- # Permutation: [7, 7]
904
- # # => Hamster::Vector[5, 6, 7]
905
- #
906
- # @return [self, Enumerator]
907
- def repeated_permutation(n = @size)
908
- return enum_for(:repeated_permutation, n) if not block_given?
909
- if n < 0
910
- # yield nothing
911
- elsif n == 0
912
- yield []
913
- elsif n == 1
914
- each { |item| yield [item] }
915
- else
916
- result = []
917
- perms = lambda do |index|
918
- 0.upto(@size-1) do |i|
919
- result[index] = get(i)
920
- if index < n-1
921
- perms[index+1]
922
- else
923
- yield result.dup
924
- end
925
- end
926
- end
927
- perms[0]
928
- end
929
- self
930
- end
931
-
932
- # With one or more vector or array arguments, return the cartesian product of
933
- # this vector's elements and those of each argument; with no arguments, return the
934
- # result of multiplying all this vector's items together.
935
- #
936
- # @overload product(*vectors)
937
- # Return a `Vector` of all combinations of elements from this `Vector` and each
938
- # of the given vectors or arrays. The length of the returned `Vector` is the product
939
- # of `self.size` and the size of each argument vector or array.
940
- # @overload product
941
- # Return the result of multiplying all the items in this `Vector` together.
942
- #
943
- # @example
944
- # # Cartesian product:
945
- # v1 = Hamster::Vector[1, 2, 3]
946
- # v2 = Hamster::Vector["A", "B"]
947
- # v1.product(v2)
948
- # # => [[1, "A"], [1, "B"], [2, "A"], [2, "B"], [3, "A"], [3, "B"]]
949
- #
950
- # # Multiply all items:
951
- # Hamster::Vector[1, 2, 3, 4, 5].product # => 120
952
- #
953
- # @return [Vector]
954
- def product(*vectors)
955
- # if no vectors passed, return "product" as in result of multiplying all items
956
- return super if vectors.empty?
957
-
958
- vectors.unshift(self)
959
-
960
- if vectors.any?(&:empty?)
961
- return block_given? ? self : []
962
- end
963
-
964
- counters = Array.new(vectors.size, 0)
965
-
966
- bump_counters = lambda do
967
- i = vectors.size-1
968
- counters[i] += 1
969
- while counters[i] == vectors[i].size
970
- counters[i] = 0
971
- i -= 1
972
- return true if i == -1 # we are done
973
- counters[i] += 1
974
- end
975
- false # not done yet
976
- end
977
- build_array = lambda do
978
- array = []
979
- counters.each_with_index { |index,i| array << vectors[i][index] }
980
- array
981
- end
982
-
983
- if block_given?
984
- while true
985
- yield build_array[]
986
- return self if bump_counters[]
987
- end
988
- else
989
- result = []
990
- while true
991
- result << build_array[]
992
- return result if bump_counters[]
993
- end
994
- end
75
+ return self unless block_given?
76
+ traverse_depth_first(&block)
77
+ nil
995
78
  end
996
79
 
997
- # Assume all elements are vectors or arrays and transpose the rows and columns.
998
- # In other words, take the first element of each nested vector/array and gather
999
- # them together into a new `Vector`. Do likewise for the second, third, and so on
1000
- # down to the end of each nested vector/array. Gather all the resulting `Vectors`
1001
- # into a new `Vector` and return it.
1002
- #
1003
- # This operation is closely related to {#zip}. The result is almost the same as
1004
- # calling {#zip} on the first nested vector/array with the others supplied as
1005
- # arguments.
1006
- #
1007
- # @example
1008
- # Hamster::Vector[["A", 10], ["B", 20], ["C", 30]].transpose
1009
- # # => Hamster::Vector[Hamster::Vector["A", "B", "C"], Hamster::Vector[10, 20, 30]]
1010
- #
1011
- # @return [Vector]
1012
- def transpose
1013
- return self.class.empty if empty?
1014
- result = Array.new(first.size) { [] }
1015
-
1016
- 0.upto(@size-1) do |i|
1017
- source = get(i)
1018
- if source.size != result.size
1019
- raise IndexError, "element size differs (#{source.size} should be #{result.size})"
1020
- end
1021
-
1022
- 0.upto(result.size-1) do |j|
1023
- result[j].push(source[j])
1024
- end
1025
- end
1026
-
1027
- result.map! { |a| self.class.new(a) }
1028
- self.class.new(result)
80
+ def map(&block)
81
+ return self unless block_given?
82
+ reduce(EmptyVector) { |vector, item| vector.add(yield(item)) }
1029
83
  end
84
+ def_delegator :self, :map, :collect
1030
85
 
1031
- # By using binary search, finds a value from this `Vector` which meets the
1032
- # condition defined by the provided block. Behavior is just like `Array#bsearch`.
1033
- # See `Array#bsearch` for details.
1034
- #
1035
- # @example
1036
- # v = Hamster::Vector[1, 3, 5, 7, 9, 11, 13]
1037
- # # Block returns true/false for exact element match:
1038
- # v.bsearch { |e| e > 4 } # => 5
1039
- # # Block returns number to match an element in 4 <= e <= 7:
1040
- # v.bsearch { |e| 1 - e / 4 } # => 7
1041
- #
1042
- # @return [Object]
1043
- def bsearch
1044
- low, high, result = 0, @size, nil
1045
- while low < high
1046
- mid = (low + ((high - low) >> 1))
1047
- val = get(mid)
1048
- v = yield val
1049
- if v.is_a? Numeric
1050
- if v == 0
1051
- return val
1052
- elsif v > 0
1053
- high = mid
1054
- else
1055
- low = mid + 1
1056
- end
1057
- elsif v == true
1058
- result = val
1059
- high = mid
1060
- elsif !v
1061
- low = mid + 1
1062
- else
1063
- raise TypeError, "wrong argument type #{v.class} (must be numeric, true, false, or nil)"
1064
- end
1065
- end
1066
- result
86
+ def filter
87
+ return self unless block_given?
88
+ reduce(EmptyVector) { |vector, item| yield(item) ? vector.add(item) : vector }
1067
89
  end
1068
90
 
1069
- # Return an empty `Vector` instance, of the same class as this one. Useful if you
1070
- # have multiple subclasses of `Vector` and want to treat them polymorphically.
1071
- #
1072
- # @return [Vector]
1073
91
  def clear
1074
- self.class.empty
1075
- end
1076
-
1077
- # Return a randomly chosen item from this `Vector`. If the vector is empty, return `nil`.
1078
- #
1079
- # @example
1080
- # Hamster::Vector[1, 2, 3, 4, 5].sample # => 2
1081
- #
1082
- # @return [Object]
1083
- def sample
1084
- get(rand(@size))
1085
- end
1086
-
1087
- # Return a new `Vector` with only the elements at the given `indices`, in the
1088
- # order specified by `indices`. If any of the `indices` do not exist, `nil`s will
1089
- # appear in their places.
1090
- #
1091
- # @example
1092
- # v = Hamster::Vector["A", "B", "C", "D", "E", "F"]
1093
- # v.values_at(2, 4, 5) # => Hamster::Vector["C", "E", "F"]
1094
- #
1095
- # @param indices [Array] The indices to retrieve and gather into a new `Vector`
1096
- # @return [Vector]
1097
- def values_at(*indices)
1098
- self.class.new(indices.map { |i| get(i) }.freeze)
1099
- end
1100
-
1101
- # Return the index of the last element which is equal to the provided object,
1102
- # or for which the provided block returns true.
1103
- #
1104
- # @overload rindex(obj)
1105
- # Return the index of the last element in this `Vector` which is `#==` to `obj`.
1106
- # @overload rindex { |item| ... }
1107
- # Return the index of the last element in this `Vector` for which the block
1108
- # returns true. (Iteration starts from the last element, counts back, and
1109
- # stops as soon as a matching element is found.)
1110
- #
1111
- # @example
1112
- # v = Hamster::Vector[7, 8, 9, 7, 8, 9]
1113
- # v.rindex(8) # => 4
1114
- # v.rindex { |e| e.even? } # => 4
1115
- #
1116
- # @return [Index]
1117
- def rindex(obj = (missing_arg = true))
1118
- i = @size - 1
1119
- if missing_arg
1120
- if block_given?
1121
- reverse_each { |item| return i if yield item; i -= 1 }
1122
- nil
1123
- else
1124
- enum_for(:rindex)
1125
- end
1126
- else
1127
- reverse_each { |item| return i if item == obj; i -= 1 }
1128
- nil
1129
- end
1130
- end
1131
-
1132
- # Assumes all elements are nested, indexable collections, and searches through them,
1133
- # comparing `obj` with the first element of each nested collection. Return the
1134
- # first nested collection which matches, or `nil` if none is found.
1135
- #
1136
- # @example
1137
- # v = Hamster::Vector[["A", 10], ["B", 20], ["C", 30]]
1138
- # v.assoc("B") # => ["B", 20]
1139
- #
1140
- # @param obj [Object] The object to search for
1141
- # @return [Object]
1142
- def assoc(obj)
1143
- each { |array| return array if obj == array[0] }
1144
- nil
1145
- end
1146
-
1147
- # Assumes all elements are nested, indexable collections, and searches through them,
1148
- # comparing `obj` with the second element of each nested collection. Return the
1149
- # first nested collection which matches, or `nil` if none is found.
1150
- #
1151
- # @example
1152
- # v = Hamster::Vector[["A", 10], ["B", 20], ["C", 30]]
1153
- # v.rassoc(20) # => ["B", 20]
1154
- #
1155
- # @param obj [Object] The object to search for
1156
- # @return [Object]
1157
- def rassoc(obj)
1158
- each { |array| return array if obj == array[1] }
1159
- nil
92
+ EmptyVector
1160
93
  end
1161
94
 
1162
- # Return an `Array` with the same elements, in the same order. The returned
1163
- # `Array` may or may not be frozen.
1164
- #
1165
- # @return [Array]
1166
- def to_a
1167
- if @levels == 0
1168
- @root
1169
- else
1170
- flatten_node(@root, @levels * BITS_PER_LEVEL, [])
1171
- end
95
+ def inspect
96
+ to_a.inspect
1172
97
  end
1173
- alias :to_ary :to_a
1174
98
 
1175
- # Return true if `other` has the same type and contents as this `Vector`.
1176
- #
1177
- # @param other [Object] The collection to compare with
1178
- # @return [Boolean]
1179
99
  def eql?(other)
1180
100
  return true if other.equal?(self)
1181
101
  return false unless instance_of?(other.class) && @size == other.size
1182
102
  @root.eql?(other.instance_variable_get(:@root))
1183
103
  end
1184
-
1185
- # See `Object#hash`.
1186
- # @return [Integer]
1187
- def hash
1188
- reduce(0) { |hash, item| (hash << 5) - hash + item.hash }
1189
- end
1190
-
1191
- # @return [::Array]
1192
- # @private
1193
- def marshal_dump
1194
- to_a
1195
- end
1196
-
1197
- # @private
1198
- def marshal_load(array)
1199
- initialize(array.freeze)
1200
- end
104
+ def_delegator :self, :eql?, :==
1201
105
 
1202
106
  private
1203
107
 
1204
- def traverse_depth_first(node, level, &block)
108
+ def traverse_depth_first(node = @root, level = @levels, &block)
1205
109
  return node.each(&block) if level == 0
1206
110
  node.each { |child| traverse_depth_first(child, level - 1, &block) }
1207
111
  end
1208
112
 
1209
- def reverse_traverse_depth_first(node, level, &block)
1210
- return node.reverse_each(&block) if level == 0
1211
- node.reverse_each { |child| reverse_traverse_depth_first(child, level - 1, &block) }
113
+ def leaf_node_for(node, child_index_bits, index)
114
+ return node if child_index_bits == 0
115
+ child_index = (index >> child_index_bits) & INDEX_MASK
116
+ leaf_node_for(node[child_index], child_index_bits - BITS_PER_LEVEL, index)
1212
117
  end
1213
118
 
1214
- def leaf_node_for(node, bitshift, index)
1215
- while bitshift > 0
1216
- node = node[(index >> bitshift) & INDEX_MASK]
1217
- bitshift -= BITS_PER_LEVEL
1218
- end
1219
- node
119
+ def update_leaf_node(index, item)
120
+ copy_leaf_node_for(new_root, root_index_bits, index)[index & INDEX_MASK] = item
1220
121
  end
1221
122
 
1222
- def update_root(index, item)
1223
- root, levels = @root, @levels
1224
- while index >= (1 << (BITS_PER_LEVEL * (levels + 1)))
1225
- root = [root].freeze
1226
- levels += 1
1227
- end
1228
- new_root = update_leaf_node(root, levels * BITS_PER_LEVEL, index, item)
1229
- if new_root.equal?(root)
1230
- self
123
+ def copy_leaf_node_for(node, child_index_bits, index)
124
+ return node if child_index_bits == 0
125
+ child_index = (index >> child_index_bits) & INDEX_MASK
126
+ child_node = node[child_index]
127
+ if child_node
128
+ child_node = child_node.dup
1231
129
  else
1232
- self.class.alloc(new_root, @size > index ? @size : index + 1, levels)
130
+ child_node = []
1233
131
  end
132
+ node[child_index] = child_node
133
+ copy_leaf_node_for(child_node, child_index_bits - BITS_PER_LEVEL, index)
1234
134
  end
1235
135
 
1236
- def update_leaf_node(node, bitshift, index, item)
1237
- slot_index = (index >> bitshift) & INDEX_MASK
1238
- if bitshift > 0
1239
- old_child = node[slot_index] || []
1240
- item = update_leaf_node(old_child, bitshift - BITS_PER_LEVEL, index, item)
1241
- end
1242
- existing_item = node[slot_index]
1243
- if existing_item.equal?(item)
1244
- node
136
+ def new_root
137
+ if full?
138
+ @levels += 1
139
+ @root = [@root]
1245
140
  else
1246
- node.dup.tap { |n| n[slot_index] = item }.freeze
141
+ @root = @root.dup
1247
142
  end
1248
143
  end
1249
144
 
1250
- def flatten_range(node, bitshift, from, to)
1251
- from_slot = (from >> bitshift) & INDEX_MASK
1252
- to_slot = (to >> bitshift) & INDEX_MASK
1253
-
1254
- if bitshift == 0 # are we at the bottom?
1255
- node.slice(from_slot, to_slot-from_slot+1)
1256
- elsif from_slot == to_slot
1257
- flatten_range(node[from_slot], bitshift - BITS_PER_LEVEL, from, to)
1258
- else
1259
- # the following bitmask can be used to pick out the part of the from/to indices
1260
- # which will be used to direct path BELOW this node
1261
- mask = ((1 << bitshift) - 1)
1262
- result = []
1263
-
1264
- if from & mask == 0
1265
- flatten_node(node[from_slot], bitshift - BITS_PER_LEVEL, result)
1266
- else
1267
- result.concat(flatten_range(node[from_slot], bitshift - BITS_PER_LEVEL, from, from | mask))
1268
- end
1269
-
1270
- (from_slot+1).upto(to_slot-1) do |slot_index|
1271
- flatten_node(node[slot_index], bitshift - BITS_PER_LEVEL, result)
1272
- end
1273
-
1274
- if to & mask == mask
1275
- flatten_node(node[to_slot], bitshift - BITS_PER_LEVEL, result)
1276
- else
1277
- result.concat(flatten_range(node[to_slot], bitshift - BITS_PER_LEVEL, to & ~mask, to))
1278
- end
1279
-
1280
- result
1281
- end
145
+ def full?
146
+ (@size >> root_index_bits) > 0
1282
147
  end
1283
148
 
1284
- def flatten_node(node, bitshift, result)
1285
- if bitshift == 0
1286
- result.concat(node)
1287
- elsif bitshift == BITS_PER_LEVEL
1288
- node.each { |a| result.concat(a) }
1289
- else
1290
- bitshift -= BITS_PER_LEVEL
1291
- node.each { |a| flatten_node(a, bitshift, result) }
1292
- end
1293
- result
1294
- end
1295
-
1296
- def subsequence(from, length)
1297
- return nil if from > @size || from < 0 || length < 0
1298
- length = @size - from if @size < from + length
1299
- return self.class.empty if length == 0
1300
- self.class.new(flatten_range(@root, @levels * BITS_PER_LEVEL, from, from + length - 1))
1301
- end
1302
-
1303
- def flatten_suffix(node, bitshift, from, result)
1304
- from_slot = (from >> bitshift) & INDEX_MASK
1305
-
1306
- if bitshift == 0
1307
- if from_slot == 0
1308
- result.concat(node)
1309
- else
1310
- result.concat(node.slice(from_slot, 32)) # entire suffix of node. excess length is ignored by #slice
1311
- end
1312
- else
1313
- mask = ((1 << bitshift) - 1)
1314
- if from & mask == 0
1315
- from_slot.upto(node.size-1) do |i|
1316
- flatten_node(node[i], bitshift - BITS_PER_LEVEL, result)
1317
- end
1318
- elsif child = node[from_slot]
1319
- flatten_suffix(child, bitshift - BITS_PER_LEVEL, from, result)
1320
- (from_slot+1).upto(node.size-1) do |i|
1321
- flatten_node(node[i], bitshift - BITS_PER_LEVEL, result)
1322
- end
1323
- end
1324
- result
1325
- end
1326
- end
1327
-
1328
- def replace_suffix(from, suffix)
1329
- # new suffix can go directly after existing elements
1330
- raise IndexError if from > @size
1331
- root, levels = @root, @levels
1332
-
1333
- if (from >> (BITS_PER_LEVEL * (@levels + 1))) != 0
1334
- # index where new suffix goes doesn't fall within current tree
1335
- # we will need to deepen tree
1336
- root = [root].freeze
1337
- levels += 1
1338
- end
1339
-
1340
- new_size = from + suffix.size
1341
- root = replace_node_suffix(root, levels * BITS_PER_LEVEL, from, suffix)
1342
-
1343
- if !suffix.empty?
1344
- levels.times { suffix = suffix.each_slice(32).to_a }
1345
- root.concat(suffix)
1346
- while root.size > 32
1347
- root = root.each_slice(32).to_a
1348
- levels += 1
1349
- end
1350
- else
1351
- while root.size == 1 && levels > 0
1352
- root = root[0]
1353
- levels -= 1
1354
- end
1355
- end
1356
-
1357
- self.class.alloc(root.freeze, new_size, levels)
1358
- end
1359
-
1360
- def replace_node_suffix(node, bitshift, from, suffix)
1361
- from_slot = (from >> bitshift) & INDEX_MASK
1362
-
1363
- if bitshift == 0
1364
- if from_slot == 0
1365
- suffix.shift(32)
1366
- else
1367
- node.take(from_slot).concat(suffix.shift(32 - from_slot))
1368
- end
1369
- else
1370
- mask = ((1 << bitshift) - 1)
1371
- if from & mask == 0
1372
- if from_slot == 0
1373
- new_node = suffix.shift(32 * (1 << bitshift))
1374
- while bitshift != 0
1375
- new_node = new_node.each_slice(32).to_a
1376
- bitshift -= BITS_PER_LEVEL
1377
- end
1378
- new_node
1379
- else
1380
- result = node.take(from_slot)
1381
- remainder = suffix.shift((32 - from_slot) * (1 << bitshift))
1382
- while bitshift != 0
1383
- remainder = remainder.each_slice(32).to_a
1384
- bitshift -= BITS_PER_LEVEL
1385
- end
1386
- result.concat(remainder)
1387
- end
1388
- elsif child = node[from_slot]
1389
- result = node.take(from_slot)
1390
- result.push(replace_node_suffix(child, bitshift - BITS_PER_LEVEL, from, suffix))
1391
- remainder = suffix.shift((31 - from_slot) * (1 << bitshift))
1392
- while bitshift != 0
1393
- remainder = remainder.each_slice(32).to_a
1394
- bitshift -= BITS_PER_LEVEL
1395
- end
1396
- result.concat(remainder)
1397
- else
1398
- raise "Shouldn't happen"
1399
- end
1400
- end
149
+ def root_index_bits
150
+ @levels * BITS_PER_LEVEL
1401
151
  end
1402
152
  end
1403
153
 
1404
- # The canonical empty `Vector`. Returned by `Hamster.vector` and `Vector[]` when
1405
- # invoked with no arguments; also returned by `Vector.empty`. Prefer using this
1406
- # one rather than creating many empty vectors using `Vector.new`.
1407
- #
1408
- EmptyVector = Hamster::Vector.empty
154
+ EmptyVector = Hamster::Vector.new
1409
155
  end