hamster 0.4.3 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (757) hide show
  1. checksums.yaml +7 -0
  2. data/lib/hamster.rb +11 -9
  3. data/lib/hamster/core_ext.rb +2 -3
  4. data/lib/hamster/core_ext/enumerable.rb +18 -27
  5. data/lib/hamster/core_ext/io.rb +16 -25
  6. data/lib/hamster/deque.rb +252 -0
  7. data/lib/hamster/enumerable.rb +123 -112
  8. data/lib/hamster/experimental/mutable_queue.rb +5 -14
  9. data/lib/hamster/experimental/mutable_set.rb +7 -14
  10. data/lib/hamster/hash.rb +732 -102
  11. data/lib/hamster/immutable.rb +4 -10
  12. data/lib/hamster/list.rb +1155 -215
  13. data/lib/hamster/{experimental/mutable_hash.rb → mutable_hash.rb} +11 -14
  14. data/lib/hamster/nested.rb +36 -0
  15. data/lib/hamster/{experimental/read_copy_update.rb → read_copy_update.rb} +10 -8
  16. data/lib/hamster/set.rb +488 -90
  17. data/lib/hamster/sorted_set.rb +1397 -0
  18. data/lib/hamster/trie.rb +210 -65
  19. data/lib/hamster/undefined.rb +1 -7
  20. data/lib/hamster/vector.rb +1329 -83
  21. data/lib/hamster/version.rb +1 -3
  22. data/spec/{hamster/core_ext → fixtures}/io_spec.txt +0 -0
  23. data/spec/lib/hamster/core_ext/array_spec.rb +14 -0
  24. data/spec/lib/hamster/core_ext/enumerable_spec.rb +30 -0
  25. data/spec/lib/hamster/core_ext/io_spec.rb +29 -0
  26. data/spec/lib/hamster/deque/clear_spec.rb +34 -0
  27. data/spec/lib/hamster/deque/construction_spec.rb +30 -0
  28. data/spec/lib/hamster/deque/copying_spec.rb +20 -0
  29. data/spec/lib/hamster/deque/dequeue_spec.rb +35 -0
  30. data/spec/lib/hamster/deque/empty_spec.rb +40 -0
  31. data/spec/lib/hamster/deque/enqueue_spec.rb +28 -0
  32. data/spec/lib/hamster/deque/first_spec.rb +18 -0
  33. data/spec/lib/hamster/deque/inspect_spec.rb +24 -0
  34. data/spec/lib/hamster/deque/last_spec.rb +18 -0
  35. data/spec/lib/hamster/deque/marshal_spec.rb +34 -0
  36. data/spec/lib/hamster/deque/new_spec.rb +44 -0
  37. data/spec/lib/hamster/deque/pop_spec.rb +33 -0
  38. data/spec/lib/hamster/deque/pretty_print_spec.rb +24 -0
  39. data/spec/lib/hamster/deque/random_modification_spec.rb +34 -0
  40. data/spec/lib/hamster/deque/size_spec.rb +20 -0
  41. data/spec/lib/hamster/deque/to_a_spec.rb +27 -0
  42. data/spec/lib/hamster/deque/to_ary_spec.rb +36 -0
  43. data/spec/lib/hamster/deque/to_list_spec.rb +26 -0
  44. data/spec/lib/hamster/deque/unshift_spec.rb +26 -0
  45. data/spec/lib/hamster/experimental/mutable_set/add_qm_spec.rb +39 -0
  46. data/spec/lib/hamster/experimental/mutable_set/add_spec.rb +37 -0
  47. data/spec/lib/hamster/experimental/mutable_set/delete_qm_spec.rb +38 -0
  48. data/spec/lib/hamster/experimental/mutable_set/delete_spec.rb +37 -0
  49. data/spec/lib/hamster/hash/all_spec.rb +54 -0
  50. data/spec/lib/hamster/hash/any_spec.rb +54 -0
  51. data/spec/lib/hamster/hash/assoc_spec.rb +52 -0
  52. data/spec/lib/hamster/hash/clear_spec.rb +43 -0
  53. data/spec/lib/hamster/hash/construction_spec.rb +39 -0
  54. data/spec/lib/hamster/hash/copying_spec.rb +14 -0
  55. data/spec/lib/hamster/hash/default_proc_spec.rb +73 -0
  56. data/spec/lib/hamster/hash/delete_spec.rb +40 -0
  57. data/spec/lib/hamster/hash/each_spec.rb +78 -0
  58. data/spec/lib/hamster/hash/each_with_index_spec.rb +30 -0
  59. data/spec/lib/hamster/hash/empty_spec.rb +44 -0
  60. data/spec/lib/hamster/hash/eql_spec.rb +70 -0
  61. data/spec/lib/hamster/hash/except_spec.rb +43 -0
  62. data/spec/lib/hamster/hash/fetch_spec.rb +58 -0
  63. data/spec/lib/hamster/hash/find_spec.rb +44 -0
  64. data/spec/lib/hamster/hash/flat_map_spec.rb +36 -0
  65. data/spec/lib/hamster/hash/flatten_spec.rb +99 -0
  66. data/spec/lib/hamster/hash/get_spec.rb +80 -0
  67. data/spec/lib/hamster/hash/has_key_spec.rb +32 -0
  68. data/spec/lib/hamster/hash/has_value_spec.rb +28 -0
  69. data/spec/lib/hamster/hash/hash_spec.rb +30 -0
  70. data/spec/{hamster → lib/hamster}/hash/immutable_spec.rb +3 -6
  71. data/spec/lib/hamster/hash/inspect_spec.rb +31 -0
  72. data/spec/lib/hamster/hash/invert_spec.rb +31 -0
  73. data/spec/lib/hamster/hash/key_spec.rb +28 -0
  74. data/spec/lib/hamster/hash/keys_spec.rb +17 -0
  75. data/spec/lib/hamster/hash/map_spec.rb +46 -0
  76. data/spec/lib/hamster/hash/marshal_spec.rb +29 -0
  77. data/spec/lib/hamster/hash/merge_spec.rb +83 -0
  78. data/spec/lib/hamster/hash/min_max_spec.rb +46 -0
  79. data/spec/lib/hamster/hash/new_spec.rb +71 -0
  80. data/spec/lib/hamster/hash/none_spec.rb +49 -0
  81. data/spec/lib/hamster/hash/partition_spec.rb +36 -0
  82. data/spec/lib/hamster/hash/pretty_print_spec.rb +35 -0
  83. data/spec/lib/hamster/hash/put_spec.rb +103 -0
  84. data/spec/lib/hamster/hash/reduce_spec.rb +36 -0
  85. data/spec/lib/hamster/hash/reject_spec.rb +62 -0
  86. data/spec/lib/hamster/hash/reverse_each_spec.rb +28 -0
  87. data/spec/lib/hamster/hash/sample_spec.rb +14 -0
  88. data/spec/lib/hamster/hash/select_spec.rb +58 -0
  89. data/spec/{hamster → lib/hamster}/hash/size_spec.rb +9 -18
  90. data/spec/lib/hamster/hash/slice_spec.rb +45 -0
  91. data/spec/lib/hamster/hash/sort_spec.rb +27 -0
  92. data/spec/lib/hamster/hash/store_spec.rb +76 -0
  93. data/spec/lib/hamster/hash/take_spec.rb +36 -0
  94. data/spec/lib/hamster/hash/to_a_spec.rb +14 -0
  95. data/spec/lib/hamster/hash/to_hash_spec.rb +22 -0
  96. data/spec/lib/hamster/hash/update_in_spec.rb +80 -0
  97. data/spec/lib/hamster/hash/values_at_spec.rb +14 -0
  98. data/spec/lib/hamster/hash/values_spec.rb +25 -0
  99. data/spec/{hamster → lib/hamster}/immutable/copying_spec.rb +3 -10
  100. data/spec/{hamster → lib/hamster}/immutable/immutable_spec.rb +3 -16
  101. data/spec/lib/hamster/immutable/memoize_spec.rb +56 -0
  102. data/spec/lib/hamster/immutable/new_spec.rb +14 -0
  103. data/spec/lib/hamster/immutable/transform_spec.rb +26 -0
  104. data/spec/lib/hamster/immutable/transform_unless_spec.rb +44 -0
  105. data/spec/lib/hamster/list/add_spec.rb +26 -0
  106. data/spec/lib/hamster/list/all_spec.rb +58 -0
  107. data/spec/lib/hamster/list/any_spec.rb +50 -0
  108. data/spec/lib/hamster/list/append_spec.rb +39 -0
  109. data/spec/lib/hamster/list/at_spec.rb +30 -0
  110. data/spec/lib/hamster/list/break_spec.rb +70 -0
  111. data/spec/lib/hamster/list/cadr_spec.rb +39 -0
  112. data/spec/lib/hamster/list/chunk_spec.rb +29 -0
  113. data/spec/lib/hamster/list/clear_spec.rb +25 -0
  114. data/spec/lib/hamster/list/combination_spec.rb +34 -0
  115. data/spec/lib/hamster/list/compact_spec.rb +35 -0
  116. data/spec/lib/hamster/list/compare_spec.rb +31 -0
  117. data/spec/lib/hamster/list/cons_spec.rb +26 -0
  118. data/spec/lib/hamster/list/construction_spec.rb +111 -0
  119. data/spec/lib/hamster/list/copying_spec.rb +20 -0
  120. data/spec/lib/hamster/list/count_spec.rb +37 -0
  121. data/spec/lib/hamster/list/cycle_spec.rb +29 -0
  122. data/spec/lib/hamster/list/delete_at_spec.rb +19 -0
  123. data/spec/lib/hamster/list/delete_spec.rb +17 -0
  124. data/spec/lib/hamster/list/drop_spec.rb +31 -0
  125. data/spec/lib/hamster/list/drop_while_spec.rb +39 -0
  126. data/spec/lib/hamster/list/each_slice_spec.rb +52 -0
  127. data/spec/lib/hamster/list/each_spec.rb +41 -0
  128. data/spec/lib/hamster/list/each_with_index_spec.rb +29 -0
  129. data/spec/lib/hamster/list/empty_spec.rb +24 -0
  130. data/spec/lib/hamster/list/eql_spec.rb +62 -0
  131. data/spec/lib/hamster/list/fill_spec.rb +50 -0
  132. data/spec/lib/hamster/list/find_all_spec.rb +71 -0
  133. data/spec/{hamster → lib/hamster}/list/find_index_spec.rb +7 -29
  134. data/spec/{hamster → lib/hamster}/list/find_spec.rb +13 -35
  135. data/spec/lib/hamster/list/flat_map_spec.rb +52 -0
  136. data/spec/lib/hamster/list/flatten_spec.rb +31 -0
  137. data/spec/lib/hamster/list/grep_spec.rb +47 -0
  138. data/spec/lib/hamster/list/group_by_spec.rb +42 -0
  139. data/spec/lib/hamster/list/hash_spec.rb +22 -0
  140. data/spec/{hamster → lib/hamster}/list/head_spec.rb +6 -21
  141. data/spec/{hamster → lib/hamster}/list/include_spec.rb +8 -29
  142. data/spec/lib/hamster/list/index_spec.rb +34 -0
  143. data/spec/lib/hamster/list/indices_spec.rb +62 -0
  144. data/spec/lib/hamster/list/init_spec.rb +29 -0
  145. data/spec/lib/hamster/list/inits_spec.rb +29 -0
  146. data/spec/lib/hamster/list/insert_spec.rb +47 -0
  147. data/spec/lib/hamster/list/inspect_spec.rb +30 -0
  148. data/spec/lib/hamster/list/intersperse_spec.rb +29 -0
  149. data/spec/lib/hamster/list/join_spec.rb +64 -0
  150. data/spec/lib/hamster/list/last_spec.rb +24 -0
  151. data/spec/lib/hamster/list/ltlt_spec.rb +20 -0
  152. data/spec/lib/hamster/list/map_spec.rb +46 -0
  153. data/spec/lib/hamster/list/maximum_spec.rb +40 -0
  154. data/spec/{hamster → lib/hamster}/list/merge_by_spec.rb +9 -36
  155. data/spec/{hamster → lib/hamster}/list/merge_spec.rb +5 -24
  156. data/spec/lib/hamster/list/minimum_spec.rb +40 -0
  157. data/spec/lib/hamster/list/multithreading_spec.rb +48 -0
  158. data/spec/{hamster → lib/hamster}/list/none_spec.rb +14 -41
  159. data/spec/{hamster → lib/hamster}/list/one_spec.rb +15 -40
  160. data/spec/lib/hamster/list/partition_spec.rb +116 -0
  161. data/spec/lib/hamster/list/permutation_spec.rb +56 -0
  162. data/spec/lib/hamster/list/pop_spec.rb +26 -0
  163. data/spec/lib/hamster/list/product_spec.rb +24 -0
  164. data/spec/lib/hamster/list/reduce_spec.rb +54 -0
  165. data/spec/lib/hamster/list/reject_spec.rb +46 -0
  166. data/spec/lib/hamster/list/reverse_spec.rb +35 -0
  167. data/spec/lib/hamster/list/rotate_spec.rb +37 -0
  168. data/spec/lib/hamster/list/sample_spec.rb +14 -0
  169. data/spec/lib/hamster/list/select_spec.rb +71 -0
  170. data/spec/lib/hamster/list/size_spec.rb +26 -0
  171. data/spec/lib/hamster/list/slice_spec.rb +230 -0
  172. data/spec/lib/hamster/list/sorting_spec.rb +47 -0
  173. data/spec/lib/hamster/list/span_spec.rb +77 -0
  174. data/spec/lib/hamster/list/split_at_spec.rb +44 -0
  175. data/spec/lib/hamster/list/subsequences_spec.rb +24 -0
  176. data/spec/lib/hamster/list/sum_spec.rb +24 -0
  177. data/spec/lib/hamster/list/tail_spec.rb +31 -0
  178. data/spec/lib/hamster/list/tails_spec.rb +29 -0
  179. data/spec/lib/hamster/list/take_spec.rb +31 -0
  180. data/spec/lib/hamster/list/take_while_spec.rb +47 -0
  181. data/spec/lib/hamster/list/to_a_spec.rb +40 -0
  182. data/spec/lib/hamster/list/to_ary_spec.rb +42 -0
  183. data/spec/lib/hamster/list/to_list_spec.rb +20 -0
  184. data/spec/lib/hamster/list/to_set_spec.rb +19 -0
  185. data/spec/lib/hamster/list/transpose_spec.rb +20 -0
  186. data/spec/lib/hamster/list/union_spec.rb +32 -0
  187. data/spec/lib/hamster/list/uniq_spec.rb +30 -0
  188. data/spec/lib/hamster/list/zip_spec.rb +24 -0
  189. data/spec/lib/hamster/nested/construction_spec.rb +44 -0
  190. data/spec/lib/hamster/set/add_spec.rb +76 -0
  191. data/spec/lib/hamster/set/all_spec.rb +52 -0
  192. data/spec/lib/hamster/set/any_spec.rb +52 -0
  193. data/spec/lib/hamster/set/clear_spec.rb +34 -0
  194. data/spec/{hamster → lib/hamster}/set/compact_spec.rb +9 -20
  195. data/spec/lib/hamster/set/construction_spec.rb +19 -0
  196. data/spec/lib/hamster/set/copying_spec.rb +14 -0
  197. data/spec/lib/hamster/set/count_spec.rb +37 -0
  198. data/spec/lib/hamster/set/delete_spec.rb +72 -0
  199. data/spec/lib/hamster/set/difference_spec.rb +50 -0
  200. data/spec/lib/hamster/set/disjoint_spec.rb +26 -0
  201. data/spec/lib/hamster/set/each_spec.rb +46 -0
  202. data/spec/lib/hamster/set/empty_spec.rb +45 -0
  203. data/spec/lib/hamster/set/eqeq_spec.rb +104 -0
  204. data/spec/lib/hamster/set/eql_spec.rb +110 -0
  205. data/spec/lib/hamster/set/exclusion_spec.rb +48 -0
  206. data/spec/{hamster → lib/hamster}/set/find_spec.rb +10 -27
  207. data/spec/lib/hamster/set/first_spec.rb +29 -0
  208. data/spec/lib/hamster/set/flatten_spec.rb +47 -0
  209. data/spec/lib/hamster/set/grep_spec.rb +58 -0
  210. data/spec/lib/hamster/set/group_by_spec.rb +60 -0
  211. data/spec/lib/hamster/set/hash_spec.rb +23 -0
  212. data/spec/{hamster → lib/hamster}/set/immutable_spec.rb +4 -7
  213. data/spec/lib/hamster/set/include_spec.rb +61 -0
  214. data/spec/lib/hamster/set/inspect_spec.rb +48 -0
  215. data/spec/lib/hamster/set/intersect_spec.rb +26 -0
  216. data/spec/lib/hamster/set/intersection_spec.rb +53 -0
  217. data/spec/lib/hamster/set/join_spec.rb +65 -0
  218. data/spec/lib/hamster/set/map_spec.rb +60 -0
  219. data/spec/lib/hamster/set/marshal_spec.rb +29 -0
  220. data/spec/lib/hamster/set/maximum_spec.rb +37 -0
  221. data/spec/lib/hamster/set/minimum_spec.rb +37 -0
  222. data/spec/lib/hamster/set/new_spec.rb +54 -0
  223. data/spec/{hamster → lib/hamster}/set/none_spec.rb +17 -32
  224. data/spec/{hamster → lib/hamster}/set/one_spec.rb +16 -31
  225. data/spec/lib/hamster/set/partition_spec.rb +53 -0
  226. data/spec/lib/hamster/set/product_spec.rb +24 -0
  227. data/spec/lib/hamster/set/reduce_spec.rb +56 -0
  228. data/spec/lib/hamster/set/reject_spec.rb +51 -0
  229. data/spec/lib/hamster/set/reverse_each_spec.rb +39 -0
  230. data/spec/lib/hamster/set/sample_spec.rb +14 -0
  231. data/spec/lib/hamster/set/select_spec.rb +74 -0
  232. data/spec/{hamster → lib/hamster}/set/size_spec.rb +4 -13
  233. data/spec/lib/hamster/set/sorting_spec.rb +49 -0
  234. data/spec/lib/hamster/set/subset_spec.rb +52 -0
  235. data/spec/lib/hamster/set/sum_spec.rb +24 -0
  236. data/spec/lib/hamster/set/superset_spec.rb +52 -0
  237. data/spec/lib/hamster/set/to_a_spec.rb +31 -0
  238. data/spec/lib/hamster/set/to_list_spec.rb +37 -0
  239. data/spec/lib/hamster/set/to_set_spec.rb +20 -0
  240. data/spec/lib/hamster/set/union_spec.rb +64 -0
  241. data/spec/lib/hamster/sorted_set/above_spec.rb +52 -0
  242. data/spec/lib/hamster/sorted_set/add_spec.rb +63 -0
  243. data/spec/lib/hamster/sorted_set/at_spec.rb +25 -0
  244. data/spec/lib/hamster/sorted_set/below_spec.rb +52 -0
  245. data/spec/lib/hamster/sorted_set/between_spec.rb +52 -0
  246. data/spec/lib/hamster/sorted_set/clear_spec.rb +44 -0
  247. data/spec/lib/hamster/sorted_set/construction_spec.rb +29 -0
  248. data/spec/lib/hamster/sorted_set/delete_at_spec.rb +19 -0
  249. data/spec/lib/hamster/sorted_set/delete_spec.rb +90 -0
  250. data/spec/lib/hamster/sorted_set/difference_spec.rb +23 -0
  251. data/spec/lib/hamster/sorted_set/disjoint_spec.rb +26 -0
  252. data/spec/lib/hamster/sorted_set/drop_spec.rb +56 -0
  253. data/spec/lib/hamster/sorted_set/drop_while_spec.rb +35 -0
  254. data/spec/lib/hamster/sorted_set/each_spec.rb +29 -0
  255. data/spec/lib/hamster/sorted_set/empty_spec.rb +35 -0
  256. data/spec/lib/hamster/sorted_set/eql_spec.rb +121 -0
  257. data/spec/lib/hamster/sorted_set/exclusion_spec.rb +23 -0
  258. data/spec/lib/hamster/sorted_set/fetch_spec.rb +65 -0
  259. data/spec/lib/hamster/sorted_set/find_index_spec.rb +41 -0
  260. data/spec/lib/hamster/sorted_set/first_spec.rb +19 -0
  261. data/spec/lib/hamster/sorted_set/from_spec.rb +52 -0
  262. data/spec/lib/hamster/sorted_set/group_by_spec.rb +58 -0
  263. data/spec/lib/hamster/sorted_set/include_spec.rb +24 -0
  264. data/spec/lib/hamster/sorted_set/inspect_spec.rb +38 -0
  265. data/spec/lib/hamster/sorted_set/intersect_spec.rb +26 -0
  266. data/spec/lib/hamster/sorted_set/intersection_spec.rb +29 -0
  267. data/spec/lib/hamster/sorted_set/last_spec.rb +37 -0
  268. data/spec/lib/hamster/sorted_set/map_spec.rb +36 -0
  269. data/spec/lib/hamster/sorted_set/marshal_spec.rb +37 -0
  270. data/spec/lib/hamster/sorted_set/maximum_spec.rb +37 -0
  271. data/spec/lib/hamster/sorted_set/minimum_spec.rb +20 -0
  272. data/spec/lib/hamster/sorted_set/new_spec.rb +52 -0
  273. data/spec/lib/hamster/sorted_set/reverse_each_spec.rb +29 -0
  274. data/spec/lib/hamster/sorted_set/sample_spec.rb +14 -0
  275. data/spec/lib/hamster/sorted_set/select_spec.rb +62 -0
  276. data/spec/{hamster/vector → lib/hamster/sorted_set}/size_spec.rb +6 -15
  277. data/spec/lib/hamster/sorted_set/slice_spec.rb +257 -0
  278. data/spec/lib/hamster/sorted_set/sorting_spec.rb +45 -0
  279. data/spec/lib/hamster/sorted_set/subset_spec.rb +48 -0
  280. data/spec/lib/hamster/sorted_set/superset_spec.rb +48 -0
  281. data/spec/lib/hamster/sorted_set/take_spec.rb +55 -0
  282. data/spec/lib/hamster/sorted_set/take_while_spec.rb +34 -0
  283. data/spec/lib/hamster/sorted_set/to_set_spec.rb +19 -0
  284. data/spec/lib/hamster/sorted_set/union_spec.rb +28 -0
  285. data/spec/lib/hamster/sorted_set/up_to_spec.rb +52 -0
  286. data/spec/lib/hamster/sorted_set/values_at_spec.rb +34 -0
  287. data/spec/lib/hamster/vector/add_spec.rb +68 -0
  288. data/spec/lib/hamster/vector/any_spec.rb +70 -0
  289. data/spec/lib/hamster/vector/assoc_spec.rb +36 -0
  290. data/spec/lib/hamster/vector/bsearch_spec.rb +58 -0
  291. data/spec/lib/hamster/vector/clear_spec.rb +34 -0
  292. data/spec/lib/hamster/vector/combination_spec.rb +82 -0
  293. data/spec/lib/hamster/vector/compact_spec.rb +30 -0
  294. data/spec/lib/hamster/vector/compare_spec.rb +32 -0
  295. data/spec/lib/hamster/vector/concat_spec.rb +35 -0
  296. data/spec/lib/hamster/vector/copying_spec.rb +21 -0
  297. data/spec/lib/hamster/vector/count_spec.rb +18 -0
  298. data/spec/lib/hamster/vector/delete_at_spec.rb +54 -0
  299. data/spec/lib/hamster/vector/delete_spec.rb +31 -0
  300. data/spec/lib/hamster/vector/drop_spec.rb +42 -0
  301. data/spec/lib/hamster/vector/drop_while_spec.rb +55 -0
  302. data/spec/lib/hamster/vector/each_index_spec.rb +41 -0
  303. data/spec/lib/hamster/vector/each_spec.rb +45 -0
  304. data/spec/lib/hamster/vector/each_with_index_spec.rb +40 -0
  305. data/spec/lib/hamster/vector/empty_spec.rb +42 -0
  306. data/spec/lib/hamster/vector/eql_spec.rb +77 -0
  307. data/spec/lib/hamster/vector/fetch_spec.rb +65 -0
  308. data/spec/lib/hamster/vector/fill_spec.rb +89 -0
  309. data/spec/lib/hamster/vector/first_spec.rb +19 -0
  310. data/spec/lib/hamster/vector/flat_map_spec.rb +51 -0
  311. data/spec/lib/hamster/vector/flatten_spec.rb +44 -0
  312. data/spec/lib/hamster/vector/get_spec.rb +75 -0
  313. data/spec/lib/hamster/vector/group_by_spec.rb +58 -0
  314. data/spec/{hamster → lib/hamster}/vector/include_spec.rb +6 -20
  315. data/spec/lib/hamster/vector/insert_spec.rb +69 -0
  316. data/spec/lib/hamster/vector/inspect_spec.rb +50 -0
  317. data/spec/{hamster/set → lib/hamster/vector}/join_spec.rb +24 -34
  318. data/spec/lib/hamster/vector/last_spec.rb +46 -0
  319. data/spec/lib/hamster/vector/length_spec.rb +46 -0
  320. data/spec/lib/hamster/vector/ltlt_spec.rb +66 -0
  321. data/spec/lib/hamster/vector/map_spec.rb +52 -0
  322. data/spec/lib/hamster/vector/marshal_spec.rb +32 -0
  323. data/spec/lib/hamster/vector/maximum_spec.rb +34 -0
  324. data/spec/lib/hamster/vector/minimum_spec.rb +34 -0
  325. data/spec/lib/hamster/vector/multiply_spec.rb +48 -0
  326. data/spec/lib/hamster/vector/new_spec.rb +51 -0
  327. data/spec/lib/hamster/vector/partition_spec.rb +53 -0
  328. data/spec/lib/hamster/vector/permutation_spec.rb +92 -0
  329. data/spec/lib/hamster/vector/pop_spec.rb +27 -0
  330. data/spec/lib/hamster/vector/product_spec.rb +71 -0
  331. data/spec/{hamster → lib/hamster}/vector/reduce_spec.rb +18 -49
  332. data/spec/lib/hamster/vector/reject_spec.rb +44 -0
  333. data/spec/lib/hamster/vector/repeated_combination_spec.rb +78 -0
  334. data/spec/lib/hamster/vector/repeated_permutation_spec.rb +94 -0
  335. data/spec/lib/hamster/vector/reverse_each_spec.rb +32 -0
  336. data/spec/lib/hamster/vector/reverse_spec.rb +22 -0
  337. data/spec/lib/hamster/vector/rindex_spec.rb +37 -0
  338. data/spec/lib/hamster/vector/rotate_spec.rb +74 -0
  339. data/spec/lib/hamster/vector/sample_spec.rb +14 -0
  340. data/spec/lib/hamster/vector/select_spec.rb +64 -0
  341. data/spec/lib/hamster/vector/set_spec.rb +175 -0
  342. data/spec/lib/hamster/vector/shift_spec.rb +28 -0
  343. data/spec/lib/hamster/vector/shuffle_spec.rb +44 -0
  344. data/spec/lib/hamster/vector/slice_spec.rb +241 -0
  345. data/spec/lib/hamster/vector/sorting_spec.rb +57 -0
  346. data/spec/{hamster/set → lib/hamster/vector}/sum_spec.rb +5 -19
  347. data/spec/lib/hamster/vector/take_spec.rb +43 -0
  348. data/spec/lib/hamster/vector/take_while_spec.rb +35 -0
  349. data/spec/lib/hamster/vector/to_a_spec.rb +42 -0
  350. data/spec/lib/hamster/vector/to_ary_spec.rb +35 -0
  351. data/spec/lib/hamster/vector/to_list_spec.rb +32 -0
  352. data/spec/lib/hamster/vector/to_set_spec.rb +23 -0
  353. data/spec/lib/hamster/vector/transpose_spec.rb +49 -0
  354. data/spec/lib/hamster/vector/uniq_spec.rb +56 -0
  355. data/spec/lib/hamster/vector/unshift_spec.rb +29 -0
  356. data/spec/lib/hamster/vector/update_in_spec.rb +83 -0
  357. data/spec/lib/hamster/vector/values_at_spec.rb +34 -0
  358. data/spec/lib/hamster/vector/zip_spec.rb +58 -0
  359. data/spec/spec_helper.rb +45 -13
  360. metadata +807 -458
  361. data/History.rdoc +0 -419
  362. data/LICENSE +0 -20
  363. data/README.rdoc +0 -236
  364. data/Rakefile +0 -5
  365. data/lib/hamster/core_ext/enumerator.rb +0 -30
  366. data/lib/hamster/experimental/mutable_stack.rb +0 -35
  367. data/lib/hamster/queue.rb +0 -93
  368. data/lib/hamster/sorter.rb +0 -32
  369. data/lib/hamster/stack.rb +0 -82
  370. data/lib/hamster/tuple.rb +0 -45
  371. data/spec/hamster/core_ext/array_spec.rb +0 -20
  372. data/spec/hamster/core_ext/coverage/assets/0.4.4/app.js +0 -66
  373. data/spec/hamster/core_ext/coverage/assets/0.4.4/fancybox/blank.gif +0 -0
  374. data/spec/hamster/core_ext/coverage/assets/0.4.4/fancybox/fancy_close.png +0 -0
  375. data/spec/hamster/core_ext/coverage/assets/0.4.4/fancybox/fancy_loading.png +0 -0
  376. data/spec/hamster/core_ext/coverage/assets/0.4.4/fancybox/fancy_nav_left.png +0 -0
  377. data/spec/hamster/core_ext/coverage/assets/0.4.4/fancybox/fancy_nav_right.png +0 -0
  378. data/spec/hamster/core_ext/coverage/assets/0.4.4/fancybox/fancy_shadow_e.png +0 -0
  379. data/spec/hamster/core_ext/coverage/assets/0.4.4/fancybox/fancy_shadow_n.png +0 -0
  380. data/spec/hamster/core_ext/coverage/assets/0.4.4/fancybox/fancy_shadow_ne.png +0 -0
  381. data/spec/hamster/core_ext/coverage/assets/0.4.4/fancybox/fancy_shadow_nw.png +0 -0
  382. data/spec/hamster/core_ext/coverage/assets/0.4.4/fancybox/fancy_shadow_s.png +0 -0
  383. data/spec/hamster/core_ext/coverage/assets/0.4.4/fancybox/fancy_shadow_se.png +0 -0
  384. data/spec/hamster/core_ext/coverage/assets/0.4.4/fancybox/fancy_shadow_sw.png +0 -0
  385. data/spec/hamster/core_ext/coverage/assets/0.4.4/fancybox/fancy_shadow_w.png +0 -0
  386. data/spec/hamster/core_ext/coverage/assets/0.4.4/fancybox/fancy_title_left.png +0 -0
  387. data/spec/hamster/core_ext/coverage/assets/0.4.4/fancybox/fancy_title_main.png +0 -0
  388. data/spec/hamster/core_ext/coverage/assets/0.4.4/fancybox/fancy_title_over.png +0 -0
  389. data/spec/hamster/core_ext/coverage/assets/0.4.4/fancybox/fancy_title_right.png +0 -0
  390. data/spec/hamster/core_ext/coverage/assets/0.4.4/fancybox/fancybox-x.png +0 -0
  391. data/spec/hamster/core_ext/coverage/assets/0.4.4/fancybox/fancybox-y.png +0 -0
  392. data/spec/hamster/core_ext/coverage/assets/0.4.4/fancybox/fancybox.png +0 -0
  393. data/spec/hamster/core_ext/coverage/assets/0.4.4/fancybox/jquery.fancybox-1.3.1.css +0 -363
  394. data/spec/hamster/core_ext/coverage/assets/0.4.4/fancybox/jquery.fancybox-1.3.1.pack.js +0 -44
  395. data/spec/hamster/core_ext/coverage/assets/0.4.4/favicon.png +0 -0
  396. data/spec/hamster/core_ext/coverage/assets/0.4.4/jquery-1.4.2.min.js +0 -155
  397. data/spec/hamster/core_ext/coverage/assets/0.4.4/jquery.dataTables.min.js +0 -152
  398. data/spec/hamster/core_ext/coverage/assets/0.4.4/jquery.timeago.js +0 -141
  399. data/spec/hamster/core_ext/coverage/assets/0.4.4/jquery.url.js +0 -174
  400. data/spec/hamster/core_ext/coverage/assets/0.4.4/loading.gif +0 -0
  401. data/spec/hamster/core_ext/coverage/assets/0.4.4/magnify.png +0 -0
  402. data/spec/hamster/core_ext/coverage/assets/0.4.4/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  403. data/spec/hamster/core_ext/coverage/assets/0.4.4/smoothness/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
  404. data/spec/hamster/core_ext/coverage/assets/0.4.4/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
  405. data/spec/hamster/core_ext/coverage/assets/0.4.4/smoothness/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  406. data/spec/hamster/core_ext/coverage/assets/0.4.4/smoothness/images/ui-bg_glass_75_dadada_1x400.png +0 -0
  407. data/spec/hamster/core_ext/coverage/assets/0.4.4/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  408. data/spec/hamster/core_ext/coverage/assets/0.4.4/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  409. data/spec/hamster/core_ext/coverage/assets/0.4.4/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  410. data/spec/hamster/core_ext/coverage/assets/0.4.4/smoothness/images/ui-icons_222222_256x240.png +0 -0
  411. data/spec/hamster/core_ext/coverage/assets/0.4.4/smoothness/images/ui-icons_2e83ff_256x240.png +0 -0
  412. data/spec/hamster/core_ext/coverage/assets/0.4.4/smoothness/images/ui-icons_454545_256x240.png +0 -0
  413. data/spec/hamster/core_ext/coverage/assets/0.4.4/smoothness/images/ui-icons_888888_256x240.png +0 -0
  414. data/spec/hamster/core_ext/coverage/assets/0.4.4/smoothness/images/ui-icons_cd0a0a_256x240.png +0 -0
  415. data/spec/hamster/core_ext/coverage/assets/0.4.4/smoothness/jquery-ui-1.8.4.custom.css +0 -295
  416. data/spec/hamster/core_ext/coverage/assets/0.4.4/stylesheet.css +0 -341
  417. data/spec/hamster/core_ext/coverage/covered_percent +0 -1
  418. data/spec/hamster/core_ext/coverage/index.html +0 -71
  419. data/spec/hamster/core_ext/coverage/resultset.yml +0 -10
  420. data/spec/hamster/core_ext/enumerable_spec.rb +0 -34
  421. data/spec/hamster/core_ext/enumerator_spec.rb +0 -25
  422. data/spec/hamster/core_ext/io_spec.rb +0 -29
  423. data/spec/hamster/experimental/mutable_set/add?_spec.rb +0 -47
  424. data/spec/hamster/experimental/mutable_set/add_spec.rb +0 -51
  425. data/spec/hamster/experimental/mutable_set/delete?_spec.rb +0 -47
  426. data/spec/hamster/experimental/mutable_set/delete_spec.rb +0 -47
  427. data/spec/hamster/experimental/mutable_stack/pop_spec.rb +0 -41
  428. data/spec/hamster/experimental/mutable_stack/push_spec.rb +0 -41
  429. data/spec/hamster/hash/all_spec.rb +0 -59
  430. data/spec/hamster/hash/any_spec.rb +0 -68
  431. data/spec/hamster/hash/clear_spec.rb +0 -36
  432. data/spec/hamster/hash/construction_spec.rb +0 -35
  433. data/spec/hamster/hash/copying_spec.rb +0 -23
  434. data/spec/hamster/hash/delete_spec.rb +0 -47
  435. data/spec/hamster/hash/each_spec.rb +0 -41
  436. data/spec/hamster/hash/empty_spec.rb +0 -27
  437. data/spec/hamster/hash/eql_spec.rb +0 -62
  438. data/spec/hamster/hash/except_spec.rb +0 -31
  439. data/spec/hamster/hash/fetch_spec.rb +0 -95
  440. data/spec/hamster/hash/filter_spec.rb +0 -63
  441. data/spec/hamster/hash/find_spec.rb +0 -58
  442. data/spec/hamster/hash/get_spec.rb +0 -68
  443. data/spec/hamster/hash/has_key_spec.rb +0 -35
  444. data/spec/hamster/hash/hash_spec.rb +0 -54
  445. data/spec/hamster/hash/inspect_spec.rb +0 -32
  446. data/spec/hamster/hash/keys_spec.rb +0 -21
  447. data/spec/hamster/hash/map_spec.rb +0 -64
  448. data/spec/hamster/hash/merge_spec.rb +0 -36
  449. data/spec/hamster/hash/none_spec.rb +0 -64
  450. data/spec/hamster/hash/put_spec.rb +0 -65
  451. data/spec/hamster/hash/reduce_spec.rb +0 -60
  452. data/spec/hamster/hash/remove_spec.rb +0 -63
  453. data/spec/hamster/hash/slice_spec.rb +0 -31
  454. data/spec/hamster/hash/uniq_spec.rb +0 -23
  455. data/spec/hamster/hash/values_spec.rb +0 -34
  456. data/spec/hamster/immutable/memoize_spec.rb +0 -64
  457. data/spec/hamster/immutable/new_spec.rb +0 -28
  458. data/spec/hamster/immutable/transform_spec.rb +0 -31
  459. data/spec/hamster/immutable/transform_unless_spec.rb +0 -55
  460. data/spec/hamster/list/all_spec.rb +0 -111
  461. data/spec/hamster/list/any_spec.rb +0 -79
  462. data/spec/hamster/list/append_spec.rb +0 -50
  463. data/spec/hamster/list/at_spec.rb +0 -49
  464. data/spec/hamster/list/break_spec.rb +0 -85
  465. data/spec/hamster/list/cadr_spec.rb +0 -50
  466. data/spec/hamster/list/chunk_spec.rb +0 -40
  467. data/spec/hamster/list/clear_spec.rb +0 -36
  468. data/spec/hamster/list/combinations_spec.rb +0 -51
  469. data/spec/hamster/list/compact_spec.rb +0 -46
  470. data/spec/hamster/list/cons_spec.rb +0 -41
  471. data/spec/hamster/list/construction_spec.rb +0 -140
  472. data/spec/hamster/list/copying_spec.rb +0 -32
  473. data/spec/hamster/list/count_spec.rb +0 -66
  474. data/spec/hamster/list/coverage/assets/0.4.4/app.js +0 -66
  475. data/spec/hamster/list/coverage/assets/0.4.4/fancybox/blank.gif +0 -0
  476. data/spec/hamster/list/coverage/assets/0.4.4/fancybox/fancy_close.png +0 -0
  477. data/spec/hamster/list/coverage/assets/0.4.4/fancybox/fancy_loading.png +0 -0
  478. data/spec/hamster/list/coverage/assets/0.4.4/fancybox/fancy_nav_left.png +0 -0
  479. data/spec/hamster/list/coverage/assets/0.4.4/fancybox/fancy_nav_right.png +0 -0
  480. data/spec/hamster/list/coverage/assets/0.4.4/fancybox/fancy_shadow_e.png +0 -0
  481. data/spec/hamster/list/coverage/assets/0.4.4/fancybox/fancy_shadow_n.png +0 -0
  482. data/spec/hamster/list/coverage/assets/0.4.4/fancybox/fancy_shadow_ne.png +0 -0
  483. data/spec/hamster/list/coverage/assets/0.4.4/fancybox/fancy_shadow_nw.png +0 -0
  484. data/spec/hamster/list/coverage/assets/0.4.4/fancybox/fancy_shadow_s.png +0 -0
  485. data/spec/hamster/list/coverage/assets/0.4.4/fancybox/fancy_shadow_se.png +0 -0
  486. data/spec/hamster/list/coverage/assets/0.4.4/fancybox/fancy_shadow_sw.png +0 -0
  487. data/spec/hamster/list/coverage/assets/0.4.4/fancybox/fancy_shadow_w.png +0 -0
  488. data/spec/hamster/list/coverage/assets/0.4.4/fancybox/fancy_title_left.png +0 -0
  489. data/spec/hamster/list/coverage/assets/0.4.4/fancybox/fancy_title_main.png +0 -0
  490. data/spec/hamster/list/coverage/assets/0.4.4/fancybox/fancy_title_over.png +0 -0
  491. data/spec/hamster/list/coverage/assets/0.4.4/fancybox/fancy_title_right.png +0 -0
  492. data/spec/hamster/list/coverage/assets/0.4.4/fancybox/fancybox-x.png +0 -0
  493. data/spec/hamster/list/coverage/assets/0.4.4/fancybox/fancybox-y.png +0 -0
  494. data/spec/hamster/list/coverage/assets/0.4.4/fancybox/fancybox.png +0 -0
  495. data/spec/hamster/list/coverage/assets/0.4.4/fancybox/jquery.fancybox-1.3.1.css +0 -363
  496. data/spec/hamster/list/coverage/assets/0.4.4/fancybox/jquery.fancybox-1.3.1.pack.js +0 -44
  497. data/spec/hamster/list/coverage/assets/0.4.4/favicon.png +0 -0
  498. data/spec/hamster/list/coverage/assets/0.4.4/jquery-1.4.2.min.js +0 -155
  499. data/spec/hamster/list/coverage/assets/0.4.4/jquery.dataTables.min.js +0 -152
  500. data/spec/hamster/list/coverage/assets/0.4.4/jquery.timeago.js +0 -141
  501. data/spec/hamster/list/coverage/assets/0.4.4/jquery.url.js +0 -174
  502. data/spec/hamster/list/coverage/assets/0.4.4/loading.gif +0 -0
  503. data/spec/hamster/list/coverage/assets/0.4.4/magnify.png +0 -0
  504. data/spec/hamster/list/coverage/assets/0.4.4/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  505. data/spec/hamster/list/coverage/assets/0.4.4/smoothness/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
  506. data/spec/hamster/list/coverage/assets/0.4.4/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
  507. data/spec/hamster/list/coverage/assets/0.4.4/smoothness/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  508. data/spec/hamster/list/coverage/assets/0.4.4/smoothness/images/ui-bg_glass_75_dadada_1x400.png +0 -0
  509. data/spec/hamster/list/coverage/assets/0.4.4/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  510. data/spec/hamster/list/coverage/assets/0.4.4/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  511. data/spec/hamster/list/coverage/assets/0.4.4/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  512. data/spec/hamster/list/coverage/assets/0.4.4/smoothness/images/ui-icons_222222_256x240.png +0 -0
  513. data/spec/hamster/list/coverage/assets/0.4.4/smoothness/images/ui-icons_2e83ff_256x240.png +0 -0
  514. data/spec/hamster/list/coverage/assets/0.4.4/smoothness/images/ui-icons_454545_256x240.png +0 -0
  515. data/spec/hamster/list/coverage/assets/0.4.4/smoothness/images/ui-icons_888888_256x240.png +0 -0
  516. data/spec/hamster/list/coverage/assets/0.4.4/smoothness/images/ui-icons_cd0a0a_256x240.png +0 -0
  517. data/spec/hamster/list/coverage/assets/0.4.4/smoothness/jquery-ui-1.8.4.custom.css +0 -295
  518. data/spec/hamster/list/coverage/assets/0.4.4/stylesheet.css +0 -341
  519. data/spec/hamster/list/coverage/covered_percent +0 -1
  520. data/spec/hamster/list/coverage/index.html +0 -71
  521. data/spec/hamster/list/coverage/resultset.yml +0 -225
  522. data/spec/hamster/list/cycle_spec.rb +0 -45
  523. data/spec/hamster/list/drop_spec.rb +0 -42
  524. data/spec/hamster/list/drop_while_spec.rb +0 -59
  525. data/spec/hamster/list/each_slice_spec.rb +0 -80
  526. data/spec/hamster/list/each_spec.rb +0 -72
  527. data/spec/hamster/list/each_with_index_spec.rb +0 -42
  528. data/spec/hamster/list/elem_index_spec.rb +0 -58
  529. data/spec/hamster/list/elem_indices_spec.rb +0 -45
  530. data/spec/hamster/list/empty_spec.rb +0 -47
  531. data/spec/hamster/list/eql_spec.rb +0 -78
  532. data/spec/hamster/list/filter_spec.rb +0 -61
  533. data/spec/hamster/list/find_indices_spec.rb +0 -45
  534. data/spec/hamster/list/flatten_spec.rb +0 -42
  535. data/spec/hamster/list/grep_spec.rb +0 -70
  536. data/spec/hamster/list/group_by_spec.rb +0 -77
  537. data/spec/hamster/list/hash_spec.rb +0 -43
  538. data/spec/hamster/list/init_spec.rb +0 -40
  539. data/spec/hamster/list/inits_spec.rb +0 -42
  540. data/spec/hamster/list/inspect_spec.rb +0 -43
  541. data/spec/hamster/list/intersperse_spec.rb +0 -40
  542. data/spec/hamster/list/join_spec.rb +0 -81
  543. data/spec/hamster/list/last_spec.rb +0 -44
  544. data/spec/hamster/list/map_spec.rb +0 -69
  545. data/spec/hamster/list/maximum_spec.rb +0 -77
  546. data/spec/hamster/list/minimum_spec.rb +0 -77
  547. data/spec/hamster/list/partition_spec.rb +0 -75
  548. data/spec/hamster/list/product_spec.rb +0 -44
  549. data/spec/hamster/list/reduce_spec.rb +0 -99
  550. data/spec/hamster/list/remove_spec.rb +0 -67
  551. data/spec/hamster/list/reverse_spec.rb +0 -52
  552. data/spec/hamster/list/size_spec.rb +0 -47
  553. data/spec/hamster/list/slice_spec.rb +0 -50
  554. data/spec/hamster/list/sorting_spec.rb +0 -70
  555. data/spec/hamster/list/span_spec.rb +0 -86
  556. data/spec/hamster/list/split_at_spec.rb +0 -53
  557. data/spec/hamster/list/sum_spec.rb +0 -44
  558. data/spec/hamster/list/tail_spec.rb +0 -48
  559. data/spec/hamster/list/tails_spec.rb +0 -42
  560. data/spec/hamster/list/take_spec.rb +0 -42
  561. data/spec/hamster/list/take_while_spec.rb +0 -62
  562. data/spec/hamster/list/to_a_spec.rb +0 -54
  563. data/spec/hamster/list/to_ary_spec.rb +0 -56
  564. data/spec/hamster/list/to_list_spec.rb +0 -32
  565. data/spec/hamster/list/to_set_spec.rb +0 -33
  566. data/spec/hamster/list/union_spec.rb +0 -49
  567. data/spec/hamster/list/uniq_spec.rb +0 -45
  568. data/spec/hamster/list/zip_spec.rb +0 -39
  569. data/spec/hamster/queue/clear_spec.rb +0 -36
  570. data/spec/hamster/queue/construction_spec.rb +0 -43
  571. data/spec/hamster/queue/dequeue_spec.rb +0 -40
  572. data/spec/hamster/queue/empty_spec.rb +0 -47
  573. data/spec/hamster/queue/enqueue_spec.rb +0 -41
  574. data/spec/hamster/queue/head_spec.rb +0 -35
  575. data/spec/hamster/queue/inspect_spec.rb +0 -31
  576. data/spec/hamster/queue/size_spec.rb +0 -35
  577. data/spec/hamster/queue/to_a_spec.rb +0 -42
  578. data/spec/hamster/queue/to_ary_spec.rb +0 -44
  579. data/spec/hamster/queue/to_list_spec.rb +0 -44
  580. data/spec/hamster/set/add_spec.rb +0 -51
  581. data/spec/hamster/set/all_spec.rb +0 -67
  582. data/spec/hamster/set/any_spec.rb +0 -67
  583. data/spec/hamster/set/clear_spec.rb +0 -36
  584. data/spec/hamster/set/construction_spec.rb +0 -31
  585. data/spec/hamster/set/copying_spec.rb +0 -23
  586. data/spec/hamster/set/count_spec.rb +0 -54
  587. data/spec/hamster/set/coverage/assets/0.4.4/app.js +0 -66
  588. data/spec/hamster/set/coverage/assets/0.4.4/fancybox/blank.gif +0 -0
  589. data/spec/hamster/set/coverage/assets/0.4.4/fancybox/fancy_close.png +0 -0
  590. data/spec/hamster/set/coverage/assets/0.4.4/fancybox/fancy_loading.png +0 -0
  591. data/spec/hamster/set/coverage/assets/0.4.4/fancybox/fancy_nav_left.png +0 -0
  592. data/spec/hamster/set/coverage/assets/0.4.4/fancybox/fancy_nav_right.png +0 -0
  593. data/spec/hamster/set/coverage/assets/0.4.4/fancybox/fancy_shadow_e.png +0 -0
  594. data/spec/hamster/set/coverage/assets/0.4.4/fancybox/fancy_shadow_n.png +0 -0
  595. data/spec/hamster/set/coverage/assets/0.4.4/fancybox/fancy_shadow_ne.png +0 -0
  596. data/spec/hamster/set/coverage/assets/0.4.4/fancybox/fancy_shadow_nw.png +0 -0
  597. data/spec/hamster/set/coverage/assets/0.4.4/fancybox/fancy_shadow_s.png +0 -0
  598. data/spec/hamster/set/coverage/assets/0.4.4/fancybox/fancy_shadow_se.png +0 -0
  599. data/spec/hamster/set/coverage/assets/0.4.4/fancybox/fancy_shadow_sw.png +0 -0
  600. data/spec/hamster/set/coverage/assets/0.4.4/fancybox/fancy_shadow_w.png +0 -0
  601. data/spec/hamster/set/coverage/assets/0.4.4/fancybox/fancy_title_left.png +0 -0
  602. data/spec/hamster/set/coverage/assets/0.4.4/fancybox/fancy_title_main.png +0 -0
  603. data/spec/hamster/set/coverage/assets/0.4.4/fancybox/fancy_title_over.png +0 -0
  604. data/spec/hamster/set/coverage/assets/0.4.4/fancybox/fancy_title_right.png +0 -0
  605. data/spec/hamster/set/coverage/assets/0.4.4/fancybox/fancybox-x.png +0 -0
  606. data/spec/hamster/set/coverage/assets/0.4.4/fancybox/fancybox-y.png +0 -0
  607. data/spec/hamster/set/coverage/assets/0.4.4/fancybox/fancybox.png +0 -0
  608. data/spec/hamster/set/coverage/assets/0.4.4/fancybox/jquery.fancybox-1.3.1.css +0 -363
  609. data/spec/hamster/set/coverage/assets/0.4.4/fancybox/jquery.fancybox-1.3.1.pack.js +0 -44
  610. data/spec/hamster/set/coverage/assets/0.4.4/favicon.png +0 -0
  611. data/spec/hamster/set/coverage/assets/0.4.4/jquery-1.4.2.min.js +0 -155
  612. data/spec/hamster/set/coverage/assets/0.4.4/jquery.dataTables.min.js +0 -152
  613. data/spec/hamster/set/coverage/assets/0.4.4/jquery.timeago.js +0 -141
  614. data/spec/hamster/set/coverage/assets/0.4.4/jquery.url.js +0 -174
  615. data/spec/hamster/set/coverage/assets/0.4.4/loading.gif +0 -0
  616. data/spec/hamster/set/coverage/assets/0.4.4/magnify.png +0 -0
  617. data/spec/hamster/set/coverage/assets/0.4.4/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  618. data/spec/hamster/set/coverage/assets/0.4.4/smoothness/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
  619. data/spec/hamster/set/coverage/assets/0.4.4/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
  620. data/spec/hamster/set/coverage/assets/0.4.4/smoothness/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  621. data/spec/hamster/set/coverage/assets/0.4.4/smoothness/images/ui-bg_glass_75_dadada_1x400.png +0 -0
  622. data/spec/hamster/set/coverage/assets/0.4.4/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  623. data/spec/hamster/set/coverage/assets/0.4.4/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  624. data/spec/hamster/set/coverage/assets/0.4.4/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  625. data/spec/hamster/set/coverage/assets/0.4.4/smoothness/images/ui-icons_222222_256x240.png +0 -0
  626. data/spec/hamster/set/coverage/assets/0.4.4/smoothness/images/ui-icons_2e83ff_256x240.png +0 -0
  627. data/spec/hamster/set/coverage/assets/0.4.4/smoothness/images/ui-icons_454545_256x240.png +0 -0
  628. data/spec/hamster/set/coverage/assets/0.4.4/smoothness/images/ui-icons_888888_256x240.png +0 -0
  629. data/spec/hamster/set/coverage/assets/0.4.4/smoothness/images/ui-icons_cd0a0a_256x240.png +0 -0
  630. data/spec/hamster/set/coverage/assets/0.4.4/smoothness/jquery-ui-1.8.4.custom.css +0 -295
  631. data/spec/hamster/set/coverage/assets/0.4.4/stylesheet.css +0 -341
  632. data/spec/hamster/set/coverage/covered_percent +0 -1
  633. data/spec/hamster/set/coverage/index.html +0 -71
  634. data/spec/hamster/set/coverage/resultset.yml +0 -13
  635. data/spec/hamster/set/delete_spec.rb +0 -47
  636. data/spec/hamster/set/difference_spec.rb +0 -37
  637. data/spec/hamster/set/each_spec.rb +0 -42
  638. data/spec/hamster/set/empty_spec.rb +0 -35
  639. data/spec/hamster/set/eql_spec.rb +0 -62
  640. data/spec/hamster/set/exclusion_spec.rb +0 -38
  641. data/spec/hamster/set/filter_spec.rb +0 -79
  642. data/spec/hamster/set/flatten_spec.rb +0 -49
  643. data/spec/hamster/set/grep_spec.rb +0 -62
  644. data/spec/hamster/set/group_by_spec.rb +0 -65
  645. data/spec/hamster/set/hash_spec.rb +0 -31
  646. data/spec/hamster/set/head_spec.rb +0 -39
  647. data/spec/hamster/set/include_spec.rb +0 -35
  648. data/spec/hamster/set/inspect_spec.rb +0 -32
  649. data/spec/hamster/set/intersection_spec.rb +0 -46
  650. data/spec/hamster/set/map_spec.rb +0 -64
  651. data/spec/hamster/set/maximum_spec.rb +0 -65
  652. data/spec/hamster/set/minimum_spec.rb +0 -65
  653. data/spec/hamster/set/partition_spec.rb +0 -71
  654. data/spec/hamster/set/product_spec.rb +0 -32
  655. data/spec/hamster/set/reduce_spec.rb +0 -87
  656. data/spec/hamster/set/remove_spec.rb +0 -63
  657. data/spec/hamster/set/sorting_spec.rb +0 -58
  658. data/spec/hamster/set/subset_spec.rb +0 -39
  659. data/spec/hamster/set/superset_spec.rb +0 -39
  660. data/spec/hamster/set/to_a_spec.rb +0 -42
  661. data/spec/hamster/set/to_list_spec.rb +0 -47
  662. data/spec/hamster/set/to_set_spec.rb +0 -32
  663. data/spec/hamster/set/union_spec.rb +0 -45
  664. data/spec/hamster/set/uniq_spec.rb +0 -23
  665. data/spec/hamster/sorter/coverage/assets/0.4.4/app.js +0 -66
  666. data/spec/hamster/sorter/coverage/assets/0.4.4/fancybox/blank.gif +0 -0
  667. data/spec/hamster/sorter/coverage/assets/0.4.4/fancybox/fancy_close.png +0 -0
  668. data/spec/hamster/sorter/coverage/assets/0.4.4/fancybox/fancy_loading.png +0 -0
  669. data/spec/hamster/sorter/coverage/assets/0.4.4/fancybox/fancy_nav_left.png +0 -0
  670. data/spec/hamster/sorter/coverage/assets/0.4.4/fancybox/fancy_nav_right.png +0 -0
  671. data/spec/hamster/sorter/coverage/assets/0.4.4/fancybox/fancy_shadow_e.png +0 -0
  672. data/spec/hamster/sorter/coverage/assets/0.4.4/fancybox/fancy_shadow_n.png +0 -0
  673. data/spec/hamster/sorter/coverage/assets/0.4.4/fancybox/fancy_shadow_ne.png +0 -0
  674. data/spec/hamster/sorter/coverage/assets/0.4.4/fancybox/fancy_shadow_nw.png +0 -0
  675. data/spec/hamster/sorter/coverage/assets/0.4.4/fancybox/fancy_shadow_s.png +0 -0
  676. data/spec/hamster/sorter/coverage/assets/0.4.4/fancybox/fancy_shadow_se.png +0 -0
  677. data/spec/hamster/sorter/coverage/assets/0.4.4/fancybox/fancy_shadow_sw.png +0 -0
  678. data/spec/hamster/sorter/coverage/assets/0.4.4/fancybox/fancy_shadow_w.png +0 -0
  679. data/spec/hamster/sorter/coverage/assets/0.4.4/fancybox/fancy_title_left.png +0 -0
  680. data/spec/hamster/sorter/coverage/assets/0.4.4/fancybox/fancy_title_main.png +0 -0
  681. data/spec/hamster/sorter/coverage/assets/0.4.4/fancybox/fancy_title_over.png +0 -0
  682. data/spec/hamster/sorter/coverage/assets/0.4.4/fancybox/fancy_title_right.png +0 -0
  683. data/spec/hamster/sorter/coverage/assets/0.4.4/fancybox/fancybox-x.png +0 -0
  684. data/spec/hamster/sorter/coverage/assets/0.4.4/fancybox/fancybox-y.png +0 -0
  685. data/spec/hamster/sorter/coverage/assets/0.4.4/fancybox/fancybox.png +0 -0
  686. data/spec/hamster/sorter/coverage/assets/0.4.4/fancybox/jquery.fancybox-1.3.1.css +0 -363
  687. data/spec/hamster/sorter/coverage/assets/0.4.4/fancybox/jquery.fancybox-1.3.1.pack.js +0 -44
  688. data/spec/hamster/sorter/coverage/assets/0.4.4/favicon.png +0 -0
  689. data/spec/hamster/sorter/coverage/assets/0.4.4/jquery-1.4.2.min.js +0 -155
  690. data/spec/hamster/sorter/coverage/assets/0.4.4/jquery.dataTables.min.js +0 -152
  691. data/spec/hamster/sorter/coverage/assets/0.4.4/jquery.timeago.js +0 -141
  692. data/spec/hamster/sorter/coverage/assets/0.4.4/jquery.url.js +0 -174
  693. data/spec/hamster/sorter/coverage/assets/0.4.4/loading.gif +0 -0
  694. data/spec/hamster/sorter/coverage/assets/0.4.4/magnify.png +0 -0
  695. data/spec/hamster/sorter/coverage/assets/0.4.4/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  696. data/spec/hamster/sorter/coverage/assets/0.4.4/smoothness/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
  697. data/spec/hamster/sorter/coverage/assets/0.4.4/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
  698. data/spec/hamster/sorter/coverage/assets/0.4.4/smoothness/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  699. data/spec/hamster/sorter/coverage/assets/0.4.4/smoothness/images/ui-bg_glass_75_dadada_1x400.png +0 -0
  700. data/spec/hamster/sorter/coverage/assets/0.4.4/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  701. data/spec/hamster/sorter/coverage/assets/0.4.4/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  702. data/spec/hamster/sorter/coverage/assets/0.4.4/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  703. data/spec/hamster/sorter/coverage/assets/0.4.4/smoothness/images/ui-icons_222222_256x240.png +0 -0
  704. data/spec/hamster/sorter/coverage/assets/0.4.4/smoothness/images/ui-icons_2e83ff_256x240.png +0 -0
  705. data/spec/hamster/sorter/coverage/assets/0.4.4/smoothness/images/ui-icons_454545_256x240.png +0 -0
  706. data/spec/hamster/sorter/coverage/assets/0.4.4/smoothness/images/ui-icons_888888_256x240.png +0 -0
  707. data/spec/hamster/sorter/coverage/assets/0.4.4/smoothness/images/ui-icons_cd0a0a_256x240.png +0 -0
  708. data/spec/hamster/sorter/coverage/assets/0.4.4/smoothness/jquery-ui-1.8.4.custom.css +0 -295
  709. data/spec/hamster/sorter/coverage/assets/0.4.4/stylesheet.css +0 -341
  710. data/spec/hamster/sorter/coverage/covered_percent +0 -1
  711. data/spec/hamster/sorter/coverage/index.html +0 -71
  712. data/spec/hamster/sorter/coverage/resultset.yml +0 -22
  713. data/spec/hamster/sorter/immutable_spec.rb +0 -12
  714. data/spec/hamster/stack/clear_spec.rb +0 -36
  715. data/spec/hamster/stack/construction_spec.rb +0 -43
  716. data/spec/hamster/stack/copying_spec.rb +0 -31
  717. data/spec/hamster/stack/empty_spec.rb +0 -31
  718. data/spec/hamster/stack/eql_spec.rb +0 -60
  719. data/spec/hamster/stack/immutable_spec.rb +0 -12
  720. data/spec/hamster/stack/inspect_spec.rb +0 -31
  721. data/spec/hamster/stack/peek_spec.rb +0 -40
  722. data/spec/hamster/stack/pop_spec.rb +0 -41
  723. data/spec/hamster/stack/push_spec.rb +0 -41
  724. data/spec/hamster/stack/size_spec.rb +0 -35
  725. data/spec/hamster/stack/to_a_spec.rb +0 -42
  726. data/spec/hamster/stack/to_ary.rb +0 -44
  727. data/spec/hamster/stack/to_list_spec.rb +0 -33
  728. data/spec/hamster/trie/remove_spec.rb +0 -117
  729. data/spec/hamster/tuple/copying_spec.rb +0 -24
  730. data/spec/hamster/tuple/eql_spec.rb +0 -61
  731. data/spec/hamster/tuple/first_spec.rb +0 -19
  732. data/spec/hamster/tuple/immutable_spec.rb +0 -12
  733. data/spec/hamster/tuple/inspect_spec.rb +0 -19
  734. data/spec/hamster/tuple/last_spec.rb +0 -19
  735. data/spec/hamster/tuple/to_a_spec.rb +0 -38
  736. data/spec/hamster/tuple/to_ary_spec.rb +0 -44
  737. data/spec/hamster/undefined/erase_spec.rb +0 -47
  738. data/spec/hamster/vector/add_spec.rb +0 -41
  739. data/spec/hamster/vector/any_spec.rb +0 -67
  740. data/spec/hamster/vector/clear_spec.rb +0 -36
  741. data/spec/hamster/vector/copying_spec.rb +0 -32
  742. data/spec/hamster/vector/each_spec.rb +0 -46
  743. data/spec/hamster/vector/each_with_index_spec.rb +0 -42
  744. data/spec/hamster/vector/empty_spec.rb +0 -35
  745. data/spec/hamster/vector/eql_spec.rb +0 -65
  746. data/spec/hamster/vector/filter_spec.rb +0 -63
  747. data/spec/hamster/vector/first_spec.rb +0 -35
  748. data/spec/hamster/vector/get_spec.rb +0 -81
  749. data/spec/hamster/vector/inspect_spec.rb +0 -31
  750. data/spec/hamster/vector/last_spec.rb +0 -32
  751. data/spec/hamster/vector/map_spec.rb +0 -64
  752. data/spec/hamster/vector/set_spec.rb +0 -153
  753. data/spec/hamster/vector/to_a_spec.rb +0 -42
  754. data/spec/hamster/vector/to_ary_spec.rb +0 -44
  755. data/tasks/bundler.rb +0 -2
  756. data/tasks/publish.rb +0 -12
  757. data/tasks/spec.rb +0 -13
