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

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