immutable-ruby 0.0.4 → 0.2.0

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 (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'