@@ -1,7 +1,6 @@
1
1
  module Hamster
2
-
2
+ # @private
3
3
  module Immutable
4
-
5
4
  def self.included(klass)
6
5
  klass.extend(ClassMethods)
7
6
  klass.instance_eval do
@@ -9,8 +8,8 @@ module Hamster
9
8
  end
10
9
  end
11
10
 
11
+ # @private
12
12
  module ClassMethods
13
-
14
13
  def new(*args)
15
14
  super.immutable!
16
15
  end
@@ -31,20 +30,18 @@ module Hamster
31
30
  METHOD
32
31
  end
33
32
  end
34
-
35
33
  end
36
34
 
35
+ # @private
37
36
  module MemoizeMethods
38
-
39
37
  def immutable!
40
38
  @__hamster_immutable_memory__ = Object.new
41
39
  freeze
42
40
  end
43
-
44
41
  end
45
42
 
43
+ # @private
46
44
  module InstanceMethods
47
-
48
45
  def immutable!
49
46
  freeze
50
47
  end
@@ -73,9 +70,6 @@ module Hamster
73
70
  def transform(&block)
74
71
  __hamster_immutable_dup__.tap { |copy| copy.instance_eval(&block) }.immutable!
75
72
  end
76
-
77
73
  end
78
-
79
74
  end
