immutable-ruby 0.0.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 (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