immutable-ruby 0.0.1

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