80
-
81
75
  end
@@ -1,135 +1,337 @@
1
- require 'forwardable'
2
- require 'thread'
1
+ require "thread"
2
+ require "atomic"
3
+ require "set"
3
4
 
4
- require 'hamster/core_ext/enumerable'
5
- require 'hamster/undefined'
6
- require 'hamster/enumerable'
7
- require 'hamster/tuple'
8
- require 'hamster/sorter'
9
- require 'hamster/hash'
10
- require 'hamster/set'
5
+ require "hamster/core_ext/enumerable"
6
+ require "hamster/undefined"
7
+ require "hamster/enumerable"
8
+ require "hamster/hash"
9
+ require "hamster/set"
11
10
 
12
11
  module Hamster
13
-
14
12
  class << self
15
13
 
16
- extend Forwardable
17
-
14
+ # Create a list containing the given items.
15
+ #
16
+ # @example
17
+ # list = Hamster.list(:a, :b, :c)
18
+ # # => Hamster::List[:a, :b, :c]
19
+ #
20
+ # @return [List]
18
21
  def list(*items)
19
22
  items.to_list
20
23
  end
21
24
 
25
+ # Create a lazy, infinite list.
26
+ #
27
+ # The given block is called as necessary to return successive elements of the list.
28
+ #
29
+ # @example
30
+ # Hamster.stream { :hello }.take(3)
31
+ # # => Hamster::List[:hello, :hello, :hello]
32
+ #
33
+ # @return [List]
22
34
  def stream(&block)
