hamster 1.0.1.pre.rc2 → 1.0.1.pre.rc3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (482) hide show
  1. checksums.yaml +4 -4
  2. data/lib/hamster.rb +2 -2
  3. data/lib/hamster/core_ext.rb +0 -1
  4. data/lib/hamster/core_ext/enumerable.rb +17 -17
  5. data/lib/hamster/core_ext/io.rb +15 -17
  6. data/lib/hamster/deque.rb +229 -0
  7. data/lib/hamster/enumerable.rb +147 -105
  8. data/lib/hamster/experimental/mutable_queue.rb +2 -2
  9. data/lib/hamster/hash.rb +488 -82
  10. data/lib/hamster/immutable.rb +4 -0
  11. data/lib/hamster/list.rb +839 -196
  12. data/lib/hamster/read_copy_update.rb +1 -0
  13. data/lib/hamster/set.rb +317 -54
  14. data/lib/hamster/sorted_set.rb +1014 -0
  15. data/lib/hamster/trie.rb +67 -47
  16. data/lib/hamster/undefined.rb +1 -3
  17. data/lib/hamster/vector.rb +989 -76
  18. data/lib/hamster/version.rb +1 -1
  19. data/spec/{hamster → lib/hamster}/core_ext/array_spec.rb +1 -1
  20. data/spec/{hamster → lib/hamster}/core_ext/enumerable_spec.rb +4 -0
  21. data/spec/{hamster → lib/hamster}/core_ext/io_spec.rb +0 -0
  22. data/spec/lib/hamster/deque/clear_spec.rb +34 -0
  23. data/spec/lib/hamster/deque/construction_spec.rb +30 -0
  24. data/spec/lib/hamster/deque/copying_spec.rb +20 -0
  25. data/spec/lib/hamster/deque/dequeue_spec.rb +27 -0
  26. data/spec/lib/hamster/deque/empty_spec.rb +42 -0
  27. data/spec/{hamster/queue → lib/hamster/deque}/enqueue_spec.rb +7 -10
  28. data/spec/lib/hamster/deque/head_spec.rb +20 -0
  29. data/spec/lib/hamster/deque/inspect_spec.rb +24 -0
  30. data/spec/lib/hamster/deque/last_spec.rb +20 -0
  31. data/spec/lib/hamster/deque/marshal_spec.rb +34 -0
  32. data/spec/lib/hamster/deque/new_spec.rb +44 -0
  33. data/spec/lib/hamster/deque/pop_spec.rb +25 -0
  34. data/spec/lib/hamster/deque/random_modification_spec.rb +34 -0
  35. data/spec/{hamster/queue → lib/hamster/deque}/size_spec.rb +4 -9
  36. data/spec/lib/hamster/deque/to_a_spec.rb +27 -0
  37. data/spec/{hamster/queue → lib/hamster/deque}/to_ary_spec.rb +6 -6
  38. data/spec/lib/hamster/deque/to_list_spec.rb +26 -0
  39. data/spec/lib/hamster/deque/unshift_spec.rb +26 -0
  40. data/spec/{hamster → lib/hamster}/experimental/mutable_set/add_qm_spec.rb +0 -0
  41. data/spec/{hamster → lib/hamster}/experimental/mutable_set/add_spec.rb +0 -0
  42. data/spec/{hamster → lib/hamster}/experimental/mutable_set/delete_qm_spec.rb +0 -0
  43. data/spec/{hamster → lib/hamster}/experimental/mutable_set/delete_spec.rb +0 -0
  44. data/spec/{hamster → lib/hamster}/hash/all_spec.rb +10 -0
  45. data/spec/lib/hamster/hash/any_spec.rb +56 -0
  46. data/spec/lib/hamster/hash/assoc_spec.rb +52 -0
  47. data/spec/lib/hamster/hash/clear_spec.rb +43 -0
  48. data/spec/lib/hamster/hash/construction_spec.rb +39 -0
  49. data/spec/{hamster → lib/hamster}/hash/copying_spec.rb +2 -4
  50. data/spec/lib/hamster/hash/default_proc_spec.rb +73 -0
  51. data/spec/lib/hamster/hash/delete_spec.rb +40 -0
  52. data/spec/lib/hamster/hash/each_spec.rb +78 -0
  53. data/spec/lib/hamster/hash/each_with_index_spec.rb +30 -0
  54. data/spec/lib/hamster/hash/empty_spec.rb +46 -0
  55. data/spec/lib/hamster/hash/eql_spec.rb +70 -0
  56. data/spec/lib/hamster/hash/except_spec.rb +43 -0
  57. data/spec/lib/hamster/hash/fetch_spec.rb +58 -0
  58. data/spec/lib/hamster/hash/filter_spec.rb +58 -0
  59. data/spec/lib/hamster/hash/find_spec.rb +44 -0
  60. data/spec/lib/hamster/hash/flat_map_spec.rb +36 -0
  61. data/spec/lib/hamster/hash/flatten_spec.rb +99 -0
  62. data/spec/lib/hamster/hash/get_spec.rb +80 -0
  63. data/spec/lib/hamster/hash/has_key_spec.rb +32 -0
  64. data/spec/lib/hamster/hash/has_value_spec.rb +28 -0
  65. data/spec/{hamster → lib/hamster}/hash/hash_spec.rb +5 -12
  66. data/spec/{hamster → lib/hamster}/hash/immutable_spec.rb +0 -0
  67. data/spec/lib/hamster/hash/inspect_spec.rb +31 -0
  68. data/spec/lib/hamster/hash/invert_spec.rb +31 -0
  69. data/spec/lib/hamster/hash/key_spec.rb +28 -0
  70. data/spec/{hamster → lib/hamster}/hash/keys_spec.rb +3 -6
  71. data/spec/lib/hamster/hash/map_spec.rb +46 -0
  72. data/spec/{hamster → lib/hamster}/hash/marshal_spec.rb +3 -3
  73. data/spec/lib/hamster/hash/merge_spec.rb +77 -0
  74. data/spec/lib/hamster/hash/min_max_spec.rb +50 -0
  75. data/spec/lib/hamster/hash/new_spec.rb +71 -0
  76. data/spec/{hamster → lib/hamster}/hash/none_spec.rb +12 -14
  77. data/spec/lib/hamster/hash/partition_spec.rb +36 -0
  78. data/spec/lib/hamster/hash/pretty_print_spec.rb +35 -0
  79. data/spec/lib/hamster/hash/put_spec.rb +81 -0
  80. data/spec/lib/hamster/hash/reduce_spec.rb +36 -0
  81. data/spec/lib/hamster/hash/remove_spec.rb +62 -0
  82. data/spec/lib/hamster/hash/reverse_each_spec.rb +28 -0
  83. data/spec/lib/hamster/hash/sample_spec.rb +14 -0
  84. data/spec/{hamster → lib/hamster}/hash/size_spec.rb +2 -2
  85. data/spec/lib/hamster/hash/slice_spec.rb +45 -0
  86. data/spec/lib/hamster/hash/sort_spec.rb +27 -0
  87. data/spec/lib/hamster/hash/store_spec.rb +54 -0
  88. data/spec/lib/hamster/hash/take_spec.rb +36 -0
  89. data/spec/lib/hamster/hash/to_a_spec.rb +14 -0
  90. data/spec/lib/hamster/hash/to_hash_spec.rb +22 -0
  91. data/spec/{hamster → lib/hamster}/hash/uniq_spec.rb +2 -4
  92. data/spec/lib/hamster/hash/values_at_spec.rb +14 -0
  93. data/spec/lib/hamster/hash/values_spec.rb +25 -0
  94. data/spec/{hamster → lib/hamster}/immutable/copying_spec.rb +0 -0
  95. data/spec/{hamster → lib/hamster}/immutable/immutable_spec.rb +0 -0
  96. data/spec/{hamster → lib/hamster}/immutable/memoize_spec.rb +2 -2
  97. data/spec/{hamster → lib/hamster}/immutable/new_spec.rb +0 -0
  98. data/spec/{hamster → lib/hamster}/immutable/transform_spec.rb +0 -0
  99. data/spec/{hamster → lib/hamster}/immutable/transform_unless_spec.rb +0 -0
  100. data/spec/lib/hamster/list/add_spec.rb +20 -0
  101. data/spec/lib/hamster/list/all_spec.rb +60 -0
  102. data/spec/{hamster → lib/hamster}/list/any_spec.rb +12 -20
  103. data/spec/{hamster → lib/hamster}/list/append_spec.rb +9 -10
  104. data/spec/lib/hamster/list/at_spec.rb +30 -0
  105. data/spec/lib/hamster/list/break_spec.rb +70 -0
  106. data/spec/{hamster → lib/hamster}/list/cadr_spec.rb +5 -8
  107. data/spec/{hamster → lib/hamster}/list/chunk_spec.rb +5 -8
  108. data/spec/{hamster → lib/hamster}/list/clear_spec.rb +4 -7
  109. data/spec/lib/hamster/list/combination_spec.rb +34 -0
  110. data/spec/{hamster → lib/hamster}/list/compact_spec.rb +5 -8
  111. data/spec/lib/hamster/list/compare_spec.rb +31 -0
  112. data/spec/{hamster → lib/hamster}/list/cons_spec.rb +5 -9
  113. data/spec/lib/hamster/list/construction_spec.rb +118 -0
  114. data/spec/{hamster → lib/hamster}/list/copying_spec.rb +3 -7
  115. data/spec/lib/hamster/list/count_spec.rb +37 -0
  116. data/spec/lib/hamster/list/cycle_spec.rb +29 -0
  117. data/spec/lib/hamster/list/delete_at_spec.rb +19 -0
  118. data/spec/lib/hamster/list/delete_spec.rb +17 -0
  119. data/spec/{hamster → lib/hamster}/list/drop_spec.rb +5 -8
  120. data/spec/lib/hamster/list/drop_while_spec.rb +39 -0
  121. data/spec/lib/hamster/list/each_slice_spec.rb +52 -0
  122. data/spec/lib/hamster/list/each_spec.rb +43 -0
  123. data/spec/lib/hamster/list/each_with_index_spec.rb +29 -0
  124. data/spec/{hamster → lib/hamster}/list/elem_index_spec.rb +4 -14
  125. data/spec/{hamster → lib/hamster}/list/elem_indices_spec.rb +5 -9
  126. data/spec/{hamster → lib/hamster}/list/empty_spec.rb +4 -13
  127. data/spec/{hamster → lib/hamster}/list/eql_spec.rb +2 -8
  128. data/spec/lib/hamster/list/fill_spec.rb +50 -0
  129. data/spec/{hamster → lib/hamster}/list/filter_spec.rb +3 -2
  130. data/spec/{hamster → lib/hamster}/list/find_all_spec.rb +3 -2
  131. data/spec/{hamster → lib/hamster}/list/find_index_spec.rb +4 -14
  132. data/spec/{hamster → lib/hamster}/list/find_indices_spec.rb +11 -9
  133. data/spec/{hamster → lib/hamster}/list/find_spec.rb +10 -16
  134. data/spec/{hamster → lib/hamster}/list/flat_map_spec.rb +0 -0
  135. data/spec/{hamster → lib/hamster}/list/flatten_spec.rb +5 -8
  136. data/spec/{hamster → lib/hamster}/list/grep_spec.rb +9 -17
  137. data/spec/{hamster → lib/hamster}/list/group_by_spec.rb +8 -24
  138. data/spec/{hamster → lib/hamster}/list/hash_spec.rb +4 -12
  139. data/spec/{hamster → lib/hamster}/list/head_spec.rb +2 -7
  140. data/spec/{hamster → lib/hamster}/list/include_spec.rb +4 -13
  141. data/spec/{hamster → lib/hamster}/list/init_spec.rb +5 -9
  142. data/spec/lib/hamster/list/inits_spec.rb +29 -0
  143. data/spec/lib/hamster/list/insert_spec.rb +47 -0
  144. data/spec/lib/hamster/list/inspect_spec.rb +30 -0
  145. data/spec/{hamster → lib/hamster}/list/intersperse_spec.rb +5 -8
  146. data/spec/lib/hamster/list/join_spec.rb +64 -0
  147. data/spec/lib/hamster/list/last_spec.rb +24 -0
  148. data/spec/{hamster → lib/hamster}/list/map_spec.rb +11 -20
  149. data/spec/lib/hamster/list/maximum_spec.rb +42 -0
  150. data/spec/{hamster → lib/hamster}/list/merge_by_spec.rb +4 -13
  151. data/spec/{hamster → lib/hamster}/list/merge_spec.rb +0 -0
  152. data/spec/lib/hamster/list/minimum_spec.rb +42 -0
  153. data/spec/lib/hamster/list/multithreading_spec.rb +48 -0
  154. data/spec/{hamster → lib/hamster}/list/none_spec.rb +11 -21
  155. data/spec/{hamster → lib/hamster}/list/one_spec.rb +12 -22
  156. data/spec/lib/hamster/list/partition_spec.rb +116 -0
  157. data/spec/lib/hamster/list/permutation_spec.rb +56 -0
  158. data/spec/{hamster → lib/hamster}/list/pop_spec.rb +1 -1
  159. data/spec/lib/hamster/list/product_spec.rb +24 -0
  160. data/spec/lib/hamster/list/reduce_spec.rb +97 -0
  161. data/spec/{hamster → lib/hamster}/list/remove_spec.rb +9 -19
  162. data/spec/{hamster → lib/hamster}/list/reverse_spec.rb +7 -14
  163. data/spec/lib/hamster/list/rotate_spec.rb +37 -0
  164. data/spec/lib/hamster/list/sample_spec.rb +14 -0
  165. data/spec/{hamster → lib/hamster}/list/select_spec.rb +3 -2
  166. data/spec/{hamster → lib/hamster}/list/size_spec.rb +4 -13
  167. data/spec/lib/hamster/list/slice_spec.rb +230 -0
  168. data/spec/{hamster → lib/hamster}/list/sorting_spec.rb +10 -20
  169. data/spec/lib/hamster/list/span_spec.rb +77 -0
  170. data/spec/{hamster → lib/hamster}/list/split_at_spec.rb +13 -14
  171. data/spec/lib/hamster/list/subsequences_spec.rb +24 -0
  172. data/spec/lib/hamster/list/sum_spec.rb +24 -0
  173. data/spec/lib/hamster/list/tail_spec.rb +31 -0
  174. data/spec/lib/hamster/list/tails_spec.rb +29 -0
  175. data/spec/{hamster → lib/hamster}/list/take_spec.rb +5 -8
  176. data/spec/{hamster → lib/hamster}/list/take_while_spec.rb +11 -17
  177. data/spec/lib/hamster/list/to_a_spec.rb +40 -0
  178. data/spec/{hamster → lib/hamster}/list/to_ary_spec.rb +1 -3
  179. data/spec/{hamster → lib/hamster}/list/to_list_spec.rb +3 -7
  180. data/spec/{hamster → lib/hamster}/list/to_set_spec.rb +2 -10
  181. data/spec/lib/hamster/list/transpose_spec.rb +20 -0
  182. data/spec/{hamster → lib/hamster}/list/union_spec.rb +5 -12
  183. data/spec/{hamster → lib/hamster}/list/uniq_spec.rb +5 -8
  184. data/spec/{hamster → lib/hamster}/list/zip_spec.rb +2 -9
  185. data/spec/lib/hamster/set/add_spec.rb +76 -0
  186. data/spec/{hamster → lib/hamster}/set/all_spec.rb +18 -14
  187. data/spec/{hamster → lib/hamster}/set/any_spec.rb +19 -16
  188. data/spec/{hamster → lib/hamster}/set/clear_spec.rb +8 -11
  189. data/spec/{hamster → lib/hamster}/set/compact_spec.rb +4 -7
  190. data/spec/{hamster → lib/hamster}/set/construction_spec.rb +4 -8
  191. data/spec/{hamster → lib/hamster}/set/copying_spec.rb +3 -5
  192. data/spec/{hamster → lib/hamster}/set/count_spec.rb +11 -16
  193. data/spec/lib/hamster/set/delete_spec.rb +72 -0
  194. data/spec/lib/hamster/set/difference_spec.rb +50 -0
  195. data/spec/lib/hamster/set/disjoint_spec.rb +26 -0
  196. data/spec/lib/hamster/set/each_spec.rb +46 -0
  197. data/spec/lib/hamster/set/empty_spec.rb +47 -0
  198. data/spec/{hamster → lib/hamster}/set/eqeq_spec.rb +0 -0
  199. data/spec/{hamster → lib/hamster}/set/eql_spec.rb +7 -1
  200. data/spec/lib/hamster/set/exclusion_spec.rb +48 -0
  201. data/spec/lib/hamster/set/filter_spec.rb +74 -0
  202. data/spec/{hamster → lib/hamster}/set/find_spec.rb +7 -11
  203. data/spec/lib/hamster/set/flatten_spec.rb +47 -0
  204. data/spec/{hamster → lib/hamster}/set/foreach_spec.rb +5 -4
  205. data/spec/{hamster → lib/hamster}/set/grep_spec.rb +1 -1
  206. data/spec/lib/hamster/set/group_by_spec.rb +60 -0
  207. data/spec/lib/hamster/set/hash_spec.rb +23 -0
  208. data/spec/lib/hamster/set/head_spec.rb +31 -0
  209. data/spec/{hamster → lib/hamster}/set/immutable_spec.rb +0 -0
  210. data/spec/lib/hamster/set/include_spec.rb +61 -0
  211. data/spec/lib/hamster/set/inspect_spec.rb +48 -0
  212. data/spec/lib/hamster/set/intersect_spec.rb +26 -0
  213. data/spec/lib/hamster/set/intersection_spec.rb +53 -0
  214. data/spec/lib/hamster/set/join_spec.rb +65 -0
  215. data/spec/lib/hamster/set/map_spec.rb +60 -0
  216. data/spec/{hamster → lib/hamster}/set/marshal_spec.rb +3 -3
  217. data/spec/{hamster → lib/hamster}/set/maximum_spec.rb +6 -15
  218. data/spec/{hamster → lib/hamster}/set/minimum_spec.rb +6 -16
  219. data/spec/lib/hamster/set/new_spec.rb +54 -0
  220. data/spec/{hamster → lib/hamster}/set/none_spec.rb +15 -15
  221. data/spec/{hamster → lib/hamster}/set/one_spec.rb +14 -16
  222. data/spec/lib/hamster/set/partition_spec.rb +53 -0
  223. data/spec/{hamster → lib/hamster}/set/product_spec.rb +6 -6
  224. data/spec/lib/hamster/set/reduce_spec.rb +56 -0
  225. data/spec/lib/hamster/set/remove_spec.rb +51 -0
  226. data/spec/{hamster/set/each_spec.rb → lib/hamster/set/reverse_each_spec.rb} +8 -7
  227. data/spec/lib/hamster/set/sample_spec.rb +14 -0
  228. data/spec/{hamster → lib/hamster}/set/size_spec.rb +0 -1
  229. data/spec/{hamster → lib/hamster}/set/sorting_spec.rb +17 -13
  230. data/spec/lib/hamster/set/subset_spec.rb +52 -0
  231. data/spec/lib/hamster/set/sum_spec.rb +24 -0
  232. data/spec/lib/hamster/set/superset_spec.rb +52 -0
  233. data/spec/lib/hamster/set/to_a_spec.rb +31 -0
  234. data/spec/lib/hamster/set/to_list_spec.rb +37 -0
  235. data/spec/{hamster → lib/hamster}/set/to_set_spec.rb +2 -6
  236. data/spec/lib/hamster/set/union_spec.rb +55 -0
  237. data/spec/{hamster → lib/hamster}/set/uniq_spec.rb +2 -5
  238. data/spec/lib/hamster/sorted_set/above_spec.rb +52 -0
  239. data/spec/lib/hamster/sorted_set/add_spec.rb +63 -0
  240. data/spec/lib/hamster/sorted_set/at_spec.rb +25 -0
  241. data/spec/lib/hamster/sorted_set/below_spec.rb +52 -0
  242. data/spec/lib/hamster/sorted_set/between_spec.rb +52 -0
  243. data/spec/lib/hamster/sorted_set/clear_spec.rb +35 -0
  244. data/spec/lib/hamster/sorted_set/construction_spec.rb +29 -0
  245. data/spec/lib/hamster/sorted_set/delete_at_spec.rb +19 -0
  246. data/spec/lib/hamster/sorted_set/delete_spec.rb +81 -0
  247. data/spec/{hamster/set → lib/hamster/sorted_set}/difference_spec.rb +5 -9
  248. data/spec/lib/hamster/sorted_set/disjoint_spec.rb +26 -0
  249. data/spec/lib/hamster/sorted_set/drop_spec.rb +29 -0
  250. data/spec/lib/hamster/sorted_set/drop_while_spec.rb +35 -0
  251. data/spec/lib/hamster/sorted_set/each_spec.rb +31 -0
  252. data/spec/lib/hamster/sorted_set/empty_spec.rb +37 -0
  253. data/spec/lib/hamster/sorted_set/eql_spec.rb +121 -0
  254. data/spec/{hamster/set → lib/hamster/sorted_set}/exclusion_spec.rb +4 -9
  255. data/spec/lib/hamster/sorted_set/fetch_spec.rb +65 -0
  256. data/spec/lib/hamster/sorted_set/filter_spec.rb +62 -0
  257. data/spec/lib/hamster/sorted_set/find_index_spec.rb +33 -0
  258. data/spec/lib/hamster/sorted_set/first_spec.rb +21 -0
  259. data/spec/lib/hamster/sorted_set/from_spec.rb +52 -0
  260. data/spec/lib/hamster/sorted_set/group_by_spec.rb +58 -0
  261. data/spec/lib/hamster/sorted_set/include_spec.rb +24 -0
  262. data/spec/lib/hamster/sorted_set/inspect_spec.rb +38 -0
  263. data/spec/lib/hamster/sorted_set/intersect_spec.rb +26 -0
  264. data/spec/lib/hamster/sorted_set/intersection_spec.rb +29 -0
  265. data/spec/lib/hamster/sorted_set/last_spec.rb +37 -0
  266. data/spec/lib/hamster/sorted_set/map_spec.rb +36 -0
  267. data/spec/lib/hamster/sorted_set/marshal_spec.rb +37 -0
  268. data/spec/lib/hamster/sorted_set/minimum_spec.rb +22 -0
  269. data/spec/lib/hamster/sorted_set/new_spec.rb +52 -0
  270. data/spec/lib/hamster/sorted_set/reverse_each_spec.rb +29 -0
  271. data/spec/lib/hamster/sorted_set/sample_spec.rb +14 -0
  272. data/spec/lib/hamster/sorted_set/size_spec.rb +18 -0
  273. data/spec/lib/hamster/sorted_set/slice_spec.rb +241 -0
  274. data/spec/lib/hamster/sorted_set/sorting_spec.rb +45 -0
  275. data/spec/lib/hamster/sorted_set/subset_spec.rb +48 -0
  276. data/spec/lib/hamster/sorted_set/superset_spec.rb +48 -0
  277. data/spec/lib/hamster/sorted_set/take_spec.rb +26 -0
  278. data/spec/lib/hamster/sorted_set/take_while_spec.rb +34 -0
  279. data/spec/lib/hamster/sorted_set/to_set_spec.rb +19 -0
  280. data/spec/lib/hamster/sorted_set/union_spec.rb +28 -0
  281. data/spec/lib/hamster/sorted_set/up_to_spec.rb +52 -0
  282. data/spec/lib/hamster/sorted_set/values_at_spec.rb +34 -0
  283. data/spec/lib/hamster/vector/add_spec.rb +68 -0
  284. data/spec/{hamster → lib/hamster}/vector/any_spec.rb +0 -0
  285. data/spec/lib/hamster/vector/assoc_spec.rb +36 -0
  286. data/spec/lib/hamster/vector/bsearch_spec.rb +58 -0
  287. data/spec/lib/hamster/vector/clear_spec.rb +34 -0
  288. data/spec/lib/hamster/vector/combination_spec.rb +82 -0
  289. data/spec/lib/hamster/vector/compact_spec.rb +30 -0
  290. data/spec/lib/hamster/vector/compare_spec.rb +32 -0
  291. data/spec/lib/hamster/vector/concat_spec.rb +35 -0
  292. data/spec/{hamster → lib/hamster}/vector/copying_spec.rb +3 -6
  293. data/spec/lib/hamster/vector/count_spec.rb +18 -0
  294. data/spec/lib/hamster/vector/delete_at_spec.rb +54 -0
  295. data/spec/lib/hamster/vector/delete_spec.rb +31 -0
  296. data/spec/lib/hamster/vector/drop_spec.rb +35 -0
  297. data/spec/lib/hamster/vector/drop_while_spec.rb +55 -0
  298. data/spec/lib/hamster/vector/each_index_spec.rb +41 -0
  299. data/spec/lib/hamster/vector/each_spec.rb +47 -0
  300. data/spec/lib/hamster/vector/each_with_index_spec.rb +40 -0
  301. data/spec/lib/hamster/vector/empty_spec.rb +44 -0
  302. data/spec/lib/hamster/vector/eql_spec.rb +77 -0
  303. data/spec/lib/hamster/vector/exist_spec.rb +4 -4
  304. data/spec/lib/hamster/vector/exists_spec.rb +4 -4
  305. data/spec/lib/hamster/vector/fetch_spec.rb +65 -0
  306. data/spec/lib/hamster/vector/fill_spec.rb +89 -0
  307. data/spec/lib/hamster/vector/filter_spec.rb +64 -0
  308. data/spec/{hamster → lib/hamster}/vector/first_spec.rb +2 -6
  309. data/spec/lib/hamster/vector/flatten_spec.rb +44 -0
  310. data/spec/lib/hamster/vector/get_spec.rb +75 -0
  311. data/spec/lib/hamster/vector/group_by_spec.rb +58 -0
  312. data/spec/{hamster → lib/hamster}/vector/include_spec.rb +2 -6
  313. data/spec/lib/hamster/vector/insert_spec.rb +69 -0
  314. data/spec/lib/hamster/vector/inspect_spec.rb +50 -0
  315. data/spec/{hamster/set → lib/hamster/vector}/join_spec.rb +23 -18
  316. data/spec/{hamster → lib/hamster}/vector/last_spec.rb +12 -3
  317. data/spec/{hamster → lib/hamster}/vector/length_spec.rb +12 -3
  318. data/spec/lib/hamster/vector/ltlt_spec.rb +20 -2
  319. data/spec/lib/hamster/vector/map_spec.rb +52 -0
  320. data/spec/lib/hamster/vector/marshal_spec.rb +32 -0
  321. data/spec/lib/hamster/vector/maximum_spec.rb +36 -0
  322. data/spec/lib/hamster/vector/minimum_spec.rb +36 -0
  323. data/spec/lib/hamster/vector/multiply_spec.rb +48 -0
  324. data/spec/lib/hamster/vector/new_spec.rb +51 -0
  325. data/spec/lib/hamster/vector/partition_spec.rb +53 -0
  326. data/spec/lib/hamster/vector/permutation_spec.rb +92 -0
  327. data/spec/lib/hamster/vector/pop_spec.rb +27 -0
  328. data/spec/lib/hamster/vector/product_spec.rb +71 -0
  329. data/spec/lib/hamster/vector/reduce_spec.rb +108 -0
  330. data/spec/lib/hamster/vector/remove_spec.rb +44 -0
  331. data/spec/lib/hamster/vector/repeated_combination_spec.rb +78 -0
  332. data/spec/lib/hamster/vector/repeated_permutation_spec.rb +94 -0
  333. data/spec/lib/hamster/vector/reverse_each_spec.rb +32 -0
  334. data/spec/lib/hamster/vector/reverse_spec.rb +22 -0
  335. data/spec/lib/hamster/vector/rindex_spec.rb +37 -0
  336. data/spec/lib/hamster/vector/rotate_spec.rb +74 -0
  337. data/spec/lib/hamster/vector/sample_spec.rb +14 -0
  338. data/spec/{hamster → lib/hamster}/vector/set_spec.rb +48 -14
  339. data/spec/lib/hamster/vector/shift_spec.rb +28 -0
  340. data/spec/lib/hamster/vector/shuffle_spec.rb +44 -0
  341. data/spec/lib/hamster/vector/slice_spec.rb +241 -0
  342. data/spec/lib/hamster/vector/sorting_spec.rb +57 -0
  343. data/spec/{hamster/set → lib/hamster/vector}/sum_spec.rb +3 -9
  344. data/spec/lib/hamster/vector/take_spec.rb +29 -0
  345. data/spec/lib/hamster/vector/take_while_spec.rb +35 -0
  346. data/spec/{hamster → lib/hamster}/vector/to_a_spec.rb +11 -12
  347. data/spec/{hamster → lib/hamster}/vector/to_ary_spec.rb +0 -0
  348. data/spec/{hamster/set → lib/hamster/vector}/to_list_spec.rb +7 -12
  349. data/spec/lib/hamster/vector/to_set_spec.rb +23 -0
  350. data/spec/lib/hamster/vector/transpose_spec.rb +49 -0
  351. data/spec/lib/hamster/vector/uniq_spec.rb +56 -0
  352. data/spec/lib/hamster/vector/unshift_spec.rb +29 -0
  353. data/spec/lib/hamster/vector/values_at_spec.rb +34 -0
  354. data/spec/lib/hamster/vector/zip_spec.rb +58 -0
  355. data/spec/spec_helper.rb +34 -1
  356. metadata +684 -467
  357. data/lib/hamster/core_ext/enumerator.rb +0 -16
  358. data/lib/hamster/experimental/mutable_stack.rb +0 -30
  359. data/lib/hamster/groupable.rb +0 -12
  360. data/lib/hamster/queue.rb +0 -86
  361. data/lib/hamster/sorter.rb +0 -25
  362. data/lib/hamster/stack.rb +0 -77
  363. data/lib/hamster/tuple.rb +0 -24
  364. data/spec/hamster/core_ext/enumerator_spec.rb +0 -19
  365. data/spec/hamster/experimental/mutable_stack/pop_spec.rb +0 -35
  366. data/spec/hamster/experimental/mutable_stack/push_spec.rb +0 -21
  367. data/spec/hamster/hash/any_spec.rb +0 -52
  368. data/spec/hamster/hash/clear_spec.rb +0 -29
  369. data/spec/hamster/hash/construction_spec.rb +0 -27
  370. data/spec/hamster/hash/delete_spec.rb +0 -38
  371. data/spec/hamster/hash/each_spec.rb +0 -30
  372. data/spec/hamster/hash/empty_spec.rb +0 -27
  373. data/spec/hamster/hash/eql_spec.rb +0 -70
  374. data/spec/hamster/hash/except_spec.rb +0 -22
  375. data/spec/hamster/hash/fetch_spec.rb +0 -72
  376. data/spec/hamster/hash/filter_spec.rb +0 -48
  377. data/spec/hamster/hash/find_spec.rb +0 -45
  378. data/spec/hamster/hash/get_spec.rb +0 -55
  379. data/spec/hamster/hash/has_key_spec.rb +0 -26
  380. data/spec/hamster/hash/inspect_spec.rb +0 -24
  381. data/spec/hamster/hash/map_spec.rb +0 -49
  382. data/spec/hamster/hash/merge_spec.rb +0 -30
  383. data/spec/hamster/hash/new_spec.rb +0 -21
  384. data/spec/hamster/hash/put_spec.rb +0 -67
  385. data/spec/hamster/hash/reduce_spec.rb +0 -52
  386. data/spec/hamster/hash/remove_spec.rb +0 -48
  387. data/spec/hamster/hash/slice_spec.rb +0 -26
  388. data/spec/hamster/hash/values_spec.rb +0 -29
  389. data/spec/hamster/list/add_spec.rb +0 -11
  390. data/spec/hamster/list/all_spec.rb +0 -84
  391. data/spec/hamster/list/at_spec.rb +0 -37
  392. data/spec/hamster/list/break_spec.rb +0 -73
  393. data/spec/hamster/list/combinations_spec.rb +0 -41
  394. data/spec/hamster/list/construction_spec.rb +0 -137
  395. data/spec/hamster/list/count_spec.rb +0 -52
  396. data/spec/hamster/list/cycle_spec.rb +0 -36
  397. data/spec/hamster/list/drop_while_spec.rb +0 -47
  398. data/spec/hamster/list/each_slice_spec.rb +0 -64
  399. data/spec/hamster/list/each_spec.rb +0 -56
  400. data/spec/hamster/list/each_with_index_spec.rb +0 -33
  401. data/spec/hamster/list/inits_spec.rb +0 -34
  402. data/spec/hamster/list/inspect_spec.rb +0 -33
  403. data/spec/hamster/list/join_spec.rb +0 -64
  404. data/spec/hamster/list/last_spec.rb +0 -34
  405. data/spec/hamster/list/maximum_spec.rb +0 -58
  406. data/spec/hamster/list/minimum_spec.rb +0 -58
  407. data/spec/hamster/list/partition_spec.rb +0 -63
  408. data/spec/hamster/list/product_spec.rb +0 -34
  409. data/spec/hamster/list/reduce_spec.rb +0 -72
  410. data/spec/hamster/list/slice_spec.rb +0 -40
  411. data/spec/hamster/list/span_spec.rb +0 -75
  412. data/spec/hamster/list/sum_spec.rb +0 -34
  413. data/spec/hamster/list/tail_spec.rb +0 -38
  414. data/spec/hamster/list/tails_spec.rb +0 -34
  415. data/spec/hamster/list/to_a_spec.rb +0 -42
  416. data/spec/hamster/queue/clear_spec.rb +0 -28
  417. data/spec/hamster/queue/construction_spec.rb +0 -34
  418. data/spec/hamster/queue/dequeue_spec.rb +0 -30
  419. data/spec/hamster/queue/empty_spec.rb +0 -35
  420. data/spec/hamster/queue/head_spec.rb +0 -25
  421. data/spec/hamster/queue/inspect_spec.rb +0 -23
  422. data/spec/hamster/queue/to_a_spec.rb +0 -32
  423. data/spec/hamster/queue/to_list_spec.rb +0 -34
  424. data/spec/hamster/set/add_spec.rb +0 -40
  425. data/spec/hamster/set/delete_spec.rb +0 -38
  426. data/spec/hamster/set/empty_spec.rb +0 -25
  427. data/spec/hamster/set/filter_spec.rb +0 -72
  428. data/spec/hamster/set/flatten_spec.rb +0 -47
  429. data/spec/hamster/set/group_by_spec.rb +0 -56
  430. data/spec/hamster/set/hash_spec.rb +0 -20
  431. data/spec/hamster/set/head_spec.rb +0 -28
  432. data/spec/hamster/set/include_spec.rb +0 -27
  433. data/spec/hamster/set/inspect_spec.rb +0 -24
  434. data/spec/hamster/set/intersection_spec.rb +0 -36
  435. data/spec/hamster/set/map_spec.rb +0 -49
  436. data/spec/hamster/set/new_spec.rb +0 -21
  437. data/spec/hamster/set/partition_spec.rb +0 -59
  438. data/spec/hamster/set/reduce_spec.rb +0 -62
  439. data/spec/hamster/set/remove_spec.rb +0 -48
  440. data/spec/hamster/set/subset_spec.rb +0 -31
  441. data/spec/hamster/set/superset_spec.rb +0 -31
  442. data/spec/hamster/set/to_a_spec.rb +0 -32
  443. data/spec/hamster/set/union_spec.rb +0 -35
  444. data/spec/hamster/sorter/immutable_spec.rb +0 -9
  445. data/spec/hamster/stack/clear_spec.rb +0 -28
  446. data/spec/hamster/stack/construction_spec.rb +0 -34
  447. data/spec/hamster/stack/copying_spec.rb +0 -23
  448. data/spec/hamster/stack/empty_spec.rb +0 -23
  449. data/spec/hamster/stack/eql_spec.rb +0 -48
  450. data/spec/hamster/stack/immutable_spec.rb +0 -9
  451. data/spec/hamster/stack/inspect_spec.rb +0 -23
  452. data/spec/hamster/stack/peek_spec.rb +0 -30
  453. data/spec/hamster/stack/pop_spec.rb +0 -31
  454. data/spec/hamster/stack/push_spec.rb +0 -31
  455. data/spec/hamster/stack/size_spec.rb +0 -25
  456. data/spec/hamster/stack/to_a_spec.rb +0 -32
  457. data/spec/hamster/stack/to_ary.rb +0 -37
  458. data/spec/hamster/stack/to_list_spec.rb +0 -25
  459. data/spec/hamster/trie/remove_spec.rb +0 -117
  460. data/spec/hamster/tuple/construction_spec.rb +0 -30
  461. data/spec/hamster/tuple/copying_spec.rb +0 -17
  462. data/spec/hamster/tuple/eql_spec.rb +0 -78
  463. data/spec/hamster/tuple/first_spec.rb +0 -14
  464. data/spec/hamster/tuple/immutable_spec.rb +0 -9
  465. data/spec/hamster/tuple/inspect_spec.rb +0 -14
  466. data/spec/hamster/tuple/last_spec.rb +0 -14
  467. data/spec/hamster/tuple/to_a_spec.rb +0 -30
  468. data/spec/hamster/tuple/to_ary_spec.rb +0 -37
  469. data/spec/hamster/undefined/erase_spec.rb +0 -36
  470. data/spec/hamster/vector/add_spec.rb +0 -56
  471. data/spec/hamster/vector/clear_spec.rb +0 -28
  472. data/spec/hamster/vector/each_spec.rb +0 -35
  473. data/spec/hamster/vector/each_with_index_spec.rb +0 -33
  474. data/spec/hamster/vector/empty_spec.rb +0 -32
  475. data/spec/hamster/vector/eql_spec.rb +0 -53
  476. data/spec/hamster/vector/filter_spec.rb +0 -58
  477. data/spec/hamster/vector/get_spec.rb +0 -58
  478. data/spec/hamster/vector/inspect_spec.rb +0 -33
  479. data/spec/hamster/vector/map_spec.rb +0 -57
  480. data/spec/hamster/vector/new_spec.rb +0 -48
  481. data/spec/hamster/vector/reduce_spec.rb +0 -62
  482. data/spec/lib/hamster/vector/cons_spec.rb +0 -48
