immutable-ruby 0.0.4 → 0.2.0

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