23
35
  return EmptyList unless block_given?
24
- Stream.new { Sequence.new(yield, stream(&block)) }
25
- end
26
-
36
+ LazyList.new { Cons.new(yield, stream(&block)) }
37
+ end
38
+
39
+ # Construct a list of consecutive integers.
40
+ #
41
+ # @example
42
+ # Hamster.interval(5,9)
43
+ # # => Hamster::List[5, 6, 7, 8, 9]
44
+ #
45
+ # @param from [Integer] Start value, inclusive
46
+ # @param to [Integer] End value, inclusive
47
+ # @return [List]
27
48
  def interval(from, to)
28
49
  return EmptyList if from > to
29
50
  interval_exclusive(from, to.next)
30
51
  end
31
- def_delegator :self, :interval, :range
32
52
 
53
+ # Create an infinite list repeating the same item indefinitely
54
+ #
55
+ # @example
56
+ # Hamster.repeat(:chunky).take(4)
57
+ # => Hamster::List[:chunky, :chunky, :chunky, :chunky]
58
+ #
59
+ # @return [List]
33
60
  def repeat(item)
34
- Stream.new { Sequence.new(item, repeat(item)) }
61
+ LazyList.new { Cons.new(item, repeat(item)) }
35
62
  end
36
63
 
64
+ # Create a list that contains a given item a fixed number of times
65
+ #
66
+ # @example
67
+ # Hamster.replicate(3).(:hamster)
68
+ # #=> Hamster::List[:hamster, :hamster, :hamster]
69
+ #
70
+ # @return [List]
37
71
  def replicate(number, item)