@@ -0,0 +1,1014 @@
1
+ require "forwardable"
2
+ require "hamster/immutable"
3
+ require "hamster/enumerable"
4
+
5
+ module Hamster
6
+ def self.sorted_set(*items, &block)
7
+ (items.empty? && block.nil?) ? EmptySortedSet : SortedSet.new(items, &block)
8
+ end
9
+
10
+ # A `SortedSet` is a collection of ordered values with no duplicates. Unlike a
11
+ # {Vector}, in which items can appear in any arbitrary order, a `SortedSet` always
12
+ # keeps items either in their natural order, or in an order defined by a comparator
13
+ # block which is provided at initialization time.
14
+ #
15
+ # `SortedSet` uses `#<=>` (or its comparator block) to determine which items are
16
+ # equivalent. If the comparator indicates that an existing item and a new item are
17
+ # equal, any attempt to insert the new item will have no effect.
18
+ #
19
+ # This means that *all* the items inserted into any one `SortedSet` must all be
20
+ # comparable. For example, you cannot put `String`s and `Integer`s in the same
21
+ # `SortedSet`. This is unlike {Set}, which can store items of any type, as long
22
+ # as they all support `#hash` and `#eql?`.
23
+ #
24
+ # A `SortedSet` can be created in any of the following ways:
25
+ #
26
+ # Hamster.sorted_set('Tom', 'Dick', 'Harry')
27
+ # Hamster::SortedSet.new([1, 2, 3]) # any Enumerable can be used to initialize
28
+ # Hamster::SortedSet['A', 'B', 'C', 'D']
29
+ #
30
+ # Or if you want to use a custom ordering:
31
+ #
32
+ # Hamster.sorted_set('Tom', 'Dick', 'Harry') { |a, b| a.reverse <=> b.reverse }
33
+ # Hamster.sorted_set('Tom', 'Dick', 'Harry') { |str| str.reverse }
34
+ # Hamster::SortedSet.new([1,2,3]) { |a, b| -a <=> -b }
35
+ # Hamster::SortedSet.new([1, 2, 3]) { |num| -num }
36
+ #
37
+ # As you can see, `SortedSet` can use a 2-parameter block which returns 0, 1, or -1
38
+ # as a comparator (like `Array#sort`), *or* use a 1-parameter block to derive sort
39
+ # keys (like `Array#sort_by`) which will be compared using `#<=>`.
40
+ #
41
+ # Like all Hamster collections, `SortedSet`s are immutable. Any operation which you
42
+ # might expect to "modify" a `SortedSet` will actually return a new collection and
43
+ # leave the existing one unchanged.
44
+ #
45
+ # `SortedSet` supports the same basic set-theoretic operations as {Set}, including
46
+ # {#union}, {#intersection}, {#difference}, and {#exclusion}, as well as {#subset?},
47
+ # {#superset?}, and so on. Unlike {Set}, it does not define comparison operators like
48
+ # {#>} or {#<} as aliases for the superset/subset predicates. Instead, these comparison
49
+ # operators do a item-by-item comparison between the `SortedSet` and another sequential
50
+ # collection. (See `Array#<=>` for details.)
51
+ #
52
+ # Additionally, since `SortedSet`s are ordered, they also support indexed retrieval
53
+ # of items (or slices of items) using {#at} or {#[]}. Like {Vector} (or `Array`),
54
+ # negative indices count back from the end of the `SortedSet`.
55
+ #
56
+ # Getting the {#max} or {#min} item from a `SortedSet`, as defined by its comparator,
57
+ # is very efficient.
58
+ #
59
+ class SortedSet
60
+ extend Forwardable
61
+ include Immutable
62
+ include Enumerable
63
+
64
+ class << self
65
+ # Create a new `SortedSet` populated with the given items. This method does not
66
+ # accept a comparator block.
67
+ #
68
+ # @return [SortedSet]
69
+ def [](*items)
70
+ new(items)
71
+ end
72
+
73
+ # Return an empty `SortedSet`. If used on a subclass, returns an empty instance
74
+ # of that class.
75
+ #
76
+ # @return [SortedSet]
77
+ def empty
78
+ @empty ||= self.alloc(EmptyAVLNode, lambda { |a,b| a <=> b })
79
+ end
80
+
81
+ # "Raw" allocation of a new `SortedSet`. Used internally to create a new
82
+ # instance quickly after obtaining a modified binary tree.
83
+ #
84
+ # @return [Set]
85
+ # @private
86
+ def alloc(node, comparator)
87
+ result = allocate
88
+ result.instance_variable_set(:@node, node)
89
+ result.instance_variable_set(:@comparator, comparator)
90
+ result
91
+ end
92
+ end
93
+
94
+ def initialize(items=[], &block)
95
+ items = items.to_a
96
+ if block
97
+ @comparator = if block.arity == 1
98
+ lambda { |a,b| block.call(a) <=> block.call(b) }
99
+ else
100
+ block
101
+ end
102
+ items = items.sort(&@comparator)
103
+ else
104
+ items = items.sort
105
+ end
106
+ @node = AVLNode.from_items(items, 0, items.size-1)
107
+ end
108
+
109
+ # Return `true` if this `SortedSet` contains no items.
110
+ #
111
+ # @return [Boolean]
112
+ def empty?
113
+ @node.empty?
114
+ end
115
+ def_delegator :self, :empty?, :null?
116
+
117
+ # Return the number of items in this `SortedSet`.
118
+ #
119
+ # @return [Integer]
120
+ def size
121
+ @node.size
122
+ end
123
+ def_delegator :self, :size, :length
124
+
125
+ # Return a new `SortedSet` with `item` added. If `item` is already in the set,
126
+ # return `self`.
127
+ #
128
+ # @param item [Object] The object to add
129
+ # @return [SortedSet]
130
+ def add(item)
131
+ return self if include?(item)
132
+ node = @node.insert(item, @comparator)
133
+ self.class.alloc(node, @comparator)
134
+ end
135
+ def_delegator :self, :add, :<<
136
+ def_delegator :self, :add, :conj
137
+ def_delegator :self, :add, :conjoin
138
+
139
+ # If `item` is not a member of this `SortedSet`, return a new `SortedSet` with
140
+ # `item` added. Otherwise, return `false`.
141
+ #
142
+ # @param item [Object] The object to add
143
+ # @return [SortedSet, false]
144
+ def add?(item)
145
+ !include?(item) && add(item)
146
+ end
147
+
148
+ # Return a new `SortedSet` with `item` removed. If `item` is not a member of the set,
149
+ # return `self`.
150
+ #
151
+ # @param item [Object] The object to remove
152
+ # @return [SortedSet]
153
+ def delete(item)
154
+ return self if not include?(item)
155
+ node = @node.delete(item, @comparator)
156
+ if node.empty?
157
+ self.class.empty
158
+ else
159
+ self.class.alloc(node, @comparator)
160
+ end
161
+ end
162
+
163
+ # If `item` is a member of this `SortedSet`, return a new `SortedSet` with
164
+ # `item` removed. Otherwise, return `false`.
165
+ #
166
+ # @param item [Object] The object to remove
167
+ # @return [SortedSet, false]
168
+ def delete?(item)
169
+ include?(item) && delete(item)
170
+ end
171
+
172
+ # Return a new `SortedSet` with the item at `index` removed. If the given `index`
173
+ # does not exist (if it is too high or too low), return `self`.
174
+ #
175
+ # @param index [Integer] The index to remove
176
+ # @return [SortedSet]
177
+ def delete_at(index)
178
+ (item = at(index)) ? delete(item) : self
179
+ end
180
+
181
+ # Retrieve the item at `index`. If there is none (either the provided index
182
+ # is too high or too low), return `nil`.
183
+ #
184
+ # @param index [Integer] The index to retrieve
185
+ # @return [Object]
186
+ def at(index)
187
+ index += @node.size if index < 0
188
+ return nil if index >= @node.size || index < 0
189
+ @node.at(index)
190
+ end
191
+
192
+ # Retrieve the value at `index`, or use the provided default value or block,
193
+ # or otherwise raise an `IndexError`.
194
+ #
195
+ # @overload fetch(index)
196
+ # Retrieve the value at the given index, or raise an `IndexError` if it is
197
+ # not found.
198
+ # @param index [Integer] The index to look up
199
+ # @overload fetch(index) { |index| ... }
200
+ # Retrieve the value at the given index, or call the optional
201
+ # code block (with the non-existent index) and get its return value.
202
+ # @yield [index] The index which does not exist
203
+ # @yieldreturn [Object] Object to return instead
204
+ # @param index [Integer] The index to look up
205
+ # @overload fetch(index, default)
206
+ # Retrieve the value at the given index, or else return the provided
207
+ # `default` value.
208
+ # @param index [Integer] The index to look up
209
+ # @param default [Object] Object to return if the key is not found
210
+ #
211
+ # @return [Object]
212
+ def fetch(index, default = (missing_default = true))
213
+ if index >= -@node.size && index < @node.size
214
+ at(index)
215
+ elsif block_given?
216
+ yield(index)
217
+ elsif !missing_default
218
+ default
219
+ else
220
+ raise IndexError, "index #{index} outside of sorted set bounds"
221
+ end
222
+ end
223
+
224
+ # Element reference. Return the item at a specific index, or a specified,
225
+ # contiguous range of items (as a new `SortedSet`).
226
+ #
227
+ # @overload set[index]
228
+ # Return the item at `index`.
229
+ # @param index [Integer] The index to retrieve.
230
+ # @overload set[start, length]
231
+ # Return a subset starting at index `start` and continuing for `length` elements.
232
+ # @param start [Integer] The index to start retrieving items from.
233
+ # @param length [Integer] The number of items to retrieve.
234
+ # @overload set[range]
235
+ # Return a subset specified by the given `range` of indices.
236
+ # @param range [Range] The range of indices to retrieve.
237
+ #
238
+ # @return [Object]
239
+ def [](arg, length = (missing_length = true))
240
+ if missing_length
241
+ if arg.is_a?(Range)
242
+ from, to = arg.begin, arg.end
243
+ from += @node.size if from < 0
244
+ to += @node.size if to < 0
245
+ to += 1 if !arg.exclude_end?
246
+ length = to - from
247
+ length = 0 if length < 0
248
+ subsequence(from, length)
249
+ else
250
+ at(arg)
251
+ end
252
+ else
253
+ arg += @node.size if arg < 0
254
+ subsequence(arg, length)
255
+ end
256
+ end
257
+ def_delegator :self, :[], :slice
258
+
259
+ # Return a new `SortedSet` with only the elements at the given `indices`.
260
+ # If any of the `indices` do not exist, they will be skipped.
261
+ #
262
+ # @param indices [Array] The indices to retrieve and gather into a new `SortedSet`
263
+ # @return [SortedSet]
264
+ def values_at(*indices)
265
+ indices.select! { |i| i >= -@node.size && i < @node.size }
266
+ self.class.new(indices.map! { |i| at(i) })
267
+ end
268
+
269
+ # Call the given block once for each item in the set, passing each
270
+ # item from first to last successively to the block.
271
+ #
272
+ # @return [self]
273
+ def each(&block)
274
+ return @node.to_enum if not block_given?
275
+ @node.each(&block)
276
+ self
277
+ end
278
+
279
+ # Call the given block once for each item in the set, passing each
280
+ # item starting from the last, and counting back to the first, successively to
281
+ # the block.
282
+ #
283
+ # @return [self]
284
+ def reverse_each(&block)
285
+ return @node.enum_for(:reverse_each) if not block_given?
286
+ @node.reverse_each(&block)
287
+ self
288
+ end
289
+
290
+ # Return the "lowest" element in this set, as determined by its sort order.
291
+ # @return [Object]
292
+ def min
293
+ @node.min
294
+ end
295
+ alias :first :min
296
+ def_delegator :self, :first, :head
297
+
298
+ # Return the "highest" element in this set, as determined by its sort order.
299
+ # @return [Object]
300
+ def max
301
+ @node.max
302
+ end
303
+ alias :last :max
304
+
305
+ # Return a new `SortedSet` containing all elements for which the given block returns
306
+ # true.
307
+ #
308
+ # @return [SortedSet]
309
+ def filter
310
+ return enum_for(:filter) unless block_given?
311
+ reduce(self) { |set, item| yield(item) ? set : set.delete(item) }
312
+ end
313
+
314
+ # Invoke the given block once for each item in the set, and return a new
315
+ # `SortedSet` containing the values returned by the block.
316
+ #
317
+ # @return [SortedSet]
318
+ def map
319
+ return enum_for(:map) if not block_given?
320
+ return self if empty?
321
+ self.class.new(super, &@comparator)
322
+ end
323
+ def_delegator :self, :map, :collect
324
+
325
+ # Return `true` if the given item is present in this `SortedSet`. More precisely,
326
+ # return `true` if an object which compares as "equal" using this set's
327
+ # comparator is present.
328
+ #
329
+ # @param item [Object] The object to check for
330
+ # @return [Boolean]
331
+ def include?(item)
332
+ @node.include?(item, @comparator)
333
+ end
334
+ def_delegator :self, :include?, :member?
335
+
336
+ # Return a new `SortedSet` with the same items, but a sort order determined by
337
+ # the given block.
338
+ #
339
+ # @return [SortedSet]
340
+ def sort(&block)
341
+ block ||= lambda { |a,b| a <=> b }
342
+ self.class.new(self.to_a, &block)
343
+ end
344
+ alias :sort_by :sort
345
+
346
+ # Return the index of the first object in this set which is equal to
347
+ # `obj`. Rather than using `#==`, we use `#<=>` (or our comparator block) for
348
+ # comparisons. This means we can find the index in O(log N) time, rather than O(N).
349
+ #
350
+ # @param obj [Object] The object to search for
351
+ # @return [Integer]
352
+ def find_index(obj = (missing_obj = true), &block)
353
+ if !missing_obj
354
+ # Enumerable provides a default implementation, but this is more efficient
355
+ node = @node
356
+ index = node.left.size
357
+ while !node.empty?
358
+ direction = node.direction(obj, @comparator)
359
+ if direction > 0
360
+ node = node.right
361
+ index += node.left.size
362
+ elsif direction < 0
363
+ node = node.left
364
+ index -= node.right.size
365
+ else
366
+ return index
367
+ end
368
+ end
369
+ nil
370
+ else
371
+ super(&block)
372
+ end
373
+ end
374
+ def_delegator :self, :find_index, :index
375
+
376
+ # Drop the first `n` elements and return the rest in a new `SortedSet`.
377
+ # @param n [Integer] The number of elements to remove
378
+ # @return [SortedSet]
379
+ def drop(n)
380
+ self.class.new(super)
381
+ end
382
+
383
+ # Return only the first `n` elements in a new `SortedSet`.
384
+ # @param n [Integer] The number of elements to retain
385
+ # @return [SortedSet]
386
+ def take(n)
387
+ self.class.new(super)
388
+ end
389
+
390
+ # Drop elements up to, but not including, the first element for which the
391
+ # block returns `nil` or `false`. Gather the remaining elements into a new
392
+ # `SortedSet`. If no block is given, an `Enumerator` is returned instead.
393
+ #
394
+ # @return [SortedSet, Enumerator]
395
+ def drop_while
396
+ return enum_for(:drop_while) if not block_given?
397
+ self.class.new(super)
398
+ end
399
+
400
+ # Gather elements up to, but not including, the first element for which the
401
+ # block returns `nil` or `false`, and return them in a new `SortedSet`. If no block
402
+ # is given, an `Enumerator` is returned instead.
403
+ #
404
+ # @return [SortedSet, Enumerator]
405
+ def take_while
406
+ return enum_for(:take_while) if not block_given?
407
+ self.class.new(super)
408
+ end
409
+
410
+ # Return a new `SortedSet` which contains all the members of both this set and `other`.
411
+ # `other` can be any `Enumerable` object.
412
+ #
413
+ # @example
414
+ # Hamster::SortedSet[1, 2] | Hamster::SortedSet[2, 3]
415
+ # # => Hamster::SortedSet[1, 2, 3]
416
+ #
417
+ # @param other [Enumerable] The collection to merge with
418
+ # @return [SortedSet]
419
+ def union(other)
420
+ self.class.alloc(@node.bulk_insert(other, @comparator), @comparator)
421
+ end
422
+ def_delegator :self, :union, :|
423
+ def_delegator :self, :union, :+
424
+ def_delegator :self, :union, :merge
425
+
426
+ # Return a new `SortedSet` which contains all the items which are members of both
427
+ # this set and `other`. `other` can be any `Enumerable` object.
428
+ #
429
+ # @example
430
+ # Hamster::SortedSet[1, 2] & Hamster::SortedSet[2, 3]
431
+ # # => Hamster::SortedSet[2]
432
+ #
433
+ # @param other [Enumerable] The collection to intersect with
434
+ # @return [SortedSet]
435
+ def intersection(other)
436
+ self.class.alloc(@node.keep_only(other, @comparator), @comparator)
437
+ end
438
+ def_delegator :self, :intersection, :intersect
439
+ def_delegator :self, :intersection, :&
440
+
441
+ # Return a new `SortedSet` with all the items in `other` removed. `other` can be
442
+ # any `Enumerable` object.
443
+ #
444
+ # @example
445
+ # Hamster::SortedSet[1, 2] - Hamster::SortedSet[2, 3]
446
+ # # => Hamster::SortedSet[1]
447
+ #
448
+ # @param other [Enumerable] The collection to subtract from this set
449
+ # @return [SortedSet]
450
+ def difference(other)
451
+ self.class.alloc(@node.bulk_delete(other, @comparator), @comparator)
452
+ end
453
+ def_delegator :self, :difference, :diff
454
+ def_delegator :self, :difference, :subtract
455
+ def_delegator :self, :difference, :-
456
+
457
+ # Return a new `SortedSet` with all the items which are members of this
458
+ # set or of `other`, but not both. `other` can be any `Enumerable` object.
459
+ #
460
+ # @example
461
+ # Hamster::SortedSet[1, 2] ^ Hamster::SortedSet[2, 3]
462
+ # # => Hamster::SortedSet[1, 3]
463
+ #
464
+ # @param other [Enumerable] The collection to take the exclusive disjunction of
465
+ # @return [SortedSet]
466
+ def exclusion(other)
467
+ ((self | other) - (self & other))
468
+ end
469
+ def_delegator :self, :exclusion, :^
470
+
471
+ # Return `true` if all items in this set are also in `other`.
472
+ #
473
+ # @param other [Enumerable]
474
+ # @return [Boolean]
475
+ def subset?(other)
476
+ return false if other.size < size
477
+ all? { |item| other.include?(item) }
478
+ end
479
+
480
+ # Return `true` if all items in `other` are also in this set.
481
+ #
482
+ # @param other [Enumerable]
483
+ # @return [Boolean]
484
+ def superset?(other)
485
+ other.subset?(self)
486
+ end
487
+
488
+ # Returns `true` if `other` contains all the items in this set, plus at least
489
+ # one item which is not in this set.
490
+ #
491
+ # @param other [Enumerable]
492
+ # @return [Boolean]
493
+ def proper_subset?(other)
494
+ return false if other.size <= size
495
+ all? { |item| other.include?(item) }
496
+ end
497
+
498
+ # Returns `true` if this set contains all the items in `other`, plus at least
499
+ # one item which is not in `other`.
500
+ #
501
+ # @param other [Enumerable]
502
+ # @return [Boolean]
503
+ def proper_superset?(other)
504
+ other.proper_subset?(self)
505
+ end
506
+
507
+ # Return `true` if this set and `other` do not share any items.
508
+ #
509
+ # @param other [Enumerable]
510
+ # @return [Boolean]
511
+ def disjoint?(other)
512
+ if size < other.size
513
+ each { |item| return false if other.include?(item) }
514
+ else
515
+ other.each { |item| return false if include?(item) }
516
+ end
517
+ true
518
+ end
519
+
520
+ # Return `true` if this set and `other` have at least one item in common.
521
+ #
522
+ # @param other [Enumerable]
523
+ # @return [Boolean]
524
+ def intersect?(other)
525
+ !disjoint?(other)
526
+ end
527
+
528
+ def_delegator :self, :group_by, :group
529
+ def_delegator :self, :group_by, :classify
530
+
531
+ # With a block, yield all the items which are "higher" than `item` (as defined
532
+ # by the set's comparator). Otherwise, return them as a new `SortedSet`.
533
+ #
534
+ # @param item [Object]
535
+ def above(item, &block)
536
+ if block_given?
537
+ @node.each_greater(item, @comparator, false, &block)
538
+ else
539
+ self.class.alloc(@node.suffix(item, @comparator, false), @comparator)
540
+ end
541
+ end
542
+
543
+ # With a block, yield all the items which are "higher" than `item` (as defined
544
+ # by the set's comparator). Otherwise, return them as a new `SortedSet`.
545
+ #
546
+ # @param item [Object]
547
+ def below(item, &block)
548
+ if block_given?
549
+ @node.each_less(item, @comparator, false, &block)
550
+ else
551
+ self.class.alloc(@node.prefix(item, @comparator, false), @comparator)
552
+ end
553
+ end
554
+
555
+ # With a block, yield all the items which are "higher" or equal to `item`
556
+ # (as determined by the set's comparator). Otherwise, return them as a new
557
+ # `SortedSet`.
558
+ #
559
+ # @param item [Object]
560
+ def from(item, &block)
561
+ if block_given?
562
+ @node.each_greater(item, @comparator, true, &block)
563
+ else
564
+ self.class.alloc(@node.suffix(item, @comparator, true), @comparator)
565
+ end
566
+ end
567
+
568
+ # With a block, yield all the items which are "lower" than `item` (as defined
569
+ # by the set's comparator). Otherwise, return them as a new `SortedSet`.
570
+ #
571
+ # @param item [Object]
572
+ def up_to(item, &block)
573
+ if block_given?
574
+ @node.each_less(item, @comparator, true, &block)
575
+ else
576
+ self.class.alloc(@node.prefix(item, @comparator, true), @comparator)
577
+ end
578
+ end
579
+
580
+ # With a block, yield all the items which are equal or higher than `from` and
581
+ # equal or less than `to` (as determined by the set's comparator). Otherwise,
582
+ # return the specified range of items as a new `SortedSet`.
583
+ #
584
+ # @param from [Object]
585
+ # @param to [Object]
586
+ def between(from, to, &block)
587
+ if block_given?
588
+ @node.each_between(from, to, @comparator, &block)
589
+ else
590
+ self.class.alloc(@node.between(from, to, @comparator), @comparator)
591
+ end
592
+ end
593
+
594
+ # Return a randomly chosen item from this set. If the set is empty, return `nil`.
595
+ #
596
+ # @return [Object]
597
+ def sample
598
+ @node.at(rand(@node.size))
599
+ end
600
+
601
+ # Return an empty `SortedSet` instance, of the same class as this one. Useful if you
602
+ # have multiple subclasses of `SortedSet` and want to treat them polymorphically.
603
+ #
604
+ # @return [Hash]
605
+ def clear
606
+ self.class.empty
607
+ end
608
+
609
+ # Return true if `other` has the same type and contents as this `SortedSet`.
610
+ #
611
+ # @param other [Object] The object to compare with
612
+ # @return [Boolean]
613
+ def eql?(other)
614
+ return true if other.equal?(self)
615
+ return false if not instance_of?(other.class)
616
+ return false if size != other.size
617
+ a, b = self.to_enum, other.to_enum
618
+ while true
619
+ return false if !a.next.eql?(b.next)
620
+ end
621
+ rescue StopIteration
622
+ true
623
+ end
624
+
625
+ # See `Object#hash`.
626
+ # @return [Integer]
627
+ def hash
628
+ reduce(0) { |hash, item| (hash << 5) - hash + item.hash }
629
+ end
630
+
631
+ def_delegator :self, :dup, :uniq
632
+ def_delegator :self, :dup, :nub
633
+ def_delegator :self, :dup, :remove_duplicates
634
+
635
+ # @return [::Array]
636
+ # @private
637
+ def marshal_dump
638
+ if @comparator
639
+ raise TypeError, "can't dump SortedSet with custom sort order"
640
+ else
641
+ to_a
642
+ end
643
+ end
644
+
645
+ # @private
646
+ def marshal_load(array)
647
+ initialize(array)
648
+ end
649
+
650
+ private
651
+
652
+ def subsequence(from, length)
653
+ return nil if from > @node.size || from < 0 || length < 0
654
+ length = @node.size - from if @node.size < from + length
655
+ return self.class.empty if length == 0
656
+ self.class.alloc(@node.slice(from, length), @comparator)
657
+ end
658
+
659
+ # @private
660
+ class AVLNode
661
+ def self.from_items(items, from, to) # items must be sorted
662
+ size = to - from + 1
663
+ if size >= 3
664
+ middle = (to + from) / 2
665
+ AVLNode.new(items[middle], AVLNode.from_items(items, from, middle-1), AVLNode.from_items(items, middle+1, to))
666
+ elsif size == 2
667
+ AVLNode.new(items[from], EmptyAVLNode, AVLNode.new(items[from+1], EmptyAVLNode, EmptyAVLNode))
668
+ elsif size == 1
669
+ AVLNode.new(items[from], EmptyAVLNode, EmptyAVLNode)
670
+ elsif size == 0
671
+ EmptyAVLNode
672
+ end
673
+ end
674
+
675
+ def initialize(item, left, right)
676
+ @item, @left, @right = item, left, right
677
+ @height = ((@right.height > @left.height) ? @right.height : @left.height) + 1
678
+ @size = @right.size + @left.size + 1
679
+ end
680
+ attr_reader :item, :left, :right, :height, :size
681
+
682
+ def empty?
683
+ false
684
+ end
685
+
686
+ def insert(item, comparator)
687
+ dir = direction(item, comparator)
688
+ if dir == 0
689
+ self
690
+ elsif dir > 0
691
+ rebalance_right(@left, @right.insert(item, comparator))
692
+ else
693
+ rebalance_left(@left.insert(item, comparator), @right)
694
+ end
695
+ end
696
+
697
+ def bulk_insert(items, comparator)
698
+ return self if items.empty?
699
+ return insert(items.first, comparator) if items.size == 1
700
+
701
+ left, right = partition(items, comparator)
702
+
703
+ if right.size > left.size
704
+ rebalance_right(@left.bulk_insert(left, comparator), @right.bulk_insert(right, comparator))
705
+ else
706
+ rebalance_left(@left.bulk_insert(left, comparator), @right.bulk_insert(right, comparator))
707
+ end
708
+ end
709
+
710
+ def delete(item, comparator)
711
+ dir = direction(item, comparator)
712
+ if dir == 0
713
+ if @right.empty?
714
+ return @left # replace this node with its only child
715
+ elsif @left.empty?
716
+ return @right # likewise
717
+ end
718
+
719
+ if balance > 0
720
+ # tree is leaning to the left. replace with highest node on that side
721
+ replace_with = @left.max
722
+ AVLNode.new(replace_with, @left.delete(replace_with, comparator), @right)
723
+ else
724
+ # tree is leaning to the right. replace with lowest node on that side
725
+ replace_with = @right.min
726
+ AVLNode.new(replace_with, @left, @right.delete(replace_with, comparator))
727
+ end
728
+ elsif dir > 0
729
+ rebalance_left(@left, @right.delete(item, comparator))
730
+ else
731
+ rebalance_right(@left.delete(item, comparator), @right)
732
+ end
733
+ end
734
+
735
+ def bulk_delete(items, comparator)
736
+ return self if items.empty?
737
+ return delete(items.first, comparator) if items.size == 1
738
+
739
+ left, right, keep_item = [], [], true
740
+ items.each do |item|
741
+ dir = direction(item, comparator)
742
+ if dir > 0
743
+ right << item
744
+ elsif dir < 0
745
+ left << item
746
+ else
747
+ keep_item = false
748
+ end
749
+ end
750
+
751
+ left = @left.bulk_delete(left, comparator)
752
+ right = @right.bulk_delete(right, comparator)
753
+ finish_removal(keep_item, left, right, comparator)
754
+ end
755
+
756
+ def keep_only(items, comparator)
757
+ return EmptyAVLNode if items.empty?
758
+
759
+ left, right, keep_item = [], [], false
760
+ items.each do |item|
761
+ dir = direction(item, comparator)
762
+ if dir > 0
763
+ right << item
764
+ elsif dir < 0
765
+ left << item
766
+ else
767
+ keep_item = true
768
+ end
769
+ end
770
+
771
+ left = @left.keep_only(left, comparator)
772
+ right = @right.keep_only(right, comparator)
773
+ finish_removal(keep_item, left, right, comparator)
774
+ end
775
+
776
+ def finish_removal(keep_item, left, right, comparator)
777
+ # deletion of items may have occurred on left and right sides
778
+ # now we may also need to delete the current item
779
+ if keep_item
780
+ rebalance(left, right) # no need to delete the current item
781
+ elsif left.empty?
782
+ right
783
+ elsif right.empty?
784
+ left
785
+ elsif left.height > right.height
786
+ replace_with = left.max
787
+ AVLNode.new(replace_with, left.delete(replace_with, comparator), right)
788
+ else
789
+ replace_with = right.min
790
+ AVLNode.new(replace_with, left, right.delete(replace_with, comparator))
791
+ end
792
+ end
793
+
794
+ def prefix(item, comparator, inclusive)
795
+ dir = direction(item, comparator)
796
+ if dir > 0 || (inclusive && dir == 0)
797
+ rebalance_left(@left, @right.prefix(item, comparator, inclusive))
798
+ else
799
+ @left.prefix(item, comparator, inclusive)
800
+ end
801
+ end
802
+
803
+ def suffix(item, comparator, inclusive)
804
+ dir = direction(item, comparator)
805
+ if dir < 0 || (inclusive && dir == 0)
806
+ rebalance_right(@left.suffix(item, comparator, inclusive), @right)
807
+ else
808
+ @right.suffix(item, comparator, inclusive)
809
+ end
810
+ end
811
+
812
+ def between(from, to, comparator)
813
+ if direction(from, comparator) > 0 # all on the right
814
+ @right.between(from, to, comparator)
815
+ elsif direction(to, comparator) < 0 # all on the left
816
+ @left.between(from, to, comparator)
817
+ else
818
+ left = @left.suffix(from, comparator, true)
819
+ right = @right.prefix(to, comparator, true)
820
+ rebalance(left, right)
821
+ end
822
+ end
823
+
824
+ def each_less(item, comparator, inclusive, &block)
825
+ dir = direction(item, comparator)
826
+ if dir > 0 || (inclusive && dir == 0)
827
+ @left.each(&block)
828
+ yield @item
829
+ @right.each_less(item, comparator, inclusive, &block)
830
+ else
831
+ @left.each_less(item, comparator, inclusive, &block)
832
+ end
833
+ end
834
+
835
+ def each_greater(item, comparator, inclusive, &block)
836
+ dir = direction(item, comparator)
837
+ if dir < 0 || (inclusive && dir == 0)
838
+ @left.each_greater(item, comparator, inclusive, &block)
839
+ yield @item
840
+ @right.each(&block)
841
+ else
842
+ @right.each_greater(item, comparator, inclusive, &block)
843
+ end
844
+ end
845
+
846
+ def each_between(from, to, comparator, &block)
847
+ if direction(from, comparator) > 0 # all on the right
848
+ @right.each_between(from, to, comparator, &block)
849
+ elsif direction(to, comparator) < 0 # all on the left
850
+ @left.each_between(from, to, comparator, &block)
851
+ else
852
+ @left.each_greater(from, comparator, true, &block)
853
+ yield @item
854
+ @right.each_less(to, comparator, true, &block)
855
+ end
856
+ end
857
+
858
+ def each(&block)
859
+ @left.each(&block)
860
+ yield @item
861
+ @right.each(&block)
862
+ end
863
+
864
+ def reverse_each(&block)
865
+ @right.reverse_each(&block)
866
+ yield @item
867
+ @left.reverse_each(&block)
868
+ end
869
+
870
+ def include?(item, comparator)
871
+ dir = direction(item, comparator)
872
+ if dir == 0
873
+ true
874
+ elsif dir > 0
875
+ @right.include?(item, comparator)
876
+ else
877
+ @left.include?(item, comparator)
878
+ end
879
+ end
880
+
881
+ def at(index)
882
+ if index < @left.size
883
+ @left.at(index)
884
+ elsif index > @left.size
885
+ @right.at(index - @left.size - 1)
886
+ else
887
+ @item
888
+ end
889
+ end
890
+
891
+ def max
892
+ @right.empty? ? @item : @right.max
893
+ end
894
+
895
+ def min
896
+ @left.empty? ? @item : @left.min
897
+ end
898
+
899
+ def balance
900
+ @left.height - @right.height
901
+ end
902
+
903
+ def slice(from, length)
904
+ if length <= 0
905
+ EmptyAVLNode
906
+ elsif from + length <= @left.size
907
+ @left.slice(from, length)
908
+ elsif from > @left.size
909
+ @right.slice(from - @left.size - 1, length)
910
+ else
911
+ left = @left.slice(from, @left.size - from)
912
+ right = @right.slice(0, from + length - @left.size - 1)
913
+ rebalance(left, right)
914
+ end
915
+ end
916
+
917
+ def partition(items, comparator)
918
+ left, right = [], []
919
+ items.each do |item|
920
+ dir = direction(item, comparator)
921
+ if dir > 0
922
+ right << item
923
+ elsif dir < 0
924
+ left << item
925
+ end
926
+ end
927
+ [left, right]
928
+ end
929
+
930
+ def rebalance(left, right)
931
+ if left.height > right.height
932
+ rebalance_left(left, right)
933
+ else
934
+ rebalance_right(left, right)
935
+ end
936
+ end
937
+
938
+ def rebalance_left(left, right)
939
+ # the tree might be unbalanced to the left (paths on the left too long)
940
+ balance = left.height - right.height
941
+ if balance >= 2
942
+ if left.balance > 0
943
+ # single right rotation
944
+ AVLNode.new(left.item, left.left, AVLNode.new(@item, left.right, right))
945
+ else
946
+ # left rotation, then right
947
+ AVLNode.new(left.right.item, AVLNode.new(left.item, left.left, left.right.left), AVLNode.new(@item, left.right.right, right))
948
+ end
949
+ else
950
+ AVLNode.new(@item, left, right)
951
+ end
952
+ end
953
+
954
+ def rebalance_right(left, right)
955
+ # the tree might be unbalanced to the right (paths on the right too long)
956
+ balance = left.height - right.height
957
+ if balance <= -2
958
+ if right.balance > 0
959
+ # right rotation, then left
960
+ AVLNode.new(right.left.item, AVLNode.new(@item, left, right.left.left), AVLNode.new(right.item, right.left.right, right.right))
961
+ else
962
+ # single left rotation
963
+ AVLNode.new(right.item, AVLNode.new(@item, left, right.left), right.right)
964
+ end
965
+ else
966
+ AVLNode.new(@item, left, right)
967
+ end
968
+ end
969
+
970
+ def direction(item, comparator)
971
+ if comparator
972
+ comparator.call(item, @item)
973
+ else
974
+ item <=> @item
975
+ end
976
+ end
977
+ end
978
+
979
+ EmptyAVLNode = Object.new.tap do |e|
980
+ def e.left; self; end
981
+ def e.right; self; end
982
+ def e.height; 0; end
983
+ def e.size; 0; end
984
+ def e.min; nil; end
985
+ def e.max; nil; end
986
+ def e.each; end
987
+ def e.reverse_each; end
988
+ def e.at(index); nil; end
989
+ def e.insert(item, comparator); AVLNode.new(item, self, self); end
990
+ def e.bulk_insert(items, comparator)
991
+ items = items.to_a if !items.is_a?(Array)
992
+ AVLNode.from_items(items.sort(&comparator), 0, items.size-1)
993
+ end
994
+ def e.bulk_delete(items, comparator); self; end
995
+ def e.keep_only(items, comparator); self; end
996
+ def e.delete(item, comparator); self; end
997
+ def e.include?(item, comparator); false; end
998
+ def e.prefix(item, comparator, inclusive); self; end
999
+ def e.suffix(item, comparator, inclusive); self; end
1000
+ def e.between(from, to, comparator); self; end
1001
+ def e.each_greater(item, comparator, inclusive); end
1002
+ def e.each_less(item, comparator, inclusive); end
1003
+ def e.each_between(item, comparator, inclusive); end
1004
+ def e.empty?; true; end
1005
+ def e.slice(from, length); self; end
1006
+ end.freeze
1007
+ end
1008
+
1009
+ # The canonical empty `SortedSet`. Returned by `Hamster.sorted_set` and `SortedSet[]`
1010
+ # when invoked with no arguments; also returned by `SortedSet.empty`. Prefer using
1011
+ # this one rather than creating many empty sorted sets using `SortedSet.new`.
1012
+ #
1013
+ EmptySortedSet = Hamster::SortedSet.empty
1014
+ end