38
72
  repeat(item).take(number)
39
73
  end
40
74
 
75
+ # Create an infinite list where each item is derived from the previous one,
76
+ # using the provided block
77
+ #
78
+ # @example
79
+ # Hamster.iterate(0) { |i| i.next }.take(5)
80
+ # # => Hamster::List[0, 1, 2, 3, 4]
81
+ #
82
+ # @param item [Object] Starting value
83
+ # @yieldparam [Object] The previous value
84
+ # @yieldreturn [Object] The next value
85
+ # @return [List]
41
86
  def iterate(item, &block)
42
- Stream.new { Sequence.new(item, iterate(yield(item), &block)) }
87
+ LazyList.new { Cons.new(item, iterate(yield(item), &block)) }
88
+ end
89
+
90
+ # Turn an Enumerator into a `Hamster::List`. The result is a lazy collection
91
+ # where the values are memoized as they are generated.
92
+ #
93
+ # If your code uses multiple threads, you need to make sure that the returned
94
+ # lazy collection is realized on a single thread only. Otherwise, a `FiberError`
95
+ # will be raised. After the collection is realized, it can be used from other
96
+ # threads as well.
97
+ #
98
+ # @example
99
+ # def rg; loop { yield rand(100) }; end
100
+ # Hamster.enumerate(to_enum(:rg)).take(10)
101
+ #
102
+ # @param enum [Enumerator] The object to iterate over
103
+ # @return [List]
104
+ def enumerate(enum)
105
+ LazyList.new do
106
+ begin
107
+ Cons.new(enum.next, enumerate(enum))
108
+ rescue StopIteration
109
+ EmptyList
110
+ end
111
+ end
43
112
  end
44
113
 
45
114
  private
46
115
 
47
116
  def interval_exclusive(from, to)
48
117
  return EmptyList if from == to
49
- Stream.new { Sequence.new(from, interval_exclusive(from.next, to)) }
118
+ LazyList.new { Cons.new(from, interval_exclusive(from.next, to)) }
50
119
  end
51
-
52
120
  end
53
121
 
122
+ # A `List` can be constructed with {Hamster.list Hamster.list} or {List.[] List[]}.
123
+ # It consists of a *head* (the first element) and a *tail* (which itself is also
124
+ # a `List`, containing all the remaining elements).
125
+ #
126
+ # This is a singly linked list. Prepending to the list with {List#cons} runs
127
+ # in constant time. Traversing the list from front to back is efficient,
128
+ # however, indexed access runs in linear time because the list needs to be
129
+ # traversed to find the element.
130
+ #
54
131
  module List
55
-
56
- extend Forwardable
57
-
58
132
  include Enumerable
59
133
 
134
+ # @private
60
135
  CADR = /^c([ad]+)r$/
61
136
 
62
- def_delegator :self, :head, :first
63
-
64
- def_delegator :self, :empty?, :null?
65
-
66
- def size
67
- reduce(0) { |memo, item| memo.next }
137
+ # Create a new `List` populated with the given items.
138
+ #
139
+ # @example
140
+ # list = Hamster::List[:a, :b, :c]
141
+ # # => Hamster::List[:a, :b, :c]
142
+ #
143
+ # @return [List]
144
+ def self.[](*items)
145
+ items.to_list
68
146
  end
69
- def_delegator :self, :size, :length
70
147
 
148
+ # Return the number of items in this `List`.
149
+ # @return [Integer]
150
+ def size
151
+ result, list = 0, self
152
+ until list.empty?
153
+ if list.cached_size?
154
+ return result + list.size
155
+ else
156
+ result += 1
157
+ end
158
+ list = list.tail
159
+ end
160
+ result
161
+ end
162
+ alias :length :size
163
+
164
+ # Create a new `List` with `item` added at the front.
165
+ #
166
+ # @example
167
+ # Hamster.list(:b, :c).cons(:a)
168
+ # # => Hamster::List[:a, :b, :c]
169
+ #
170
+ # @param item [Object] The item to add
171
+ # @return [List]
71
172
  def cons(item)
72
- Sequence.new(item, self)
73
- end
74
- def_delegator :self, :cons, :>>
75
-
173
+ Cons.new(item, self)
174
+ end
175
+ alias :add :cons
176
+
177
+ # Create a new `List` with `item` added at the end. This is much less efficient
178
+ # than adding items at the front.
179
+ #
180
+ # @example
181
+ # Hamster.list(:a, :b) << :c
182
+ # # => Hamster::List[:a, :b, :c]
183
+ #
184
+ # @param item [Object] The item to add
185
+ # @return [List]
186
+ def <<(item)
187
+ append(Hamster.list(item))
188
+ end
189
+
190
+ # Call the given block once for each item in the list, passing each
191
+ # item from first to last successively to the block.
192
+ #
193
+ # @return [self]
76
194
  def each
77
- return self unless block_given?
195
+ return to_enum unless block_given?
78
196
  list = self
79
- while !list.empty?
197
+ until list.empty?
80
198
  yield(list.head)
81
199
  list = list.tail
82
200
  end
83
201
  end
84
202
 
203
+ # Return a lazy list in which each element is derived from the corresponding
204
+ # element in this `List`, transformed through the given block.
205
+ #
206
+ # @example
207
+ # Hamster.list(3, 2, 1).map { |e| e * e } # => Hamster::List[9, 4, 1]
208
+ #
209
+ # @return [List]
85
210
  def map(&block)
86
- return self unless block_given?
87
- Stream.new do
211
+ return enum_for(:map) unless block_given?
212
+ LazyList.new do
88
213
  next self if empty?
89
- Sequence.new(yield(head), tail.map(&block))
214
+ Cons.new(yield(head), tail.map(&block))
90
215
  end
91
216
  end
92
- def_delegator :self, :map, :collect
93
-
94
- def filter(&block)
95
- return self unless block_given?
96
- Stream.new do
217
+ alias :collect :map
218
+
219
+ # Return a lazy list which is realized by transforming each item into a `List`,
220
+ # and flattening the resulting lists.
221
+ #
222
+ # @example
223
+ # Hamster.list(1, 2, 3).flat_map { |x| Hamster.list(x, 100) }
224
+ # # => Hamster::List[1, 100, 2, 100, 3, 100]
225
+ #
226
+ # @return [List]
227
+ def flat_map(&block)
228
+ return enum_for(:flat_map) unless block_given?
229
+ LazyList.new do
97
230
  next self if empty?
98
- next Sequence.new(head, tail.filter(&block)) if yield(head)
99
- tail.filter(&block)
231
+ head_list = Hamster.list(*yield(head))
232
+ next tail.flat_map(&block) if head_list.empty?
233
+ Cons.new(head_list.first, head_list.drop(1).append(tail.flat_map(&block)))
100
234
  end
101
235
  end
102
236
 
237
+ # Return a lazy list which contains all the items for which the given block
238
+ # returns true.
239
+ #
240
+ # @example
241
+ # Hamster.list("Bird", "Cow", "Elephant").select { |e| e.size >= 4 }
242
+ # # => Hamster::List["Bird", "Elephant"]
243
+ #
244
+ # @return [List]
245
+ def select(&block)
246
+ return enum_for(:select) unless block_given?
247
+ LazyList.new do
248
+ list = self
249
+ while true
250
+ break list if list.empty?
251
+ break Cons.new(list.head, list.tail.select(&block)) if yield(list.head)
252
+ list = list.tail
253
+ end
254
+ end
255
+ end
256
+ alias :find_all :select
257
+ alias :keep_if :select
258
+
259
+ # Return a lazy list which contains all elements up to, but not including, the
260
+ # first element for which the block returns `nil` or `false`.
261
+ #
262
+ # @example
263
+ # Hamster.list(1, 3, 5, 7, 6, 4, 2).take_while { |e| e < 5 }
264
+ # # => Hamster::List[1, 3]
265
+ #
266
+ # @return [List, Enumerator]
103
267
  def take_while(&block)
104
- return self unless block_given?
105
- Stream.new do
268
+ return enum_for(:take_while) unless block_given?
269
+ LazyList.new do
106
270
  next self if empty?
107
- next Sequence.new(head, tail.take_while(&block)) if yield(head)
271
+ next Cons.new(head, tail.take_while(&block)) if yield(head)
108
272
  EmptyList
109
273
  end
110
274
  end
111
275
 
276
+ # Return a lazy list which contains all elements starting from the
277
+ # first element for which the block returns `nil` or `false`.
278
+ #
279
+ # @example
280
+ # Hamster.list(1, 3, 5, 7, 6, 4, 2).drop_while { |e| e < 5 }
281
+ # # => Hamster::List[5, 7, 6, 4, 2]
282
+ #
283
+ # @return [List, Enumerator]
112
284
  def drop_while(&block)
113
- return self unless block_given?
114
- Stream.new do
285
+ return enum_for(:drop_while) unless block_given?
286
+ LazyList.new do
115
287
  list = self
116
- while !list.empty? && yield(list.head)
117
- list = list.tail
118
- end
288
+ list = list.tail while !list.empty? && yield(list.head)
119
289
  list
120
290
  end
121
291
  end
122
292
 
293
+ # Return a lazy list containing the first `number` items from this `List`.
294
+ #
295
+ # @example
296
+ # Hamster.list(1, 3, 5, 7, 6, 4, 2).take(3)
297
+ # # => Hamster::List[1, 3, 5]
298
+ #
299
+ # @param number [Integer] The number of items to retain
300
+ # @return [List]
123
301
  def take(number)
124
- Stream.new do
302
+ LazyList.new do
303
+ next self if empty?
304
+ next Cons.new(head, tail.take(number - 1)) if number > 0
305
+ EmptyList
306
+ end
307
+ end
308
+
309
+ # Return a lazy list containing all but the last item from this `List`.
310
+ #
311
+ # @example
312
+ # Hamster.list("A", "B", "C").pop # => Hamster::List["A", "B"]
313
+ #
314
+ # @return [List]
315
+ def pop
316
+ LazyList.new do
125
317
  next self if empty?
126
- next Sequence.new(head, tail.take(number - 1)) if number > 0
318
+ new_size = size - 1
319
+ next Cons.new(head, tail.take(new_size - 1)) if new_size >= 1
127
320
  EmptyList
128
321
  end
129
322
  end
130
323
 
324
+ # Return a lazy list containing all items after the first `number` items from
325
+ # this `List`.
326
+ #
327
+ # @example
328
+ # Hamster.list(1, 3, 5, 7, 6, 4, 2).drop(3)
329
+ # # => Hamster::List[7, 6, 4, 2]
330
+ #
331
+ # @param number [Integer] The number of items to skip over
332
+ # @return [List]
131
333
  def drop(number)
132
- Stream.new do
334
+ LazyList.new do
133
335
  list = self
134
336
  while !list.empty? && number > 0
135
337
  number -= 1
@@ -139,226 +341,688 @@ module Hamster
139
341
  end
140
342
  end
141
343
 
344
+ # Return a lazy list with all items from this `List`, followed by all items from
345
+ # `other`.
346
+ #
347
+ # @example
348
+ # Hamster.list(1, 2, 3).append(Hamster.list(4, 5))
349
+ # # => Hamster::List[1, 2, 3, 4, 5]
350
+ #
351
+ # @param other [List] The list to add onto the end of this one
352
+ # @return [List]
142
353
  def append(other)
143
- Stream.new do
354
+ LazyList.new do
144
355
  next other if empty?
145
- Sequence.new(head, tail.append(other))
356
+ Cons.new(head, tail.append(other))
146
357
  end
147
358
  end
148
- def_delegator :self, :append, :concat
149
- def_delegator :self, :append, :cat
150
- def_delegator :self, :append, :+
359
+ alias :concat :append
360
+ alias :+ :append
151
361
 
362
+ # Return a `List` with the same items, but in reverse order.
363
+ #
364
+ # @example
365
+ # Hamster.list("A", "B", "C").reverse # => Hamster::List["C", "B", "A"]
366
+ #
367
+ # @return [List]
152
368
  def reverse
153
- Stream.new { reduce(EmptyList) { |list, item| list.cons(item) } }
369
+ LazyList.new { reduce(EmptyList) { |list, item| list.cons(item) }}
370
+ end
371
+
372
+ # Gather the corresponding elements from this `List` and `others` (that is,
373
+ # the elements with the same indices) into new 2-element lists. Return a
374
+ # lazy list of these 2-element lists.
375
+ #
376
+ #
377
+ # @example
378
+ # Hamster.list("A", "B", "C").zip(Hamster.list(1, 2, 3))
379
+ # # => Hamster::List[Hamster::List["A", 1], Hamster::List["B", 2], Hamster::List["C", 3]]
380
+ #
381
+ # @param others [List] The list to zip together with this one
382
+ # @return [List]
383
+ def zip(others)
384
+ LazyList.new do
385
+ next self if empty? && others.empty?
386
+ Cons.new(Cons.new(head, Cons.new(others.head)), tail.zip(others.tail))
387
+ end
154
388
  end
155
389
 
156
- def zip(other)
157
- Stream.new do
158
- next self if empty? && other.empty?
159
- Sequence.new(Sequence.new(head, Sequence.new(other.head)), tail.zip(other.tail))
390
+ # Gather the first element of each nested list into a new `List`, then the second
391
+ # element of each nested list, then the third, and so on. In other words, if each
392
+ # nested list is a "row", return a lazy list of "columns" instead.
393
+ #
394
+ # Although the returned list is lazy, each returned nested list (each "column")
395
+ # is strict. So while each nested list in the input can be infinite, the parent
396
+ # `List` must not be, or trying to realize the first element in the output will
397
+ # cause an infinite loop.
398
+ #
399
+ # @example
400
+ # # First let's create some infinite lists
401
+ # list1 = Hamster.iterate(1, &:next)
402
+ # list2 = Hamster.iterate(2) { |n| n * 2 }
403
+ # list3 = Hamster.iterate(3) { |n| n * 3 }
404
+ #
405
+ # # Now we transpose our 3 infinite "rows" into an infinite series of 3-element "columns"
406
+ # Hamster.list(list1, list2, list3).transpose.take(4)
407
+ # # => Hamster::List[
408
+ # # Hamster::List[1, 2, 3],
409
+ # # Hamster::List[2, 4, 9],
410
+ # # Hamster::List[3, 8, 27],
411
+ # # Hamster::List[4, 16, 81]]
412
+ #
413
+ # @return [List]
414
+ def transpose
415
+ return EmptyList if empty?
416
+ LazyList.new do
417
+ next EmptyList if any? { |list| list.empty? }
418
+ heads, tails = EmptyList, EmptyList
419
+ reverse_each { |list| heads, tails = heads.cons(list.head), tails.cons(list.tail) }
420
+ Cons.new(heads, tails.transpose)
160
421
  end
161
422
  end
162
423
 
424
+ # Concatenate an infinite series of copies of this `List` together (into a
425
+ # new lazy list). Or, if empty, just return an empty list.
426
+ #
427
+ # @example
428
+ # Hamster.list(1, 2, 3).cycle.take(10)
429
+ # # => Hamster::List[1, 2, 3, 1, 2, 3, 1, 2, 3, 1]
430
+ #
431
+ # @return [List]
163
432
  def cycle
164
- Stream.new do
433
+ LazyList.new do
165
434
  next self if empty?
166
- Sequence.new(head, tail.append(self.cycle))
435
+ Cons.new(head, tail.append(cycle))
167
436
  end
168
437
  end
169
438
 
439
+ # Return a new `List` with the same elements, but rotated so that the one at
440
+ # index `count` is the first element of the new list. If `count` is positive,
441
+ # the elements will be shifted left, and those shifted past the lowest position
442
+ # will be moved to the end. If `count` is negative, the elements will be shifted
443
+ # right, and those shifted past the last position will be moved to the beginning.
444
+ #
445
+ # @example
446
+ # l = Hamster.list("A", "B", "C", "D", "E", "F")
447
+ # l.rotate(2) # => Hamster::List["C", "D", "E", "F", "A", "B"]
448
+ # l.rotate(-1) # => Hamster::List["F", "A", "B", "C", "D", "E"]
449
+ #
450
+ # @param count [Integer] The number of positions to shift items by
451
+ # @return [Vector]
452
+ def rotate(count = 1)
453
+ raise TypeError, "expected Integer" if not count.is_a?(Integer)
454
+ return self if empty? || (count % size) == 0
455
+ count = (count >= 0) ? count % size : (size - (~count % size) - 1)
456
+ drop(count).append(take(count))
457
+ end
458
+
459
+ # Return 2 `List`s, one of the first `number` items, and another of all the
460
+ # remaining items.
461
+ #
462
+ # @example
463
+ # Hamster.list("a", "b", "c", "d").split(2)
464
+ # # => [Hamster::List["a", "b"], Hamster::List["c", "d"]]
465
+ #
466
+ # @param number [Integer] The index at which to split this list
467
+ # @return [Array]
170
468
  def split_at(number)
171
- Tuple.new(take(number), drop(number))
469
+ [take(number), drop(number)].freeze
172
470
  end
173
471
 
472
+ # Return 2 `List`s, one up to (but not including) the first item for which the
473
+ # block returns `nil` or `false`, and another of all the remaining items.
474
+ #
475
+ # @example
476
+ # Hamster.list(4, 3, 5, 2, 1).span { |x| x > 2 }
477
+ # # => [Hamster::List[4, 3, 5], Hamster::List[2, 1]]
478
+ #
479
+ # @return [Array]
174
480
  def span(&block)
175
- return Tuple.new(self, EmptyList) unless block_given?
176
- Tuple.new(take_while(&block), drop_while(&block))
177
- end
178
-
481
+ return [self, EmptyList].freeze unless block_given?
482
+ splitter = Splitter.new(self, block)
483
+ mutex = Mutex.new
484
+ [Splitter::Left.new(splitter, splitter.left, mutex),
485
+ Splitter::Right.new(splitter, mutex)].freeze
486
+ end
487
+
488
+ # Return 2 `List`s, one up to (but not including) the first item for which the
489
+ # block returns true, and another of all the remaining items.
490
+ #
491
+ # @example
492
+ # Hamster.list(1, 3, 4, 2, 5).break { |x| x > 3 }
493
+ # # => [Hamster::List[1, 3], Hamster::List[4, 2, 5]]
494
+ #
495
+ # @return [Array]
179
496
  def break(&block)
180
497
  return span unless block_given?
181
498
  span { |item| !yield(item) }
182
499
  end
183
500
 
501
+ # Return an empty `List`.
502
+ # @return [List]
184
503
  def clear
185
504
  EmptyList
186
505
  end
187
506
 
507
+ # Return a `List` with the same items, but sorted either in their natural order,
508
+ # or using an optional comparator block. The block must take 2 parameters, and
509
+ # return 0, 1, or -1 if the first one is equal, greater than, or less than the
510
+ # second (respectively).
511
+ #
512
+ # @return [List]
188
513
  def sort(&comparator)
189
- Stream.new { Sorter.new(self).sort(&comparator) }
514
+ LazyList.new { super(&comparator).to_list }
190
515
  end
191
516
 
517
+ # Return a new `List` with the same items, but sorted. The sort order will be
518
+ # determined by mapping the items through the given block to obtain sort keys,
519
+ # and then sorting the keys according to their natural sort order.
520
+ #
521
+ # @return [List]
192
522
  def sort_by(&transformer)
193
523
  return sort unless block_given?
194
- Stream.new { Sorter.new(self).sort_by(&transformer) }
195
- end
196
-
197
- def join(sep = "")
198
- return "" if empty?
199
- sep = sep.to_s
200
- tail.reduce(head.to_s.dup) { |result, item| result << sep << item.to_s }
524
+ LazyList.new { super(&transformer).to_list }
201
525
  end
202
526
 
527
+ # Return a new `List` with `sep` inserted between each of the existing elements.
528
+ #
529
+ # @example
530
+ # Hamster.list("one", "two", "three").intersperse(" ")
531
+ # # => Hamster::List["one", " ", "two", " ", "three"]
532
+ #
533
+ # @return [List]
203
534
  def intersperse(sep)
204
- Stream.new do
535
+ LazyList.new do
205
536
  next self if tail.empty?
206
- Sequence.new(head, Sequence.new(sep, tail.intersperse(sep)))
537
+ Cons.new(head, Cons.new(sep, tail.intersperse(sep)))
207
538
  end
208
539
  end
209
540
 
210
- def uniq(items = EmptySet)
211
- Stream.new do
541
+ # Return a lazy list with the same items, but all duplicates removed.
542
+ # Use `#hash` and `#eql?` to determine which items are duplicates.
543
+ #
544
+ # @example
545
+ # Hamster.list(:a, :b, :a, :c, :b).uniq # => Hamster::List[:a, :b, :c]
546
+ #
547
+ # @return [List]
548
+ def uniq(items = ::Set.new)
549
+ LazyList.new do
212
550
  next self if empty?
213
551
  next tail.uniq(items) if items.include?(head)
214
- Sequence.new(head, tail.uniq(items.add(head)))
552
+ Cons.new(head, tail.uniq(items.add(head)))
215
553
  end
216
554
  end
217
- def_delegator :self, :uniq, :nub
218
- def_delegator :self, :uniq, :remove_duplicates
219
555
 
220
- def union(other)
221
- self.append(other).uniq
556
+ # Return a `List` with all the elements from both this list and `other`,
557
+ # with all duplicates removed.
558
+ #
559
+ # @example
560
+ # Hamster.list(1, 2).union(Hamster.list(2, 3)) # => Hamster::List[1, 2, 3]
561
+ #
562
+ # @param other [List] The list to merge with
563
+ # @return [List]
564
+ def union(other, items = ::Set.new)
565
+ LazyList.new do
566
+ next other.uniq(items) if empty?
567
+ next tail.union(other, items) if items.include?(head)
568
+ Cons.new(head, tail.union(other, items.add(head)))
569
+ end
222
570
  end
223
- def_delegator :self, :union, :|
571
+ alias :| :union
224
572
 
573
+ # Return a lazy list with all elements except the last one.
574
+ #
575
+ # @example
576
+ # Hamster.list("a", "b", "c").init # => Hamster::List["a", "b"]
577
+ #
578
+ # @return [List]
225
579
  def init
226
580
  return EmptyList if tail.empty?
227
- Stream.new { Sequence.new(head, tail.init) }
581
+ LazyList.new { Cons.new(head, tail.init) }
228
582
  end
229
583
 
584
+ # Return the last item in this list.
585
+ # @return [Object]
230
586
  def last
231
587
  list = self
232
- while !list.tail.empty?
233
- list = list.tail
234
- end
588
+ list = list.tail until list.tail.empty?
235
589
  list.head
236
590
  end
237
591
 
592
+ # Return a lazy list of all suffixes of this list.
593
+ #
594
+ # @example
595
+ # Hamster.list(1,2,3).tails
596
+ # # => Hamster::List[
597
+ # # Hamster::List[1, 2, 3],
598
+ # # Hamster::List[2, 3],
599
+ # # Hamster::List[3]]
600
+ #
601
+ # @return [List]
238
602
  def tails
239
- Stream.new do
240
- next Sequence.new(self) if empty?
241
- Sequence.new(self, tail.tails)
603
+ LazyList.new do
604
+ next self if empty?
605
+ Cons.new(self, tail.tails)
242
606
  end
243
607
  end
244
608
 
609
+ # Return a lazy list of all prefixes of this list.
610
+ #
611
+ # @example
612
+ # Hamster.list(1,2,3).inits
613
+ # # => Hamster::List[
614
+ # # Hamster::List[1],
615
+ # # Hamster::List[1, 2],
616
+ # # Hamster::List[1, 2, 3]]
617
+ #
618
+ # @return [List]
245
619
  def inits
246
- Stream.new do
247
- next Sequence.new(self) if empty?
248
- Sequence.new(EmptyList, tail.inits.map { |list| list.cons(head) })
620
+ LazyList.new do
621
+ next self if empty?
622
+ Cons.new(Hamster.list(head), tail.inits.map { |list| list.cons(head) })
249
623
  end
250
624
  end
251
625
 
252
- def combinations(number)
253
- return Sequence.new(EmptyList) if number == 0
254
- Stream.new do
626
+ # Return a lazy list of all combinations of length `n` of items from this `List`.
627
+ #
628
+ # @example
629
+ # Hamster.list(1,2,3).combination(2)
630
+ # # => Hamster::List[
631
+ # # Hamster::List[1, 2],
632
+ # # Hamster::List[1, 3],
633
+ # # Hamster::List[2, 3]]
634
+ #
635
+ # @return [List]
636
+ def combination(n)
637
+ return Cons.new(EmptyList) if n == 0
638
+ LazyList.new do
255
639
  next self if empty?
256
- tail.combinations(number - 1).map { |list| list.cons(head) }.append(tail.combinations(number))
640
+ tail.combination(n - 1).map { |list| list.cons(head) }.append(tail.combination(n))
257
641
  end
258
642
  end
259
- def_delegator :self, :combinations, :combination
260
643
 
644
+ # Split the items in this list in groups of `number`. Return a list of lists.
645
+ #
646
+ # @example
647
+ # Hamster.list(*("a".."o")).chunk(5)
648
+ # # => Hamster::List[
649
+ # # Hamster::List["a", "b", "c", "d", "e"],
650
+ # # Hamster::List["f", "g", "h", "i", "j"],
651
+ # # Hamster::List["k", "l", "m", "n", "o"]]
652
+ #
653
+ # @return [List]
261
654
  def chunk(number)
262
- Stream.new do
655
+ LazyList.new do
263
656
  next self if empty?
264
657
  first, remainder = split_at(number)
265
- Sequence.new(first, remainder.chunk(number))
658
+ Cons.new(first, remainder.chunk(number))
266
659
  end
267
660
  end
268
661
 
662
+ # Split the items in this list in groups of `number`, and yield each group
663
+ # to the block (as a `List`).
664
+ # @return [self]
269
665
  def each_chunk(number, &block)
666
+ return enum_for(:each_chunk, number) unless block_given?
270
667
  chunk(number).each(&block)
668
+ self
271
669
  end
272
- def_delegator :self, :each_chunk, :each_slice
273
-
670
+ alias :each_slice :each_chunk
671
+
672
+ # Return a new `List` with all nested lists recursively "flattened out",
673
+ # that is, their elements inserted into the new `List` in the place where
674
+ # the nested list originally was.
675
+ #
676
+ # @example
677
+ # Hamster.list(Hamster.list(1, 2), Hamster.list(3, 4)).flatten
678
+ # # => Hamster::List[1, 2, 3, 4]
679
+ #
680
+ # @return [List]
274
681
  def flatten
275
- Stream.new do
682
+ LazyList.new do
276
683
  next self if empty?
277
684
  next head.append(tail.flatten) if head.is_a?(List)
278
- Sequence.new(head, tail.flatten)
685
+ Cons.new(head, tail.flatten)
279
686
  end
280
687
  end
281
688
 
689
+ # Passes each item to the block, and gathers them into a {Hash} where the
690
+ # keys are return values from the block, and the values are `List`s of items
691
+ # for which the block returned that value.
692
+ #
693
+ # @return [Hash]
282
694
  def group_by(&block)
283
- return group_by { |item| item } unless block_given?
284
- reduce(EmptyHash) do |hash, item|
285
- key = yield(item)
286
- hash.put(key, (hash.get(key) || EmptyList).cons(item))
287
- end
695
+ group_by_with(EmptyList, &block)
288
696
  end
289
- def_delegator :self, :group_by, :group
697
+ alias :group :group_by
290
698
 
699
+ # Retrieve the item at `index`. Negative indices count back from the end of
700
+ # the list (-1 is the last item). If `index` is invalid (either too high or
701
+ # too low), return `nil`.
702
+ #
703
+ # @param index [Integer] The index to retrieve
704
+ # @return [Object]
291
705
  def at(index)
292
- drop(index).head
706
+ index += size if index < 0
707
+ return nil if index < 0
708
+ node = self
709
+ while index > 0
710
+ node = node.tail
711
+ index -= 1
712
+ end
713
+ node.head
714
+ end
715
+
716
+ # Element reference. Return the item at a specific index, or a specified,
717
+ # contiguous range of items (as a new list).
718
+ #
719
+ # @overload list[index]
720
+ # Return the item at `index`.
721
+ # @param index [Integer] The index to retrieve.
722
+ # @overload list[start, length]
723
+ # Return a sublist starting at index `start` and continuing for `length` elements.
724
+ # @param start [Integer] The index to start retrieving items from.
725
+ # @param length [Integer] The number of items to retrieve.
726
+ # @overload list[range]
727
+ # Return a sublist specified by the given `range` of indices.
728
+ # @param range [Range] The range of indices to retrieve.
729
+ #
730
+ # @return [Object]
731
+ def [](arg, length = (missing_length = true))
732
+ if missing_length
733
+ if arg.is_a?(Range)
734
+ from, to = arg.begin, arg.end
735
+ from += size if from < 0
736
+ return nil if from < 0
737
+ to += size if to < 0
738
+ to += 1 if !arg.exclude_end?
739
+ length = to - from
740
+ length = 0 if length < 0
741
+ list = self
742
+ while from > 0
743
+ return nil if list.empty?
744
+ list = list.tail
745
+ from -= 1
746
+ end
747
+ list.take(length)
748
+ else
749
+ at(arg)
750
+ end
751
+ else
752
+ return nil if length < 0
753
+ arg += size if arg < 0
754
+ return nil if arg < 0
755
+ list = self
756
+ while arg > 0
757
+ return nil if list.empty?
758
+ list = list.tail
759
+ arg -= 1
760
+ end
761
+ list.take(length)
762
+ end
293
763
  end
294
-
295
- def slice(from, length = Undefined)
296
- return at(from) if length.equal?(Undefined)
297
- drop(from).take(length)
764
+ alias :slice :[]
765
+
766
+ # Return a `List` of indices where the given object is found, or where the given
767
+ # block returns true.
768
+ #
769
+ # @overload indices(obj)
770
+ # Return a `List` of indices where `obj` is found. Use `#==` for testing equality.
771
+ # @overload indices { |item| ... }
772
+ # Pass each item successively to the block. Return a list of indices where the
773
+ # block returns true.
774
+ #
775
+ # @return [List]
776
+ def indices(object = Undefined, i = 0, &block)
777
+ return indices { |item| item == object } if not block_given?
778
+ return EmptyList if empty?
779
+ LazyList.new do
780
+ node = self
781
+ while true
782
+ break Cons.new(i, node.tail.indices(Undefined, i + 1, &block)) if yield(node.head)
783
+ node = node.tail
784
+ break EmptyList if node.empty?
785
+ i += 1
786
+ end
787
+ end
298
788
  end
299
- def_delegator :self, :slice, :[]
300
789
 
301
- def find_index
302
- return nil unless block_given?
303
- i = 0
304
- list = self
305
- loop do
306
- return nil if list.empty?
307
- return i if yield(list.head)
308
- i += 1
309
- list = list.tail
790
+ # Merge all the nested lists into a single list, using the given comparator
791
+ # block to determine the order which items should be shifted out of the nested
792
+ # lists and into the output list. The comparator should take 2 parameters and
793
+ # return 0, 1, or -1 if the first parameter is (respectively) equal to, greater
794
+ # than, or less than the second parameter. Whichever nested list's `#head` is
795
+ # determined to be "lowest" according to the comparator will be the first in
796
+ # the merged `List`.
797
+ #
798
+ # @example
799
+ # list_1 = Hamster::List[1, -3, -5]
800
+ # list_2 = Hamster::List[-2, 4, 6]
801
+ # Hamster::List[list_1, list_2].merge { |a,b| a.abs <=> b.abs }
802
+ # # => Hamster::List[1, -2, -3, 4, -5, 6]
803
+ #
804
+ # @return [List]
805
+ def merge(&comparator)
806
+ return merge_by unless block_given?
807
+ LazyList.new do
808
+ sorted = reject(&:empty?).sort do |a, b|
809
+ yield(a.head, b.head)
810
+ end
811
+ next EmptyList if sorted.empty?
812
+ Cons.new(sorted.head.head, sorted.tail.cons(sorted.head.tail).merge(&comparator))
310
813
  end
311
814
  end
312
815
 
313
- def elem_index(object)
314
- find_index { |item| item == object }
816
+ # Merge all the nested lists into a single list, using sort keys generated
817
+ # by mapping the items in the nested lists through the given block to determine the
818
+ # order which items should be shifted out of the nested lists and into the output
819
+ # list. Whichever nested list's `#head` has the "lowest" sort key (according to
820
+ # their natural order) will be the first in the merged `List`.
821
+ #
822
+ # @example
823
+ # list_1 = Hamster::List[1, -3, -5]
824
+ # list_2 = Hamster::List[-2, 4, 6]
825
+ # Hamster::List[list_1, list_2].merge_by { |x| x.abs }
826
+ # # => Hamster::List[1, -2, -3, 4, -5, 6]
827
+ #
828
+ # @return [List]
829
+ def merge_by(&transformer)
830
+ return merge_by { |item| item } unless block_given?
831
+ LazyList.new do
832
+ sorted = reject(&:empty?).sort_by do |list|
833
+ yield(list.head)
834
+ end
835
+ next EmptyList if sorted.empty?
836
+ Cons.new(sorted.head.head, sorted.tail.cons(sorted.head.tail).merge_by(&transformer))
837
+ end
315
838
  end
316
839
 
317
- def index(object = Undefined, &block)
318
- return elem_index(object) unless object.equal?(Undefined)
319
- find_index(&block)
840
+ # Return a randomly chosen element from this list.
841
+ # @return [Object]
842
+ def sample
843
+ at(rand(size))
844
+ end
845
+
846
+ # Return a new `List` with the given items inserted before the item at `index`.
847
+ #
848
+ # @example
849
+ # Hamster.list("A", "D", "E").insert(1, "B", "C") # => Hamster::List["A", "B", "C", "D", "E"]
850
+ #
851
+ # @param index [Integer] The index where the new items should go
852
+ # @param items [Array] The items to add
853
+ # @return [List]
854
+ def insert(index, *items)
855
+ if index == 0
856
+ return items.to_list.append(self)
857
+ elsif index > 0
858
+ LazyList.new do
859
+ Cons.new(head, tail.insert(index-1, *items))
860
+ end
861
+ else
862
+ raise IndexError if index < -size
863
+ insert(index + size, *items)
864
+ end
320
865
  end
321
866
 
322
- def find_indices(i = 0, &block)
323
- return EmptyList unless block_given?
324
- Stream.new do
325
- next EmptyList if empty?
326
- next Sequence.new(i, tail.find_indices(i + 1, &block)) if yield(head)
327
- tail.find_indices(i + 1, &block)
867
+ # Return a lazy list with all elements equal to `obj` removed. `#==` is used
868
+ # for testing equality.
869
+ #
870
+ # @example
871
+ # Hamster.list(:a, :b, :a, :a, :c).delete(:a) # => Hamster::List[:b, :c]
872
+ #
873
+ # @param obj [Object] The object to remove.
874
+ # @return [List]
875
+ def delete(obj)
876
+ list = self
877
+ list = list.tail while list.head == obj && !list.empty?
878
+ return EmptyList if list.empty?
879
+ LazyList.new { Cons.new(list.head, list.tail.delete(obj)) }
880
+ end
881
+
882
+ # Return a lazy list containing the same items, minus the one at `index`.
883
+ # If `index` is negative, it counts back from the end of the list.
884
+ #
885
+ # @example
886
+ # Hamster.list(1, 2, 3).delete_at(1) # => Hamster::List[1, 3]
887
+ # Hamster.list(1, 2, 3).delete_at(-1) # => Hamster::List[1, 2]
888
+ #
889
+ # @param index [Integer] The index of the item to remove
890
+ # @return [List]
891
+ def delete_at(index)
892
+ if index == 0
893
+ tail
894
+ elsif index < 0
895
+ index += size if index < 0
896
+ return self if index < 0
897
+ delete_at(index)
898
+ else
899
+ LazyList.new { Cons.new(head, tail.delete_at(index - 1)) }
328
900
  end
329
901
  end
330
902
 
331
- def elem_indices(object)
332
- find_indices { |item| item == object }
903
+ # Replace a range of indexes with the given object.
904
+ #
905
+ # @overload fill(obj)
906
+ # Return a new `List` of the same size, with every item set to `obj`.
907
+ # @overload fill(obj, start)
908
+ # Return a new `List` with all indexes from `start` to the end of the
909
+ # list set to `obj`.
910
+ # @overload fill(obj, start, length)
911
+ # Return a new `List` with `length` indexes, beginning from `start`,
912
+ # set to `obj`.
913
+ #
914
+ # @example
915
+ # list = Hamster.list("a", "b", "c", "d")
916
+ # list.fill("x") # => Hamster::List["x", "x", "x", "x"]
917
+ # list.fill("z", 2) # => Hamster::List["a", "b", "z", "z"]
918
+ # list.fill("y", 0, 2) # => Hamster::List["y", "y", "c", "d"]
919
+ #
920
+ # @return [List]
921
+ def fill(obj, index = 0, length = nil)
922
+ if index == 0
923
+ length ||= size
924
+ if length > 0
925
+ LazyList.new do
926
+ Cons.new(obj, tail.fill(obj, 0, length-1))
927
+ end
928
+ else
929
+ self
930
+ end
931
+ elsif index > 0
932
+ LazyList.new do
933
+ Cons.new(head, tail.fill(obj, index-1, length))
934
+ end
935
+ else
936
+ raise IndexError if index < -size
937
+ fill(obj, index + size, length)
938
+ end
333
939
  end
334
940
 
335
- def indices(object = Undefined, &block)
336
- return elem_indices(object) unless object.equal?(Undefined)
337
- find_indices(&block)
338
- end
941
+ # Yields all permutations of length `n` of the items in the list, and then
942
+ # returns `self`. If no length `n` is specified, permutations of the entire
943
+ # list will be yielded.
944
+ #
945
+ # There is no guarantee about which order the permutations will be yielded in.
946
+ #
947
+ # If no block is given, an `Enumerator` is returned instead.
948
+ #
949
+ # @example
950
+ # Hamster.list(1, 2, 3).permutation.to_a
951
+ # # => [Hamster::List[1, 2, 3],
952
+ # # Hamster::List[2, 1, 3],
953
+ # # Hamster::List[2, 3, 1],
954
+ # # Hamster::List[1, 3, 2],
955
+ # # Hamster::List[3, 1, 2],
956
+ # # Hamster::List[3, 2, 1]]
957
+ #
958
+ # @return [self, Enumerator]
959
+ def permutation(length = size, &block)
960
+ return enum_for(:permutation, length) if not block_given?
961
+ if length == 0
962
+ yield EmptyList
963
+ elsif length == 1
964
+ each { |obj| yield Cons.new(obj, EmptyList) }
965
+ elsif not empty?
966
+ if length < size
967
+ tail.permutation(length, &block)
968
+ end
339
969
 
340
- def merge(&comparator)
341
- return merge_by unless block_given?
342
- Stream.new do
343
- sorted = remove(&:empty?).sort do |a, b|
344
- yield(a.head, b.head)
970
+ tail.permutation(length-1) do |p|
971
+ 0.upto(length-1) do |i|
972
+ left,right = p.split_at(i)
973
+ yield left.append(right.cons(head))
974
+ end
345
975
  end
346
- next EmptyList if sorted.empty?
347
- Sequence.new(sorted.head.head, sorted.tail.cons(sorted.head.tail).merge(&comparator))
348
976
  end
977
+ self
349
978
  end
350
979
 
351
- def merge_by(&transformer)
352
- return merge_by { |item| item } unless block_given?
353
- Stream.new do
354
- sorted = remove(&:empty?).sort_by do |list|
355
- yield(list.head)
980
+ # Yield every non-empty sublist to the given block. (The entire `List` also
981
+ # counts as one sublist.)
982
+ #
983
+ # @example
984
+ # Hamster.list(1, 2, 3).subsequences { |list| p list }
985
+ # # prints:
986
+ # # Hamster::List[1]
987
+ # # Hamster::List[1, 2]
988
+ # # Hamster::List[1, 2, 3]
989
+ # # Hamster::List[2]
990
+ # # Hamster::List[2, 3]
991
+ # # Hamster::List[3]
992
+ #
993
+ # @yield [sublist] One or more contiguous elements from this list
994
+ # @return [self]
995
+ def subsequences(&block)
996
+ return enum_for(:subsequences) if not block_given?
997
+ if not empty?
998
+ 1.upto(size) do |n|
999
+ yield take(n)
356
1000
  end
357
- next EmptyList if sorted.empty?
358
- Sequence.new(sorted.head.head, sorted.tail.cons(sorted.head.tail).merge_by(&transformer))
1001
+ tail.subsequences(&block)
359
1002
  end
1003
+ self
360
1004
  end
361
1005
 
1006
+ # Return 2 `List`s, the first containing all the elements for which the block
1007
+ # evaluates to true, the second containing the rest.
1008
+ #
1009
+ # @example
1010
+ # Hamster.list(1, 2, 3, 4, 5, 6).partition { |x| x.even? }
1011
+ # # => [Hamster::List[2, 4, 6], Hamster::List[1, 3, 5]]
1012
+ #
1013
+ # @return [List]
1014
+ def partition(&block)
1015
+ return enum_for(:partition) if not block_given?
1016
+ partitioner = Partitioner.new(self, block)
1017
+ mutex = Mutex.new
1018
+ [Partitioned.new(partitioner, partitioner.left, mutex),
1019
+ Partitioned.new(partitioner, partitioner.right, mutex)].freeze
1020
+ end
1021
+
1022
+ # Return true if `other` has the same type and contents as this `Hash`.
1023
+ #
1024
+ # @param other [Object] The collection to compare with
1025
+ # @return [Boolean]
362
1026
  def eql?(other)
363
1027
  list = self
364
1028
  loop do
@@ -371,57 +1035,96 @@ module Hamster
371
1035
  other = other.tail
372
1036
  end
373
1037
  end
374
- def_delegator :self, :eql?, :==
375
1038
 
1039
+ # See `Object#hash`
1040
+ # @return [Integer]
376
1041
  def hash
377
1042
  reduce(0) { |hash, item| (hash << 5) - hash + item.hash }
378
1043
  end
379
1044
 
1045
+ # Return `self`.
1046
+ # @return [List]
380
1047
  def dup
381
1048
  self
382
1049
  end
383
- def_delegator :self, :dup, :clone
1050
+ alias :clone :dup
384
1051
 
1052
+ # Return `self`.
1053
+ # @return [List]
385
1054
  def to_list
386
1055
  self
387
1056
  end
388
1057
 
389
- def to_set
390
- reduce(EmptySet) { |set, item| set.add(item) }
391
- end
392
-
1058
+ # Return the contents of this `List` as a programmer-readable `String`. If all the
1059
+ # items in the list are serializable as Ruby literal strings, the returned string can
1060
+ # be passed to `eval` to reconstitute an equivalent `List`.
1061
+ #
1062
+ # @return [String]
393
1063
  def inspect
394
- to_a.inspect
1064
+ result = "Hamster::List["
1065
+ each_with_index { |obj, i| result << ', ' if i > 0; result << obj.inspect }
1066
+ result << "]"
1067
+ end
1068
+
1069
+ # Allows this `List` to be printed at the `pry` console, or using `pp` (from the
1070
+ # Ruby standard library), in a way which takes the amount of horizontal space on
1071
+ # the screen into account, and which indents nested structures to make them easier
1072
+ # to read.
1073
+ #
1074
+ # @private
1075
+ def pretty_print(pp)
1076
+ pp.group(1, "Hamster::List[", "]") do
1077
+ pp.breakable ''
1078
+ pp.seplist(self) { |obj| obj.pretty_print(pp) }
1079
+ end
395
1080
  end
396
1081
 
1082
+ # @private
397
1083
  def respond_to?(name, include_private = false)
398
- super || CADR === name.to_s
1084
+ super || !!name.to_s.match(CADR)
1085
+ end
1086
+
1087
+ # Return `true` if the size of this list can be obtained in constant time (without
1088
+ # traversing the list).
1089
+ # @return [Integer]
1090
+ def cached_size?
1091
+ false
399
1092
  end
400
1093
 
401
1094
  private
402
1095
 
403
1096
  def method_missing(name, *args, &block)
404
- return accessor($1) if CADR === name.to_s
405
- super
406
- end
407
-
408
- # Perform compositions of <tt>car</tt> and <tt>cdr</tt> operations. Their names consist of a 'c', followed by at
409
- # least one 'a' or 'd', and finally an 'r'. The series of 'a's and 'd's in each function's name is chosen to
410
- # identify the series of car and cdr operations that is performed by the function. The order in which the 'a's and
411
- # 'd's appear is the inverse of the order in which the corresponding operations are performed.
412
- def accessor(sequence)
413
- sequence.reverse.each_char.reduce(self) do |memo, char|
414
- case char
415
- when "a" then memo.head
416
- when "d" then memo.tail
417
- end
1097
+ if name.to_s.match(CADR)
1098
+ # Perform compositions of car and cdr operations. Their names consist of a 'c',
1099
+ # followed by at least one 'a' or 'd', and finally an 'r'. The series of 'a's and
1100
+ # 'd's in the method name identify the series of car and cdr operations performed.
1101
+ # The order in which the 'a's and 'd's appear is the inverse of the order in which
1102
+ # the corresponding operations are performed.
1103
+ code = "def #{name}; self."
1104
+ code << Regexp.last_match[1].reverse.chars.map do |char|
1105
+ {'a' => 'head', 'd' => 'tail'}[char]
1106
+ end.join('.')
1107
+ code << '; end'
1108
+ List.class_eval(code)
1109
+ send(name, *args, &block)
1110
+ else
1111
+ super
418
1112
  end
419
1113
  end
420
-
421
1114
  end
422
1115
 
423
- class Sequence
424
-
1116
+ # The basic building block for constructing lists
1117
+ #
1118
+ # A Cons, also known as a "cons cell", has a "head" and a "tail", where
1119
+ # the head is an element in the list, and the tail is a reference to the
1120
+ # rest of the list. This way a singly linked list can be constructed, with
1121
+ # each `Cons` holding a single element and a pointer to the next
1122
+ # `Cons`.
1123
+ #
1124
+ # The last `Cons` instance in the chain has the {EmptyList} as its tail.
1125
+ #
1126
+ # @private
1127
+ class Cons
425
1128
  include List
426
1129
 
427
1130
  attr_reader :head, :tail
@@ -429,63 +1132,292 @@ module Hamster
429
1132
  def initialize(head, tail = EmptyList)
430
1133
  @head = head
431
1134
  @tail = tail
1135
+ @size = tail.cached_size? ? tail.size + 1 : nil
432
1136
  end
433
1137
 
434
1138
  def empty?
435
1139
  false
436
1140
  end
437
1141
 
1142
+ def size
1143
+ @size ||= super
1144
+ end
1145
+ alias :length :size
1146
+
1147
+ def cached_size?
1148
+ @size != nil
1149
+ end
438
1150
  end
439
1151
 
440
- class Stream
1152
+ # A `LazyList` takes a block that returns a `List`, i.e. an object that responds
1153
+ # to `#head`, `#tail` and `#empty?`. The list is only realized (i.e. the block is
1154
+ # only called) when one of these operations is performed.
1155
+ #
1156
+ # By returning a `Cons` that in turn has a {LazyList} as its tail, one can
1157
+ # construct infinite lazy lists.
1158
+ #
1159
+ # @private
1160
+ class LazyList
1161
+ include List
1162
+
1163
+ def initialize(&block)
1164
+ @head = block # doubles as storage for block while yet unrealized
1165
+ @tail = nil
1166
+ @atomic = Atomic.new(0) # haven't yet run block
1167
+ @size = nil
1168
+ end
1169
+
1170
+ def head
1171
+ realize if @atomic.get != 2
1172
+ @head
1173
+ end
1174
+ alias :first :head
1175
+
1176
+ def tail
1177
+ realize if @atomic.get != 2
1178
+ @tail
1179
+ end
441
1180
 
442
- extend Forwardable
1181
+ def empty?
1182
+ realize if @atomic.get != 2
1183
+ @size == 0
1184
+ end
1185
+
1186
+ def size
1187
+ @size ||= super
1188
+ end
1189
+ alias :length :size
1190
+
1191
+ def cached_size?
1192
+ @size != nil
1193
+ end
443
1194
 
1195
+ private
1196
+
1197
+ QUEUE = ConditionVariable.new
1198
+ MUTEX = Mutex.new
1199
+
1200
+ def realize
1201
+ while true
1202
+ # try to "claim" the right to run the block which realizes target
1203
+ if @atomic.compare_and_swap(0,1) # full memory barrier here
1204
+ begin
1205
+ list = @head.call
1206
+ if list.empty?
1207
+ @head, @tail, @size = nil, self, 0
1208
+ else
1209
+ @head, @tail = list.head, list.tail
1210
+ end
1211
+ rescue
1212
+ @atomic.set(0)
1213
+ MUTEX.synchronize { QUEUE.broadcast }
1214
+ raise
1215
+ end
1216
+ @atomic.set(2)
1217
+ MUTEX.synchronize { QUEUE.broadcast }
1218
+ return
1219
+ end
1220
+ # we failed to "claim" it, another thread must be running it
1221
+ if @atomic.get == 1 # another thread is running the block
1222
+ MUTEX.synchronize do
1223
+ # check value of @atomic again, in case another thread already changed it
1224
+ # *and* went past the call to QUEUE.broadcast before we got here
1225
+ QUEUE.wait(MUTEX) if @atomic.get == 1
1226
+ end
1227
+ elsif @atomic.get == 2 # another thread finished the block
1228
+ return
1229
+ end
1230
+ end
1231
+ end
1232
+ end
1233
+
1234
+ # Common behavior for other classes which implement various kinds of lazy lists
1235
+ # @private
1236
+ class Realizable
444
1237
  include List
445
1238
 
446
- def initialize(&block)
447
- @block = block
448
- @lock = Mutex.new
1239
+ def initialize
1240
+ @head, @tail, @size = Undefined, Undefined, nil
449
1241
  end
450
1242
 
451
- def_delegator :target, :head
452
- def_delegator :target, :tail
453
- def_delegator :target, :empty?
1243
+ def head
1244
+ realize if @head == Undefined
1245
+ @head
1246
+ end
1247
+ alias :first :head
454
1248
 
455
- protected
1249
+ def tail
1250
+ realize if @tail == Undefined
1251
+ @tail
1252
+ end
1253
+
1254
+ def empty?
1255
+ realize if @head == Undefined
1256
+ @size == 0
1257
+ end
456
1258
 
457
- def vivify
458
- @lock.synchronize do
459
- unless @block.nil?
460
- @target = @block.call
461
- @block = nil
1259
+ def size
1260
+ @size ||= super
1261
+ end
1262
+ alias :length :size
1263
+
1264
+ def cached_size?
1265
+ @size != nil
1266
+ end
1267
+
1268
+ def realized?
1269
+ @head != Undefined
1270
+ end
1271
+ end
1272
+
1273
+ # This class can divide a collection into 2 lazy lists, one of items
1274
+ # for which the block returns true, and another for false
1275
+ # At the same time, it guarantees the block will only be called ONCE for each item
1276
+ #
1277
+ # @private
1278
+ class Partitioner
1279
+ attr_reader :left, :right
1280
+ def initialize(list, block)
1281
+ @list, @block, @left, @right = list, block, [], []
1282
+ end
1283
+
1284
+ def next_item
1285
+ unless @list.empty?
1286
+ item = @list.head
1287
+ (@block.call(item) ? @left : @right) << item
1288
+ @list = @list.tail
1289
+ end
1290
+ end
1291
+
1292
+ def done?
1293
+ @list.empty?
1294
+ end
1295
+ end
1296
+
1297
+ # One of the lazy lists which gets its items from a Partitioner
1298
+ # @private
1299
+ class Partitioned < Realizable
1300
+ def initialize(partitioner, buffer, mutex)
1301
+ super()
1302
+ @partitioner, @buffer, @mutex = partitioner, buffer, mutex
1303
+ end
1304
+
1305
+ def realize
1306
+ @mutex.synchronize do
1307
+ return if @head != Undefined # another thread got ahead of us
1308
+ while true
1309
+ if !@buffer.empty?
1310
+ @head = @buffer.shift
1311
+ @tail = Partitioned.new(@partitioner, @buffer, @mutex)
1312
+ # don't hold onto references
1313
+ # tail will keep references alive until end of list is reached
1314
+ @partitioner, @buffer, @mutex = nil, nil, nil
1315
+ return
1316
+ elsif @partitioner.done?
1317
+ @head, @size, @tail = nil, 0, self
1318
+ @partitioner, @buffer, @mutex = nil, nil, nil # allow them to be GC'd
1319
+ return
1320
+ else
1321
+ @partitioner.next_item
1322
+ end
462
1323
  end
463
1324
  end
464
- @target
465
1325
  end
1326
+ end
466
1327
 
467
- private
1328
+ # This class can divide a list up into 2 lazy lists, one for the prefix of elements
1329
+ # for which the block returns true, and another for all the elements after that
1330
+ # It guarantees that the block will only be called ONCE for each item
1331
+ #
1332
+ # @private
1333
+ class Splitter
1334
+ attr_reader :left, :right
1335
+ def initialize(list, block)
1336
+ @list, @block, @left, @right = list, block, [], EmptyList
1337
+ end
1338
+
1339
+ def next_item
1340
+ unless @list.empty?
1341
+ item = @list.head
1342
+ if @block.call(item)
1343
+ @left << item
1344
+ @list = @list.tail
1345
+ else
1346
+ @right = @list
1347
+ @list = EmptyList
1348
+ end
1349
+ end
1350
+ end
1351
+
1352
+ def done?
1353
+ @list.empty?
1354
+ end
1355
+
1356
+ # @private
1357
+ class Left < Realizable
1358
+ def initialize(splitter, buffer, mutex)
1359
+ super()
1360
+ @splitter, @buffer, @mutex = splitter, buffer, mutex
1361
+ end
468
1362
 
469
- def target
470
- list = vivify
471
- while list.is_a?(Stream)
472
- list = list.vivify
1363
+ def realize
1364
+ @mutex.synchronize do
1365
+ return if @head != Undefined # another thread got ahead of us
1366
+ while true
1367
+ if !@buffer.empty?
1368
+ @head = @buffer.shift
1369
+ @tail = Left.new(@splitter, @buffer, @mutex)
1370
+ @splitter, @buffer, @mutex = nil, nil, nil
1371
+ return
1372
+ elsif @splitter.done?
1373
+ @head, @size, @tail = nil, 0, self
1374
+ @splitter, @buffer, @mutex = nil, nil, nil
1375
+ return
1376
+ else
1377
+ @splitter.next_item
1378
+ end
1379
+ end
1380
+ end
473
1381
  end
474
- list
475
1382
  end
476
1383
 
1384
+ # @private
1385
+ class Right < Realizable
1386
+ def initialize(splitter, mutex)
1387
+ super()
1388
+ @splitter, @mutex = splitter, mutex
1389
+ end
1390
+
1391
+ def realize
1392
+ @mutex.synchronize do
1393
+ return if @head != Undefined
1394
+ @splitter.next_item until @splitter.done?
1395
+ if @splitter.right.empty?
1396
+ @head, @size, @tail = nil, 0, self
1397
+ else
1398
+ @head, @tail = @splitter.right.head, @splitter.right.tail
1399
+ end
1400
+ @splitter, @mutex = nil, nil
1401
+ end
1402
+ end
1403
+ end
477
1404
  end
478
1405
 
1406
+ # A list without any elements. This is a singleton, since all empty lists are equivalent.
1407
+ #
479
1408
  module EmptyList
480
-
481
1409
  class << self
482
-
483
1410
  include List
484
1411
 
1412
+ # There is no first item in an empty list, so return `nil`.
1413
+ # @return [nil]
485
1414
  def head
486
1415
  nil
487
1416
  end
1417
+ alias :first :head
488
1418
 
1419
+ # There are no subsequent elements, so return an empty list.
1420
+ # @return [self]
489
1421
  def tail
490
1422
  self
491
1423
  end
@@ -494,8 +1426,16 @@ module Hamster
494
1426
  true
495
1427
  end
496
1428
 
497
- end
1429
+ # Return the number of items in this `List`.
1430
+ # @return [Integer]
1431
+ def size
1432
+ 0
1433
+ end
1434
+ alias :length :size
498
1435
 
1436
+ def cached_size?
1437
+ true
1438
+ end
1439
+ end
499
1440
  end
500
-
501
1441
  end