hamster 1.0.1.pre.rc3 → 2.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.
- checksums.yaml +4 -4
- data/lib/hamster.rb +2 -0
- data/lib/hamster/associable.rb +49 -0
- data/lib/hamster/core_ext/enumerable.rb +3 -13
- data/lib/hamster/core_ext/io.rb +1 -1
- data/lib/hamster/core_ext/struct.rb +9 -0
- data/lib/hamster/deque.rb +57 -38
- data/lib/hamster/enumerable.rb +14 -41
- data/lib/hamster/experimental/mutable_queue.rb +5 -8
- data/lib/hamster/experimental/mutable_set.rb +6 -7
- data/lib/hamster/hash.rb +301 -110
- data/lib/hamster/immutable.rb +1 -1
- data/lib/hamster/list.rb +479 -194
- data/lib/hamster/mutable_hash.rb +6 -7
- data/lib/hamster/nested.rb +78 -0
- data/lib/hamster/read_copy_update.rb +1 -1
- data/lib/hamster/set.rb +198 -88
- data/lib/hamster/sorted_set.rb +706 -261
- data/lib/hamster/trie.rb +134 -15
- data/lib/hamster/vector.rb +571 -140
- data/lib/hamster/version.rb +3 -1
- data/spec/lib/hamster/associable/associable_spec.rb +150 -0
- data/spec/lib/hamster/core_ext/array_spec.rb +1 -1
- data/spec/lib/hamster/core_ext/enumerable_spec.rb +2 -2
- data/spec/lib/hamster/core_ext/io_spec.rb +1 -1
- data/spec/lib/hamster/deque/clear_spec.rb +3 -3
- data/spec/lib/hamster/deque/construction_spec.rb +8 -8
- data/spec/lib/hamster/deque/copying_spec.rb +1 -1
- data/spec/lib/hamster/deque/dequeue_spec.rb +12 -4
- data/spec/lib/hamster/deque/empty_spec.rb +14 -16
- data/spec/lib/hamster/deque/enqueue_spec.rb +4 -4
- data/spec/lib/hamster/deque/first_spec.rb +18 -0
- data/spec/lib/hamster/deque/inspect_spec.rb +1 -1
- data/spec/lib/hamster/deque/last_spec.rb +9 -11
- data/spec/lib/hamster/deque/marshal_spec.rb +6 -6
- data/spec/lib/hamster/deque/new_spec.rb +5 -5
- data/spec/lib/hamster/deque/pop_spec.rb +15 -3
- data/spec/lib/hamster/deque/pretty_print_spec.rb +24 -0
- data/spec/lib/hamster/deque/push_spec.rb +37 -0
- data/spec/lib/hamster/deque/shift_spec.rb +30 -0
- data/spec/lib/hamster/deque/size_spec.rb +1 -1
- data/spec/lib/hamster/deque/to_a_spec.rb +2 -2
- data/spec/lib/hamster/deque/to_ary_spec.rb +1 -1
- data/spec/lib/hamster/deque/to_list_spec.rb +3 -3
- data/spec/lib/hamster/deque/unshift_spec.rb +8 -3
- data/spec/lib/hamster/experimental/mutable_set/add_qm_spec.rb +3 -3
- data/spec/lib/hamster/experimental/mutable_set/add_spec.rb +3 -3
- data/spec/lib/hamster/experimental/mutable_set/delete_qm_spec.rb +3 -3
- data/spec/lib/hamster/experimental/mutable_set/delete_spec.rb +3 -3
- data/spec/lib/hamster/hash/all_spec.rb +32 -34
- data/spec/lib/hamster/hash/any_spec.rb +34 -36
- data/spec/lib/hamster/hash/assoc_spec.rb +3 -3
- data/spec/lib/hamster/hash/clear_spec.rb +4 -4
- data/spec/lib/hamster/hash/construction_spec.rb +8 -8
- data/spec/lib/hamster/hash/copying_spec.rb +1 -1
- data/spec/lib/hamster/hash/default_proc_spec.rb +3 -3
- data/spec/lib/hamster/hash/delete_spec.rb +4 -4
- data/spec/lib/hamster/hash/each_spec.rb +3 -3
- data/spec/lib/hamster/hash/each_with_index_spec.rb +1 -1
- data/spec/lib/hamster/hash/empty_spec.rb +13 -15
- data/spec/lib/hamster/hash/eql_spec.rb +4 -4
- data/spec/lib/hamster/hash/except_spec.rb +7 -7
- data/spec/lib/hamster/hash/fetch_spec.rb +10 -10
- data/spec/lib/hamster/hash/find_spec.rb +2 -2
- data/spec/lib/hamster/hash/flat_map_spec.rb +4 -4
- data/spec/lib/hamster/hash/flatten_spec.rb +13 -13
- data/spec/lib/hamster/hash/get_spec.rb +7 -7
- data/spec/lib/hamster/hash/has_key_spec.rb +3 -3
- data/spec/lib/hamster/hash/has_value_spec.rb +4 -4
- data/spec/lib/hamster/hash/hash_spec.rb +5 -5
- data/spec/lib/hamster/hash/inspect_spec.rb +2 -2
- data/spec/lib/hamster/hash/invert_spec.rb +6 -6
- data/spec/lib/hamster/hash/key_spec.rb +2 -2
- data/spec/lib/hamster/hash/keys_spec.rb +2 -2
- data/spec/lib/hamster/hash/map_spec.rb +4 -4
- data/spec/lib/hamster/hash/marshal_spec.rb +2 -2
- data/spec/lib/hamster/hash/merge_spec.rb +62 -56
- data/spec/lib/hamster/hash/min_max_spec.rb +9 -13
- data/spec/lib/hamster/hash/new_spec.rb +6 -6
- data/spec/lib/hamster/hash/none_spec.rb +3 -3
- data/spec/lib/hamster/hash/partition_spec.rb +2 -2
- data/spec/lib/hamster/hash/put_spec.rb +29 -7
- data/spec/lib/hamster/hash/reduce_spec.rb +4 -4
- data/spec/lib/hamster/hash/{remove_spec.rb → reject_spec.rb} +7 -7
- data/spec/lib/hamster/hash/reverse_each_spec.rb +1 -1
- data/spec/lib/hamster/hash/{filter_spec.rb → select_spec.rb} +6 -6
- data/spec/lib/hamster/hash/size_spec.rb +3 -3
- data/spec/lib/hamster/hash/slice_spec.rb +4 -4
- data/spec/lib/hamster/hash/sort_spec.rb +2 -2
- data/spec/lib/hamster/hash/store_spec.rb +29 -7
- data/spec/lib/hamster/hash/take_spec.rb +2 -2
- data/spec/lib/hamster/hash/to_a_spec.rb +1 -1
- data/spec/lib/hamster/hash/to_hash_spec.rb +4 -4
- data/spec/lib/hamster/hash/values_at_spec.rb +3 -3
- data/spec/lib/hamster/hash/values_spec.rb +2 -2
- data/spec/lib/hamster/immutable/new_spec.rb +14 -0
- data/spec/lib/hamster/list/add_spec.rb +16 -10
- data/spec/lib/hamster/list/all_spec.rb +33 -35
- data/spec/lib/hamster/list/any_spec.rb +29 -31
- data/spec/lib/hamster/list/append_spec.rb +6 -6
- data/spec/lib/hamster/list/at_spec.rb +1 -1
- data/spec/lib/hamster/list/break_spec.rb +4 -4
- data/spec/lib/hamster/list/cadr_spec.rb +9 -9
- data/spec/lib/hamster/list/chunk_spec.rb +5 -5
- data/spec/lib/hamster/list/clear_spec.rb +3 -3
- data/spec/lib/hamster/list/combination_spec.rb +3 -3
- data/spec/lib/hamster/list/compact_spec.rb +3 -3
- data/spec/lib/hamster/list/compare_spec.rb +3 -3
- data/spec/lib/hamster/list/cons_spec.rb +15 -17
- data/spec/lib/hamster/list/construction_spec.rb +20 -27
- data/spec/lib/hamster/list/copying_spec.rb +1 -1
- data/spec/lib/hamster/list/count_spec.rb +1 -1
- data/spec/lib/hamster/list/cycle_spec.rb +4 -4
- data/spec/lib/hamster/list/delete_at_spec.rb +4 -4
- data/spec/lib/hamster/list/drop_spec.rb +3 -3
- data/spec/lib/hamster/list/drop_while_spec.rb +3 -3
- data/spec/lib/hamster/list/each_slice_spec.rb +5 -5
- data/spec/lib/hamster/list/each_spec.rb +26 -28
- data/spec/lib/hamster/list/each_with_index_spec.rb +1 -1
- data/spec/lib/hamster/list/empty_spec.rb +13 -15
- data/spec/lib/hamster/list/eql_spec.rb +21 -21
- data/spec/lib/hamster/list/fill_spec.rb +8 -8
- data/spec/lib/hamster/list/find_all_spec.rb +3 -3
- data/spec/lib/hamster/list/find_index_spec.rb +1 -1
- data/spec/lib/hamster/list/find_spec.rb +1 -1
- data/spec/lib/hamster/list/flat_map_spec.rb +2 -2
- data/spec/lib/hamster/list/flatten_spec.rb +5 -5
- data/spec/lib/hamster/list/grep_spec.rb +4 -4
- data/spec/lib/hamster/list/group_by_spec.rb +6 -6
- data/spec/lib/hamster/list/hash_spec.rb +2 -2
- data/spec/lib/hamster/list/head_spec.rb +1 -1
- data/spec/lib/hamster/list/include_spec.rb +2 -2
- data/spec/lib/hamster/list/index_spec.rb +38 -0
- data/spec/lib/hamster/list/indices_spec.rb +62 -0
- data/spec/lib/hamster/list/init_spec.rb +3 -3
- data/spec/lib/hamster/list/inits_spec.rb +3 -3
- data/spec/lib/hamster/list/insert_spec.rb +1 -1
- data/spec/lib/hamster/list/inspect_spec.rb +1 -1
- data/spec/lib/hamster/list/intersperse_spec.rb +3 -3
- data/spec/lib/hamster/list/join_spec.rb +5 -5
- data/spec/lib/hamster/list/last_spec.rb +1 -1
- data/spec/lib/hamster/list/ltlt_spec.rb +20 -0
- data/spec/lib/hamster/list/map_spec.rb +4 -4
- data/spec/lib/hamster/list/maximum_spec.rb +24 -26
- data/spec/lib/hamster/list/merge_by_spec.rb +10 -10
- data/spec/lib/hamster/list/merge_spec.rb +10 -10
- data/spec/lib/hamster/list/minimum_spec.rb +24 -26
- data/spec/lib/hamster/list/multithreading_spec.rb +6 -6
- data/spec/lib/hamster/list/none_spec.rb +5 -5
- data/spec/lib/hamster/list/one_spec.rb +5 -5
- data/spec/lib/hamster/list/partition_spec.rb +8 -8
- data/spec/lib/hamster/list/permutation_spec.rb +8 -8
- data/spec/lib/hamster/list/pop_spec.rb +3 -3
- data/spec/lib/hamster/list/product_spec.rb +1 -1
- data/spec/lib/hamster/list/reduce_spec.rb +5 -48
- data/spec/lib/hamster/list/{remove_spec.rb → reject_spec.rb} +4 -4
- data/spec/lib/hamster/list/reverse_spec.rb +3 -3
- data/spec/lib/hamster/list/rotate_spec.rb +7 -7
- data/spec/lib/hamster/list/sample_spec.rb +1 -1
- data/spec/lib/hamster/list/select_spec.rb +3 -3
- data/spec/lib/hamster/list/size_spec.rb +1 -1
- data/spec/lib/hamster/list/slice_spec.rb +123 -123
- data/spec/lib/hamster/list/sorting_spec.rb +5 -5
- data/spec/lib/hamster/list/span_spec.rb +5 -5
- data/spec/lib/hamster/list/split_at_spec.rb +4 -4
- data/spec/lib/hamster/list/subsequences_spec.rb +1 -1
- data/spec/lib/hamster/list/sum_spec.rb +1 -1
- data/spec/lib/hamster/list/tail_spec.rb +4 -4
- data/spec/lib/hamster/list/tails_spec.rb +3 -3
- data/spec/lib/hamster/list/take_spec.rb +3 -3
- data/spec/lib/hamster/list/take_while_spec.rb +4 -4
- data/spec/lib/hamster/list/to_a_spec.rb +2 -2
- data/spec/lib/hamster/list/to_ary_spec.rb +1 -1
- data/spec/lib/hamster/list/to_list_spec.rb +1 -1
- data/spec/lib/hamster/list/to_set_spec.rb +1 -1
- data/spec/lib/hamster/list/union_spec.rb +4 -4
- data/spec/lib/hamster/list/uniq_spec.rb +23 -19
- data/spec/lib/hamster/list/zip_spec.rb +5 -5
- data/spec/lib/hamster/nested/construction_spec.rb +103 -0
- data/spec/lib/hamster/set/add_spec.rb +13 -11
- data/spec/lib/hamster/set/all_spec.rb +32 -34
- data/spec/lib/hamster/set/any_spec.rb +32 -34
- data/spec/lib/hamster/set/clear_spec.rb +3 -3
- data/spec/lib/hamster/set/compact_spec.rb +3 -3
- data/spec/lib/hamster/set/construction_spec.rb +3 -3
- data/spec/lib/hamster/set/copying_spec.rb +1 -1
- data/spec/lib/hamster/set/count_spec.rb +1 -1
- data/spec/lib/hamster/set/delete_spec.rb +8 -8
- data/spec/lib/hamster/set/difference_spec.rb +8 -8
- data/spec/lib/hamster/set/disjoint_spec.rb +1 -1
- data/spec/lib/hamster/set/each_spec.rb +2 -2
- data/spec/lib/hamster/set/empty_spec.rb +15 -17
- data/spec/lib/hamster/set/eqeq_spec.rb +3 -3
- data/spec/lib/hamster/set/eql_spec.rb +3 -3
- data/spec/lib/hamster/set/exclusion_spec.rb +7 -7
- data/spec/lib/hamster/set/find_spec.rb +2 -2
- data/spec/lib/hamster/set/first_spec.rb +29 -0
- data/spec/lib/hamster/set/flatten_spec.rb +9 -9
- data/spec/lib/hamster/set/grep_spec.rb +1 -1
- data/spec/lib/hamster/set/group_by_spec.rb +12 -12
- data/spec/lib/hamster/set/hash_spec.rb +3 -3
- data/spec/lib/hamster/set/include_spec.rb +8 -8
- data/spec/lib/hamster/set/inspect_spec.rb +2 -2
- data/spec/lib/hamster/set/intersect_spec.rb +1 -1
- data/spec/lib/hamster/set/intersection_spec.rb +13 -13
- data/spec/lib/hamster/set/join_spec.rb +6 -6
- data/spec/lib/hamster/set/map_spec.rb +7 -7
- data/spec/lib/hamster/set/marshal_spec.rb +2 -2
- data/spec/lib/hamster/set/maximum_spec.rb +22 -24
- data/spec/lib/hamster/set/minimum_spec.rb +22 -24
- data/spec/lib/hamster/set/new_spec.rb +5 -5
- data/spec/lib/hamster/set/none_spec.rb +5 -5
- data/spec/lib/hamster/set/one_spec.rb +6 -6
- data/spec/lib/hamster/set/partition_spec.rb +5 -5
- data/spec/lib/hamster/set/product_spec.rb +2 -2
- data/spec/lib/hamster/set/reduce_spec.rb +5 -5
- data/spec/lib/hamster/set/{remove_spec.rb → reject_spec.rb} +6 -6
- data/spec/lib/hamster/set/reverse_each_spec.rb +1 -1
- data/spec/lib/hamster/set/sample_spec.rb +1 -1
- data/spec/lib/hamster/set/{filter_spec.rb → select_spec.rb} +11 -11
- data/spec/lib/hamster/set/size_spec.rb +1 -1
- data/spec/lib/hamster/set/sorting_spec.rb +16 -5
- data/spec/lib/hamster/set/subset_spec.rb +2 -2
- data/spec/lib/hamster/set/sum_spec.rb +2 -2
- data/spec/lib/hamster/set/superset_spec.rb +2 -2
- data/spec/lib/hamster/set/to_a_spec.rb +2 -2
- data/spec/lib/hamster/set/to_list_spec.rb +2 -2
- data/spec/lib/hamster/set/to_set_spec.rb +1 -1
- data/spec/lib/hamster/set/union_spec.rb +23 -14
- data/spec/lib/hamster/sorted_set/above_spec.rb +11 -11
- data/spec/lib/hamster/sorted_set/add_spec.rb +8 -8
- data/spec/lib/hamster/sorted_set/at_spec.rb +1 -1
- data/spec/lib/hamster/sorted_set/below_spec.rb +11 -11
- data/spec/lib/hamster/sorted_set/between_spec.rb +11 -11
- data/spec/lib/hamster/sorted_set/clear_spec.rb +11 -2
- data/spec/lib/hamster/sorted_set/copying_spec.rb +21 -0
- data/spec/lib/hamster/sorted_set/delete_at_spec.rb +4 -4
- data/spec/lib/hamster/sorted_set/delete_spec.rb +21 -12
- data/spec/lib/hamster/sorted_set/difference_spec.rb +2 -2
- data/spec/lib/hamster/sorted_set/disjoint_spec.rb +1 -1
- data/spec/lib/hamster/sorted_set/drop_spec.rb +30 -3
- data/spec/lib/hamster/sorted_set/drop_while_spec.rb +4 -4
- data/spec/lib/hamster/sorted_set/each_spec.rb +16 -18
- data/spec/lib/hamster/sorted_set/empty_spec.rb +12 -14
- data/spec/lib/hamster/sorted_set/eql_spec.rb +5 -5
- data/spec/lib/hamster/sorted_set/exclusion_spec.rb +1 -1
- data/spec/lib/hamster/sorted_set/fetch_spec.rb +1 -1
- data/spec/lib/hamster/sorted_set/find_index_spec.rb +10 -2
- data/spec/lib/hamster/sorted_set/first_spec.rb +10 -12
- data/spec/lib/hamster/sorted_set/from_spec.rb +11 -11
- data/spec/lib/hamster/sorted_set/group_by_spec.rb +10 -10
- data/spec/lib/hamster/sorted_set/include_spec.rb +2 -2
- data/spec/lib/hamster/sorted_set/inspect_spec.rb +1 -1
- data/spec/lib/hamster/sorted_set/intersect_spec.rb +1 -1
- data/spec/lib/hamster/sorted_set/intersection_spec.rb +3 -3
- data/spec/lib/hamster/sorted_set/last_spec.rb +1 -1
- data/spec/lib/hamster/sorted_set/map_spec.rb +13 -5
- data/spec/lib/hamster/sorted_set/marshal_spec.rb +3 -3
- data/spec/lib/hamster/sorted_set/maximum_spec.rb +37 -0
- data/spec/lib/hamster/sorted_set/minimum_spec.rb +11 -13
- data/spec/lib/hamster/sorted_set/new_spec.rb +23 -3
- data/spec/lib/hamster/sorted_set/reverse_each_spec.rb +2 -2
- data/spec/lib/hamster/sorted_set/{filter_spec.rb → select_spec.rb} +10 -10
- data/spec/lib/hamster/sorted_set/size_spec.rb +1 -1
- data/spec/lib/hamster/sorted_set/slice_spec.rb +158 -142
- data/spec/lib/hamster/sorted_set/sorting_spec.rb +3 -3
- data/spec/lib/hamster/sorted_set/subset_spec.rb +2 -2
- data/spec/lib/hamster/sorted_set/superset_spec.rb +2 -2
- data/spec/lib/hamster/sorted_set/take_spec.rb +32 -3
- data/spec/lib/hamster/sorted_set/take_while_spec.rb +4 -4
- data/spec/lib/hamster/sorted_set/to_set_spec.rb +1 -1
- data/spec/lib/hamster/sorted_set/union_spec.rb +2 -2
- data/spec/lib/hamster/sorted_set/up_to_spec.rb +12 -11
- data/spec/lib/hamster/sorted_set/values_at_spec.rb +6 -6
- data/spec/lib/hamster/vector/add_spec.rb +3 -3
- data/spec/lib/hamster/vector/any_spec.rb +1 -1
- data/spec/lib/hamster/vector/assoc_spec.rb +11 -1
- data/spec/lib/hamster/vector/bsearch_spec.rb +10 -2
- data/spec/lib/hamster/vector/clear_spec.rb +3 -3
- data/spec/lib/hamster/vector/combination_spec.rb +4 -4
- data/spec/lib/hamster/vector/compact_spec.rb +2 -2
- data/spec/lib/hamster/vector/compare_spec.rb +3 -3
- data/spec/lib/hamster/vector/concat_spec.rb +2 -2
- data/spec/lib/hamster/vector/copying_spec.rb +1 -1
- data/spec/lib/hamster/vector/delete_at_spec.rb +8 -8
- data/spec/lib/hamster/vector/delete_spec.rb +2 -2
- data/spec/lib/hamster/vector/drop_spec.rb +10 -3
- data/spec/lib/hamster/vector/drop_while_spec.rb +5 -5
- data/spec/lib/hamster/vector/each_index_spec.rb +2 -2
- data/spec/lib/hamster/vector/each_spec.rb +27 -29
- data/spec/lib/hamster/vector/each_with_index_spec.rb +2 -2
- data/spec/lib/hamster/vector/empty_spec.rb +11 -13
- data/spec/lib/hamster/vector/eql_spec.rb +6 -6
- data/spec/lib/hamster/vector/fetch_spec.rb +1 -1
- data/spec/lib/hamster/vector/fill_spec.rb +9 -9
- data/spec/lib/hamster/vector/first_spec.rb +10 -12
- data/spec/lib/hamster/vector/flat_map_spec.rb +51 -0
- data/spec/lib/hamster/vector/flatten_spec.rb +15 -0
- data/spec/lib/hamster/vector/get_spec.rb +4 -4
- data/spec/lib/hamster/vector/group_by_spec.rb +12 -12
- data/spec/lib/hamster/vector/include_spec.rb +2 -2
- data/spec/lib/hamster/vector/insert_spec.rb +2 -2
- data/spec/lib/hamster/vector/inspect_spec.rb +1 -1
- data/spec/lib/hamster/vector/join_spec.rb +5 -5
- data/spec/lib/hamster/vector/last_spec.rb +1 -1
- data/spec/lib/hamster/vector/length_spec.rb +1 -1
- data/spec/lib/hamster/vector/ltlt_spec.rb +2 -2
- data/spec/lib/hamster/vector/map_spec.rb +5 -5
- data/spec/lib/hamster/vector/marshal_spec.rb +2 -2
- data/spec/lib/hamster/vector/maximum_spec.rb +20 -22
- data/spec/lib/hamster/vector/minimum_spec.rb +20 -22
- data/spec/lib/hamster/vector/multiply_spec.rb +4 -4
- data/spec/lib/hamster/vector/partition_spec.rb +5 -5
- data/spec/lib/hamster/vector/permutation_spec.rb +4 -4
- data/spec/lib/hamster/vector/pop_spec.rb +3 -3
- data/spec/lib/hamster/vector/product_spec.rb +10 -10
- data/spec/lib/hamster/vector/put_spec.rb +175 -0
- data/spec/lib/hamster/vector/reduce_spec.rb +5 -57
- data/spec/lib/hamster/vector/{remove_spec.rb → reject_spec.rb} +4 -4
- data/spec/lib/hamster/vector/repeated_combination_spec.rb +4 -4
- data/spec/lib/hamster/vector/repeated_permutation_spec.rb +6 -6
- data/spec/lib/hamster/vector/reverse_each_spec.rb +1 -1
- data/spec/lib/hamster/vector/reverse_spec.rb +1 -1
- data/spec/lib/hamster/vector/rindex_spec.rb +1 -1
- data/spec/lib/hamster/vector/rotate_spec.rb +9 -9
- data/spec/lib/hamster/vector/sample_spec.rb +1 -1
- data/spec/lib/hamster/vector/{filter_spec.rb → select_spec.rb} +8 -8
- data/spec/lib/hamster/vector/set_spec.rb +12 -141
- data/spec/lib/hamster/vector/shift_spec.rb +3 -3
- data/spec/lib/hamster/vector/shuffle_spec.rb +2 -2
- data/spec/lib/hamster/vector/slice_spec.rb +137 -137
- data/spec/lib/hamster/vector/sorting_spec.rb +5 -5
- data/spec/lib/hamster/vector/sum_spec.rb +1 -1
- data/spec/lib/hamster/vector/take_spec.rb +17 -3
- data/spec/lib/hamster/vector/take_while_spec.rb +4 -4
- data/spec/lib/hamster/vector/to_a_spec.rb +1 -1
- data/spec/lib/hamster/vector/to_ary_spec.rb +1 -1
- data/spec/lib/hamster/vector/to_list_spec.rb +2 -1
- data/spec/lib/hamster/vector/to_set_spec.rb +1 -1
- data/spec/lib/hamster/vector/uniq_spec.rb +27 -6
- data/spec/lib/hamster/vector/unshift_spec.rb +3 -3
- data/spec/lib/hamster/vector/values_at_spec.rb +6 -6
- data/spec/lib/hamster/vector/zip_spec.rb +2 -2
- data/spec/lib/load_spec.rb +42 -0
- data/spec/spec_helper.rb +25 -0
- metadata +85 -48
- data/spec/lib/hamster/deque/head_spec.rb +0 -20
- data/spec/lib/hamster/hash/uniq_spec.rb +0 -14
- data/spec/lib/hamster/list/elem_index_spec.rb +0 -36
- data/spec/lib/hamster/list/elem_indices_spec.rb +0 -31
- data/spec/lib/hamster/list/filter_spec.rb +0 -71
- data/spec/lib/hamster/list/find_indices_spec.rb +0 -37
- data/spec/lib/hamster/set/foreach_spec.rb +0 -40
- data/spec/lib/hamster/set/head_spec.rb +0 -31
- data/spec/lib/hamster/set/uniq_spec.rb +0 -14
- data/spec/lib/hamster/sorted_set/construction_spec.rb +0 -29
- data/spec/lib/hamster/vector/exist_spec.rb +0 -70
- data/spec/lib/hamster/vector/exists_spec.rb +0 -70
data/lib/hamster/immutable.rb
CHANGED
data/lib/hamster/list.rb
CHANGED
@@ -1,27 +1,14 @@
|
|
1
|
-
require "forwardable"
|
2
1
|
require "thread"
|
3
|
-
require "atomic"
|
4
2
|
require "set"
|
3
|
+
require "concurrent/atomics"
|
5
4
|
|
6
|
-
require "hamster/core_ext/enumerable"
|
7
5
|
require "hamster/undefined"
|
8
6
|
require "hamster/enumerable"
|
7
|
+
require "hamster/hash"
|
9
8
|
require "hamster/set"
|
10
9
|
|
11
10
|
module Hamster
|
12
11
|
class << self
|
13
|
-
extend Forwardable
|
14
|
-
|
15
|
-
# Create a list containing the given items.
|
16
|
-
#
|
17
|
-
# @example
|
18
|
-
# list = Hamster.list(:a, :b, :c)
|
19
|
-
# # => [:a, :b, :c]
|
20
|
-
#
|
21
|
-
# @return [List]
|
22
|
-
def list(*items)
|
23
|
-
items.to_list
|
24
|
-
end
|
25
12
|
|
26
13
|
# Create a lazy, infinite list.
|
27
14
|
#
|
@@ -29,7 +16,7 @@ module Hamster
|
|
29
16
|
#
|
30
17
|
# @example
|
31
18
|
# Hamster.stream { :hello }.take(3)
|
32
|
-
# # => [:hello, :hello, :hello]
|
19
|
+
# # => Hamster::List[:hello, :hello, :hello]
|
33
20
|
#
|
34
21
|
# @return [List]
|
35
22
|
def stream(&block)
|
@@ -41,7 +28,7 @@ module Hamster
|
|
41
28
|
#
|
42
29
|
# @example
|
43
30
|
# Hamster.interval(5,9)
|
44
|
-
# # => [5, 6, 7, 8, 9]
|
31
|
+
# # => Hamster::List[5, 6, 7, 8, 9]
|
45
32
|
#
|
46
33
|
# @param from [Integer] Start value, inclusive
|
47
34
|
# @param to [Integer] End value, inclusive
|
@@ -50,13 +37,12 @@ module Hamster
|
|
50
37
|
return EmptyList if from > to
|
51
38
|
interval_exclusive(from, to.next)
|
52
39
|
end
|
53
|
-
def_delegator :self, :interval, :range
|
54
40
|
|
55
41
|
# Create an infinite list repeating the same item indefinitely
|
56
42
|
#
|
57
43
|
# @example
|
58
44
|
# Hamster.repeat(:chunky).take(4)
|
59
|
-
# => [:chunky, :chunky, :chunky, :chunky]
|
45
|
+
# => Hamster::List[:chunky, :chunky, :chunky, :chunky]
|
60
46
|
#
|
61
47
|
# @return [List]
|
62
48
|
def repeat(item)
|
@@ -66,8 +52,8 @@ module Hamster
|
|
66
52
|
# Create a list that contains a given item a fixed number of times
|
67
53
|
#
|
68
54
|
# @example
|
69
|
-
# Hamster.replicate(3
|
70
|
-
# #=> [:hamster, :hamster, :hamster]
|
55
|
+
# Hamster.replicate(3, :hamster)
|
56
|
+
# #=> Hamster::List[:hamster, :hamster, :hamster]
|
71
57
|
#
|
72
58
|
# @return [List]
|
73
59
|
def replicate(number, item)
|
@@ -79,18 +65,18 @@ module Hamster
|
|
79
65
|
#
|
80
66
|
# @example
|
81
67
|
# Hamster.iterate(0) { |i| i.next }.take(5)
|
82
|
-
# # => [0, 1, 2, 3, 4]
|
68
|
+
# # => Hamster::List[0, 1, 2, 3, 4]
|
83
69
|
#
|
84
|
-
# @param
|
85
|
-
# @yieldparam [Object] The previous value
|
70
|
+
# @param [Object] item Starting value
|
71
|
+
# @yieldparam [Object] previous The previous value
|
86
72
|
# @yieldreturn [Object] The next value
|
87
73
|
# @return [List]
|
88
74
|
def iterate(item, &block)
|
89
75
|
LazyList.new { Cons.new(item, iterate(yield(item), &block)) }
|
90
76
|
end
|
91
77
|
|
92
|
-
# Turn an Enumerator into a `Hamster::List`. The result is a lazy
|
93
|
-
# where the values are memoized as they are generated.
|
78
|
+
# Turn an `Enumerator` into a `Hamster::List`. The result is a lazy
|
79
|
+
# collection where the values are memoized as they are generated.
|
94
80
|
#
|
95
81
|
# If your code uses multiple threads, you need to make sure that the returned
|
96
82
|
# lazy collection is realized on a single thread only. Otherwise, a `FiberError`
|
@@ -121,29 +107,58 @@ module Hamster
|
|
121
107
|
end
|
122
108
|
end
|
123
109
|
|
124
|
-
# A `List` can be constructed with {
|
110
|
+
# A `List` can be constructed with {List.[] List[]}, or {Enumerable#to_list}.
|
125
111
|
# It consists of a *head* (the first element) and a *tail* (which itself is also
|
126
112
|
# a `List`, containing all the remaining elements).
|
127
113
|
#
|
128
|
-
# This is a singly linked list. Prepending to the list with {List#
|
114
|
+
# This is a singly linked list. Prepending to the list with {List#add} runs
|
129
115
|
# in constant time. Traversing the list from front to back is efficient,
|
130
116
|
# however, indexed access runs in linear time because the list needs to be
|
131
117
|
# traversed to find the element.
|
132
118
|
#
|
133
119
|
module List
|
134
|
-
extend Forwardable
|
135
120
|
include Enumerable
|
136
121
|
|
137
122
|
# @private
|
138
123
|
CADR = /^c([ad]+)r$/
|
139
124
|
|
140
|
-
def_delegator :self, :head, :first
|
141
|
-
def_delegator :self, :empty?, :null?
|
142
|
-
|
143
125
|
# Create a new `List` populated with the given items.
|
144
|
-
#
|
126
|
+
#
|
127
|
+
# @example
|
128
|
+
# list = Hamster::List[:a, :b, :c]
|
129
|
+
# # => Hamster::List[:a, :b, :c]
|
130
|
+
#
|
131
|
+
# @return [List]
|
145
132
|
def self.[](*items)
|
146
|
-
items
|
133
|
+
from_enum(items)
|
134
|
+
end
|
135
|
+
|
136
|
+
# Return an empty `List`.
|
137
|
+
#
|
138
|
+
# @return [List]
|
139
|
+
def self.empty
|
140
|
+
EmptyList
|
141
|
+
end
|
142
|
+
|
143
|
+
# This method exists distinct from `.[]` since it is ~30% faster
|
144
|
+
# than splatting the argument.
|
145
|
+
#
|
146
|
+
# Marking as private only because it was introduced for an internal
|
147
|
+
# refactoring. It could potentially be made public with a good name.
|
148
|
+
#
|
149
|
+
# @private
|
150
|
+
def self.from_enum(items)
|
151
|
+
# use destructive operations to build up a new list, like Common Lisp's NCONC
|
152
|
+
# this is a very fast way to build up a linked list
|
153
|
+
list = tail = Hamster::Cons.allocate
|
154
|
+
items.each do |item|
|
155
|
+
new_node = Hamster::Cons.allocate
|
156
|
+
new_node.instance_variable_set(:@head, item)
|
157
|
+
tail.instance_variable_set(:@tail, new_node)
|
158
|
+
tail = new_node
|
159
|
+
end
|
160
|
+
tail.instance_variable_set(:@tail, Hamster::EmptyList)
|
161
|
+
list.tail
|
147
162
|
end
|
148
163
|
|
149
164
|
# Return the number of items in this `List`.
|
@@ -160,30 +175,41 @@ module Hamster
|
|
160
175
|
end
|
161
176
|
result
|
162
177
|
end
|
163
|
-
|
178
|
+
alias :length :size
|
164
179
|
|
165
|
-
# Create a new `List` with `item` added at the front.
|
180
|
+
# Create a new `List` with `item` added at the front. This is a constant
|
181
|
+
# time operation.
|
182
|
+
#
|
183
|
+
# @example
|
184
|
+
# Hamster::List[:b, :c].add(:a)
|
185
|
+
# # => Hamster::List[:a, :b, :c]
|
186
|
+
#
|
166
187
|
# @param item [Object] The item to add
|
167
188
|
# @return [List]
|
168
|
-
def
|
189
|
+
def add(item)
|
169
190
|
Cons.new(item, self)
|
170
191
|
end
|
171
|
-
|
172
|
-
def_delegator :self, :cons, :conj
|
173
|
-
def_delegator :self, :cons, :conjoin
|
192
|
+
alias :cons :add
|
174
193
|
|
175
|
-
# Create a new `List` with `item` added at the end.
|
194
|
+
# Create a new `List` with `item` added at the end. This is much less efficient
|
195
|
+
# than adding items at the front.
|
196
|
+
#
|
197
|
+
# @example
|
198
|
+
# Hamster::List[:a, :b] << :c
|
199
|
+
# # => Hamster::List[:a, :b, :c]
|
200
|
+
#
|
176
201
|
# @param item [Object] The item to add
|
177
202
|
# @return [List]
|
178
|
-
def
|
179
|
-
append(
|
203
|
+
def <<(item)
|
204
|
+
append(List[item])
|
180
205
|
end
|
181
|
-
def_delegator :self, :add, :<<
|
182
206
|
|
183
207
|
# Call the given block once for each item in the list, passing each
|
184
|
-
# item from first to last successively to the block.
|
208
|
+
# item from first to last successively to the block. If no block is given,
|
209
|
+
# returns an `Enumerator`.
|
185
210
|
#
|
186
211
|
# @return [self]
|
212
|
+
# @yield [item]
|
187
213
|
def each
|
188
214
|
return to_enum unless block_given?
|
189
215
|
list = self
|
@@ -193,10 +219,15 @@ module Hamster
|
|
193
219
|
end
|
194
220
|
end
|
195
221
|
|
196
|
-
# Return a
|
197
|
-
# element in this `List`, transformed through the given block.
|
222
|
+
# Return a `List` in which each element is derived from the corresponding
|
223
|
+
# element in this `List`, transformed through the given block. If no block
|
224
|
+
# is given, returns an `Enumerator`.
|
198
225
|
#
|
199
|
-
# @
|
226
|
+
# @example
|
227
|
+
# Hamster::List[3, 2, 1].map { |e| e * e } # => Hamster::List[9, 4, 1]
|
228
|
+
#
|
229
|
+
# @return [List, Enumerator]
|
230
|
+
# @yield [item]
|
200
231
|
def map(&block)
|
201
232
|
return enum_for(:map) unless block_given?
|
202
233
|
LazyList.new do
|
@@ -204,42 +235,58 @@ module Hamster
|
|
204
235
|
Cons.new(yield(head), tail.map(&block))
|
205
236
|
end
|
206
237
|
end
|
207
|
-
|
238
|
+
alias :collect :map
|
208
239
|
|
209
|
-
# Return a
|
240
|
+
# Return a `List` which is realized by transforming each item into a `List`,
|
210
241
|
# and flattening the resulting lists.
|
211
242
|
#
|
243
|
+
# @example
|
244
|
+
# Hamster::List[1, 2, 3].flat_map { |x| Hamster::List[x, 100] }
|
245
|
+
# # => Hamster::List[1, 100, 2, 100, 3, 100]
|
246
|
+
#
|
212
247
|
# @return [List]
|
213
248
|
def flat_map(&block)
|
214
249
|
return enum_for(:flat_map) unless block_given?
|
215
250
|
LazyList.new do
|
216
251
|
next self if empty?
|
217
|
-
head_list =
|
252
|
+
head_list = List.from_enum(yield(head))
|
218
253
|
next tail.flat_map(&block) if head_list.empty?
|
219
254
|
Cons.new(head_list.first, head_list.drop(1).append(tail.flat_map(&block)))
|
220
255
|
end
|
221
256
|
end
|
222
257
|
|
223
|
-
# Return a
|
258
|
+
# Return a `List` which contains all the items for which the given block
|
224
259
|
# returns true.
|
225
260
|
#
|
261
|
+
# @example
|
262
|
+
# Hamster::List["Bird", "Cow", "Elephant"].select { |e| e.size >= 4 }
|
263
|
+
# # => Hamster::List["Bird", "Elephant"]
|
264
|
+
#
|
226
265
|
# @return [List]
|
227
|
-
|
228
|
-
|
266
|
+
# @yield [item] Once for each item.
|
267
|
+
def select(&block)
|
268
|
+
return enum_for(:select) unless block_given?
|
229
269
|
LazyList.new do
|
230
270
|
list = self
|
231
271
|
while true
|
232
272
|
break list if list.empty?
|
233
|
-
break Cons.new(list.head, list.tail.
|
273
|
+
break Cons.new(list.head, list.tail.select(&block)) if yield(list.head)
|
234
274
|
list = list.tail
|
235
275
|
end
|
236
276
|
end
|
237
277
|
end
|
278
|
+
alias :find_all :select
|
279
|
+
alias :keep_if :select
|
238
280
|
|
239
|
-
# Return a
|
281
|
+
# Return a `List` which contains all elements up to, but not including, the
|
240
282
|
# first element for which the block returns `nil` or `false`.
|
241
283
|
#
|
284
|
+
# @example
|
285
|
+
# Hamster::List[1, 3, 5, 7, 6, 4, 2].take_while { |e| e < 5 }
|
286
|
+
# # => Hamster::List[1, 3]
|
287
|
+
#
|
242
288
|
# @return [List, Enumerator]
|
289
|
+
# @yield [item]
|
243
290
|
def take_while(&block)
|
244
291
|
return enum_for(:take_while) unless block_given?
|
245
292
|
LazyList.new do
|
@@ -249,10 +296,15 @@ module Hamster
|
|
249
296
|
end
|
250
297
|
end
|
251
298
|
|
252
|
-
# Return a
|
299
|
+
# Return a `List` which contains all elements starting from the
|
253
300
|
# first element for which the block returns `nil` or `false`.
|
254
301
|
#
|
302
|
+
# @example
|
303
|
+
# Hamster::List[1, 3, 5, 7, 6, 4, 2].drop_while { |e| e < 5 }
|
304
|
+
# # => Hamster::List[5, 7, 6, 4, 2]
|
305
|
+
#
|
255
306
|
# @return [List, Enumerator]
|
307
|
+
# @yield [item]
|
256
308
|
def drop_while(&block)
|
257
309
|
return enum_for(:drop_while) unless block_given?
|
258
310
|
LazyList.new do
|
@@ -262,7 +314,12 @@ module Hamster
|
|
262
314
|
end
|
263
315
|
end
|
264
316
|
|
265
|
-
# Return a
|
317
|
+
# Return a `List` containing the first `number` items from this `List`.
|
318
|
+
#
|
319
|
+
# @example
|
320
|
+
# Hamster::List[1, 3, 5, 7, 6, 4, 2].take(3)
|
321
|
+
# # => Hamster::List[1, 3, 5]
|
322
|
+
#
|
266
323
|
# @param number [Integer] The number of items to retain
|
267
324
|
# @return [List]
|
268
325
|
def take(number)
|
@@ -273,7 +330,11 @@ module Hamster
|
|
273
330
|
end
|
274
331
|
end
|
275
332
|
|
276
|
-
# Return a
|
333
|
+
# Return a `List` containing all but the last item from this `List`.
|
334
|
+
#
|
335
|
+
# @example
|
336
|
+
# Hamster::List["A", "B", "C"].pop # => Hamster::List["A", "B"]
|
337
|
+
#
|
277
338
|
# @return [List]
|
278
339
|
def pop
|
279
340
|
LazyList.new do
|
@@ -284,8 +345,13 @@ module Hamster
|
|
284
345
|
end
|
285
346
|
end
|
286
347
|
|
287
|
-
# Return a
|
348
|
+
# Return a `List` containing all items after the first `number` items from
|
288
349
|
# this `List`.
|
350
|
+
#
|
351
|
+
# @example
|
352
|
+
# Hamster::List[1, 3, 5, 7, 6, 4, 2].drop(3)
|
353
|
+
# # => Hamster::List[7, 6, 4, 2]
|
354
|
+
#
|
289
355
|
# @param number [Integer] The number of items to skip over
|
290
356
|
# @return [List]
|
291
357
|
def drop(number)
|
@@ -299,9 +365,13 @@ module Hamster
|
|
299
365
|
end
|
300
366
|
end
|
301
367
|
|
302
|
-
# Return a
|
368
|
+
# Return a `List` with all items from this `List`, followed by all items from
|
303
369
|
# `other`.
|
304
370
|
#
|
371
|
+
# @example
|
372
|
+
# Hamster::List[1, 2, 3].append(Hamster::List[4, 5])
|
373
|
+
# # => Hamster::List[1, 2, 3, 4, 5]
|
374
|
+
#
|
305
375
|
# @param other [List] The list to add onto the end of this one
|
306
376
|
# @return [List]
|
307
377
|
def append(other)
|
@@ -310,21 +380,31 @@ module Hamster
|
|
310
380
|
Cons.new(head, tail.append(other))
|
311
381
|
end
|
312
382
|
end
|
313
|
-
|
314
|
-
|
315
|
-
def_delegator :self, :append, :+
|
383
|
+
alias :concat :append
|
384
|
+
alias :+ :append
|
316
385
|
|
317
386
|
# Return a `List` with the same items, but in reverse order.
|
387
|
+
#
|
388
|
+
# @example
|
389
|
+
# Hamster::List["A", "B", "C"].reverse # => Hamster::List["C", "B", "A"]
|
390
|
+
#
|
318
391
|
# @return [List]
|
319
392
|
def reverse
|
320
393
|
LazyList.new { reduce(EmptyList) { |list, item| list.cons(item) }}
|
321
394
|
end
|
322
395
|
|
323
|
-
#
|
324
|
-
#
|
325
|
-
#
|
396
|
+
# Combine two lists by "zipping" them together. The corresponding elements
|
397
|
+
# from this `List` and each of `others` (that is, the elements with the
|
398
|
+
# same indices) will be gathered into lists.
|
326
399
|
#
|
327
|
-
#
|
400
|
+
# If `others` contains fewer elements than this list, `nil` will be used
|
401
|
+
# for padding.
|
402
|
+
#
|
403
|
+
# @example
|
404
|
+
# Hamster::List["A", "B", "C"].zip(Hamster::List[1, 2, 3])
|
405
|
+
# # => Hamster::List[Hamster::List["A", 1], Hamster::List["B", 2], Hamster::List["C", 3]]
|
406
|
+
#
|
407
|
+
# @param others [List] The list to zip together with this one
|
328
408
|
# @return [List]
|
329
409
|
def zip(others)
|
330
410
|
LazyList.new do
|
@@ -335,7 +415,7 @@ module Hamster
|
|
335
415
|
|
336
416
|
# Gather the first element of each nested list into a new `List`, then the second
|
337
417
|
# element of each nested list, then the third, and so on. In other words, if each
|
338
|
-
# nested list is a "row", return a
|
418
|
+
# nested list is a "row", return a `List` of "columns" instead.
|
339
419
|
#
|
340
420
|
# Although the returned list is lazy, each returned nested list (each "column")
|
341
421
|
# is strict. So while each nested list in the input can be infinite, the parent
|
@@ -349,7 +429,7 @@ module Hamster
|
|
349
429
|
# list3 = Hamster.iterate(3) { |n| n * 3 }
|
350
430
|
#
|
351
431
|
# # Now we transpose our 3 infinite "rows" into an infinite series of 3-element "columns"
|
352
|
-
# Hamster
|
432
|
+
# Hamster::List[list1, list2, list3].transpose.take(4)
|
353
433
|
# # => Hamster::List[
|
354
434
|
# # Hamster::List[1, 2, 3],
|
355
435
|
# # Hamster::List[2, 4, 9],
|
@@ -367,8 +447,12 @@ module Hamster
|
|
367
447
|
end
|
368
448
|
end
|
369
449
|
|
370
|
-
# Concatenate an infinite series of copies of this `List` together
|
371
|
-
# new
|
450
|
+
# Concatenate an infinite series of copies of this `List` together into a
|
451
|
+
# new `List`. Or, if empty, just return an empty list.
|
452
|
+
#
|
453
|
+
# @example
|
454
|
+
# Hamster::List[1, 2, 3].cycle.take(10)
|
455
|
+
# # => Hamster::List[1, 2, 3, 1, 2, 3, 1, 2, 3, 1]
|
372
456
|
#
|
373
457
|
# @return [List]
|
374
458
|
def cycle
|
@@ -384,27 +468,43 @@ module Hamster
|
|
384
468
|
# will be moved to the end. If `count` is negative, the elements will be shifted
|
385
469
|
# right, and those shifted past the last position will be moved to the beginning.
|
386
470
|
#
|
471
|
+
# @example
|
472
|
+
# l = Hamster::List["A", "B", "C", "D", "E", "F"]
|
473
|
+
# l.rotate(2) # => Hamster::List["C", "D", "E", "F", "A", "B"]
|
474
|
+
# l.rotate(-1) # => Hamster::List["F", "A", "B", "C", "D", "E"]
|
475
|
+
#
|
387
476
|
# @param count [Integer] The number of positions to shift items by
|
388
477
|
# @return [Vector]
|
478
|
+
# @raise [TypeError] if count is not an integer.
|
389
479
|
def rotate(count = 1)
|
390
480
|
raise TypeError, "expected Integer" if not count.is_a?(Integer)
|
391
|
-
return self if
|
481
|
+
return self if empty? || (count % size) == 0
|
392
482
|
count = (count >= 0) ? count % size : (size - (~count % size) - 1)
|
393
483
|
drop(count).append(take(count))
|
394
484
|
end
|
395
485
|
|
396
|
-
# Return
|
397
|
-
# remaining
|
486
|
+
# Return two `List`s, one of the first `number` items, and another with the
|
487
|
+
# remaining.
|
488
|
+
#
|
489
|
+
# @example
|
490
|
+
# Hamster::List["a", "b", "c", "d"].split_at(2)
|
491
|
+
# # => [Hamster::List["a", "b"], Hamster::List["c", "d"]]
|
492
|
+
#
|
398
493
|
# @param number [Integer] The index at which to split this list
|
399
494
|
# @return [Array]
|
400
495
|
def split_at(number)
|
401
496
|
[take(number), drop(number)].freeze
|
402
497
|
end
|
403
498
|
|
404
|
-
# Return
|
499
|
+
# Return two `List`s, one up to (but not including) the first item for which the
|
405
500
|
# block returns `nil` or `false`, and another of all the remaining items.
|
406
501
|
#
|
502
|
+
# @example
|
503
|
+
# Hamster::List[4, 3, 5, 2, 1].span { |x| x > 2 }
|
504
|
+
# # => [Hamster::List[4, 3, 5], Hamster::List[2, 1]]
|
505
|
+
#
|
407
506
|
# @return [Array]
|
507
|
+
# @yield [item]
|
408
508
|
def span(&block)
|
409
509
|
return [self, EmptyList].freeze unless block_given?
|
410
510
|
splitter = Splitter.new(self, block)
|
@@ -413,46 +513,75 @@ module Hamster
|
|
413
513
|
Splitter::Right.new(splitter, mutex)].freeze
|
414
514
|
end
|
415
515
|
|
416
|
-
# Return
|
516
|
+
# Return two `List`s, one up to (but not including) the first item for which the
|
417
517
|
# block returns true, and another of all the remaining items.
|
418
518
|
#
|
519
|
+
# @example
|
520
|
+
# Hamster::List[1, 3, 4, 2, 5].break { |x| x > 3 }
|
521
|
+
# # => [Hamster::List[1, 3], Hamster::List[4, 2, 5]]
|
522
|
+
#
|
419
523
|
# @return [Array]
|
524
|
+
# @yield [item]
|
420
525
|
def break(&block)
|
421
526
|
return span unless block_given?
|
422
527
|
span { |item| !yield(item) }
|
423
528
|
end
|
424
529
|
|
425
|
-
# Return an empty `List`.
|
530
|
+
# Return an empty `List`. If used on a subclass, returns an empty instance
|
531
|
+
# of that class.
|
532
|
+
#
|
426
533
|
# @return [List]
|
427
534
|
def clear
|
428
535
|
EmptyList
|
429
536
|
end
|
430
537
|
|
431
|
-
# Return a `List` with the same items, but sorted
|
432
|
-
#
|
433
|
-
#
|
434
|
-
#
|
538
|
+
# Return a new `List` with the same items, but sorted.
|
539
|
+
#
|
540
|
+
# @overload sort
|
541
|
+
# Compare elements with their natural sort key (`#<=>`).
|
542
|
+
#
|
543
|
+
# @example
|
544
|
+
# Hamster::List["Elephant", "Dog", "Lion"].sort
|
545
|
+
# # => Hamster::List["Dog", "Elephant", "Lion"]
|
546
|
+
#
|
547
|
+
# @overload sort
|
548
|
+
# Uses the block as a comparator to determine sorted order.
|
549
|
+
#
|
550
|
+
# @yield [a, b] Any number of times with different pairs of elements.
|
551
|
+
# @yieldreturn [Integer] Negative if the first element should be sorted
|
552
|
+
# lower, positive if the latter element, or 0 if
|
553
|
+
# equal.
|
554
|
+
# @example
|
555
|
+
# Hamster::List["Elephant", "Dog", "Lion"].sort { |a,b| a.size <=> b.size }
|
556
|
+
# # => Hamster::List["Dog", "Lion", "Elephant"]
|
435
557
|
#
|
436
558
|
# @return [List]
|
437
559
|
def sort(&comparator)
|
438
|
-
LazyList.new { super(&comparator)
|
560
|
+
LazyList.new { List.from_enum(super(&comparator)) }
|
439
561
|
end
|
440
562
|
|
441
|
-
# Return a new `List` with the same items, but sorted. The sort order
|
442
|
-
# determined by mapping the items through the given block to obtain sort
|
443
|
-
# and then sorting the keys according to their natural sort order
|
563
|
+
# Return a new `List` with the same items, but sorted. The sort order is
|
564
|
+
# determined by mapping the items through the given block to obtain sort
|
565
|
+
# keys, and then sorting the keys according to their natural sort order
|
566
|
+
# (`#<=>`).
|
567
|
+
#
|
568
|
+
# @yield [element] Once for each element.
|
569
|
+
# @yieldreturn a sort key object for the yielded element.
|
570
|
+
# @example
|
571
|
+
# Hamster::List["Elephant", "Dog", "Lion"].sort_by { |e| e.size }
|
572
|
+
# # => Hamster::List["Dog", "Lion", "Elephant"]
|
444
573
|
#
|
445
574
|
# @return [List]
|
446
575
|
def sort_by(&transformer)
|
447
576
|
return sort unless block_given?
|
448
|
-
LazyList.new { super(&transformer)
|
577
|
+
LazyList.new { List.from_enum(super(&transformer)) }
|
449
578
|
end
|
450
579
|
|
451
580
|
# Return a new `List` with `sep` inserted between each of the existing elements.
|
452
581
|
#
|
453
582
|
# @example
|
454
|
-
# Hamster
|
455
|
-
# # => Hamster::List[
|
583
|
+
# Hamster::List["one", "two", "three"].intersperse(" ")
|
584
|
+
# # => Hamster::List["one", " ", "two", " ", "three"]
|
456
585
|
#
|
457
586
|
# @return [List]
|
458
587
|
def intersperse(sep)
|
@@ -462,35 +591,62 @@ module Hamster
|
|
462
591
|
end
|
463
592
|
end
|
464
593
|
|
465
|
-
# Return a
|
594
|
+
# Return a `List` with the same items, but all duplicates removed.
|
466
595
|
# Use `#hash` and `#eql?` to determine which items are duplicates.
|
467
596
|
#
|
597
|
+
# @example
|
598
|
+
# Hamster::List[:a, :b, :a, :c, :b].uniq # => Hamster::List[:a, :b, :c]
|
599
|
+
# Hamster::List["a", "A", "b"].uniq(&:upcase) # => Hamster::List["a", "b"]
|
600
|
+
#
|
468
601
|
# @return [List]
|
469
|
-
def uniq(
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
602
|
+
def uniq(&block)
|
603
|
+
_uniq(::Set.new, &block)
|
604
|
+
end
|
605
|
+
|
606
|
+
# @private
|
607
|
+
# Separate from `uniq` so as not to expose `items` in the public API.
|
608
|
+
def _uniq(items, &block)
|
609
|
+
if block_given?
|
610
|
+
LazyList.new do
|
611
|
+
next self if empty?
|
612
|
+
if items.add?(block.call(head))
|
613
|
+
Cons.new(head, tail._uniq(items, &block))
|
614
|
+
else
|
615
|
+
tail._uniq(items, &block)
|
616
|
+
end
|
617
|
+
end
|
618
|
+
else
|
619
|
+
LazyList.new do
|
620
|
+
next self if empty?
|
621
|
+
next tail._uniq(items) if items.include?(head)
|
622
|
+
Cons.new(head, tail._uniq(items.add(head)))
|
623
|
+
end
|
474
624
|
end
|
475
625
|
end
|
476
|
-
|
477
|
-
def_delegator :self, :uniq, :remove_duplicates
|
626
|
+
protected :_uniq
|
478
627
|
|
479
628
|
# Return a `List` with all the elements from both this list and `other`,
|
480
629
|
# with all duplicates removed.
|
481
630
|
#
|
631
|
+
# @example
|
632
|
+
# Hamster::List[1, 2].union(Hamster::List[2, 3]) # => Hamster::List[1, 2, 3]
|
633
|
+
#
|
482
634
|
# @param other [List] The list to merge with
|
483
635
|
# @return [List]
|
484
636
|
def union(other, items = ::Set.new)
|
485
637
|
LazyList.new do
|
486
|
-
next other.
|
638
|
+
next other._uniq(items) if empty?
|
487
639
|
next tail.union(other, items) if items.include?(head)
|
488
640
|
Cons.new(head, tail.union(other, items.add(head)))
|
489
641
|
end
|
490
642
|
end
|
491
|
-
|
643
|
+
alias :| :union
|
492
644
|
|
493
|
-
# Return a
|
645
|
+
# Return a `List` with all elements except the last one.
|
646
|
+
#
|
647
|
+
# @example
|
648
|
+
# Hamster::List["a", "b", "c"].init # => Hamster::List["a", "b"]
|
649
|
+
#
|
494
650
|
# @return [List]
|
495
651
|
def init
|
496
652
|
return EmptyList if tail.empty?
|
@@ -505,10 +661,10 @@ module Hamster
|
|
505
661
|
list.head
|
506
662
|
end
|
507
663
|
|
508
|
-
# Return a
|
664
|
+
# Return a `List` of all suffixes of this list.
|
509
665
|
#
|
510
666
|
# @example
|
511
|
-
# Hamster
|
667
|
+
# Hamster::List[1,2,3].tails
|
512
668
|
# # => Hamster::List[
|
513
669
|
# # Hamster::List[1, 2, 3],
|
514
670
|
# # Hamster::List[2, 3],
|
@@ -522,10 +678,10 @@ module Hamster
|
|
522
678
|
end
|
523
679
|
end
|
524
680
|
|
525
|
-
# Return a
|
681
|
+
# Return a `List` of all prefixes of this list.
|
526
682
|
#
|
527
683
|
# @example
|
528
|
-
# Hamster
|
684
|
+
# Hamster::List[1,2,3].inits
|
529
685
|
# # => Hamster::List[
|
530
686
|
# # Hamster::List[1],
|
531
687
|
# # Hamster::List[1, 2],
|
@@ -535,14 +691,14 @@ module Hamster
|
|
535
691
|
def inits
|
536
692
|
LazyList.new do
|
537
693
|
next self if empty?
|
538
|
-
Cons.new(
|
694
|
+
Cons.new(List[head], tail.inits.map { |list| list.cons(head) })
|
539
695
|
end
|
540
696
|
end
|
541
697
|
|
542
|
-
# Return a
|
698
|
+
# Return a `List` of all combinations of length `n` of items from this `List`.
|
543
699
|
#
|
544
700
|
# @example
|
545
|
-
# Hamster
|
701
|
+
# Hamster::List[1,2,3].combination(2)
|
546
702
|
# # => Hamster::List[
|
547
703
|
# # Hamster::List[1, 2],
|
548
704
|
# # Hamster::List[1, 3],
|
@@ -558,6 +714,14 @@ module Hamster
|
|
558
714
|
end
|
559
715
|
|
560
716
|
# Split the items in this list in groups of `number`. Return a list of lists.
|
717
|
+
#
|
718
|
+
# @example
|
719
|
+
# ("a".."o").to_list.chunk(5)
|
720
|
+
# # => Hamster::List[
|
721
|
+
# # Hamster::List["a", "b", "c", "d", "e"],
|
722
|
+
# # Hamster::List["f", "g", "h", "i", "j"],
|
723
|
+
# # Hamster::List["k", "l", "m", "n", "o"]]
|
724
|
+
#
|
561
725
|
# @return [List]
|
562
726
|
def chunk(number)
|
563
727
|
LazyList.new do
|
@@ -568,19 +732,26 @@ module Hamster
|
|
568
732
|
end
|
569
733
|
|
570
734
|
# Split the items in this list in groups of `number`, and yield each group
|
571
|
-
# to the block (as a `List`).
|
572
|
-
#
|
735
|
+
# to the block (as a `List`). If no block is given, returns an
|
736
|
+
# `Enumerator`.
|
737
|
+
#
|
738
|
+
# @return [self, Enumerator]
|
739
|
+
# @yield [list] Once for each chunk.
|
573
740
|
def each_chunk(number, &block)
|
574
741
|
return enum_for(:each_chunk, number) unless block_given?
|
575
742
|
chunk(number).each(&block)
|
576
743
|
self
|
577
744
|
end
|
578
|
-
|
745
|
+
alias :each_slice :each_chunk
|
579
746
|
|
580
747
|
# Return a new `List` with all nested lists recursively "flattened out",
|
581
748
|
# that is, their elements inserted into the new `List` in the place where
|
582
749
|
# the nested list originally was.
|
583
750
|
#
|
751
|
+
# @example
|
752
|
+
# Hamster::List[Hamster::List[1, 2], Hamster::List[3, 4]].flatten
|
753
|
+
# # => Hamster::List[1, 2, 3, 4]
|
754
|
+
#
|
584
755
|
# @return [List]
|
585
756
|
def flatten
|
586
757
|
LazyList.new do
|
@@ -595,10 +766,17 @@ module Hamster
|
|
595
766
|
# for which the block returned that value.
|
596
767
|
#
|
597
768
|
# @return [Hash]
|
769
|
+
# @yield [item]
|
770
|
+
# @example
|
771
|
+
# Hamster::List["a", "b", "ab"].group_by { |e| e.size }
|
772
|
+
# # Hamster::Hash[
|
773
|
+
# # 1 => Hamster::List["b", "a"],
|
774
|
+
# # 2 => Hamster::List["ab"]
|
775
|
+
# # ]
|
598
776
|
def group_by(&block)
|
599
777
|
group_by_with(EmptyList, &block)
|
600
778
|
end
|
601
|
-
|
779
|
+
alias :group :group_by
|
602
780
|
|
603
781
|
# Retrieve the item at `index`. Negative indices count back from the end of
|
604
782
|
# the list (-1 is the last item). If `index` is invalid (either too high or
|
@@ -617,22 +795,47 @@ module Hamster
|
|
617
795
|
node.head
|
618
796
|
end
|
619
797
|
|
620
|
-
#
|
621
|
-
#
|
798
|
+
# Return specific objects from the `List`. All overloads return `nil` if
|
799
|
+
# the starting index is out of range.
|
800
|
+
#
|
801
|
+
# @overload list.slice(index)
|
802
|
+
# Returns a single object at the given `index`. If `index` is negative,
|
803
|
+
# count backwards from the end.
|
804
|
+
#
|
805
|
+
# @param index [Integer] The index to retrieve. May be negative.
|
806
|
+
# @return [Object]
|
807
|
+
# @example
|
808
|
+
# l = Hamster::List["A", "B", "C", "D", "E", "F"]
|
809
|
+
# l[2] # => "C"
|
810
|
+
# l[-1] # => "F"
|
811
|
+
# l[6] # => nil
|
622
812
|
#
|
623
|
-
# @overload list
|
624
|
-
# Return
|
625
|
-
#
|
626
|
-
#
|
627
|
-
#
|
628
|
-
#
|
813
|
+
# @overload list.slice(index, length)
|
814
|
+
# Return a sublist starting at `index` and continuing for `length`
|
815
|
+
# elements or until the end of the `List`, whichever occurs first.
|
816
|
+
#
|
817
|
+
# @param start [Integer] The index to start retrieving items from. May be
|
818
|
+
# negative.
|
629
819
|
# @param length [Integer] The number of items to retrieve.
|
630
|
-
#
|
631
|
-
#
|
632
|
-
#
|
820
|
+
# @return [List]
|
821
|
+
# @example
|
822
|
+
# l = Hamster::List["A", "B", "C", "D", "E", "F"]
|
823
|
+
# l[2, 3] # => Hamster::List["C", "D", "E"]
|
824
|
+
# l[-2, 3] # => Hamster::List["E", "F"]
|
825
|
+
# l[20, 1] # => nil
|
633
826
|
#
|
634
|
-
# @
|
635
|
-
|
827
|
+
# @overload list.slice(index..end)
|
828
|
+
# Return a sublist starting at `index` and continuing to index
|
829
|
+
# `end` or the end of the `List`, whichever occurs first.
|
830
|
+
#
|
831
|
+
# @param range [Range] The range of indices to retrieve.
|
832
|
+
# @return [Vector]
|
833
|
+
# @example
|
834
|
+
# l = Hamster::List["A", "B", "C", "D", "E", "F"]
|
835
|
+
# l[2..3] # => Hamster::List["C", "D"]
|
836
|
+
# l[-2..100] # => Hamster::List["E", "F"]
|
837
|
+
# l[20..21] # => nil
|
838
|
+
def slice(arg, length = (missing_length = true))
|
636
839
|
if missing_length
|
637
840
|
if arg.is_a?(Range)
|
638
841
|
from, to = arg.begin, arg.end
|
@@ -665,18 +868,35 @@ module Hamster
|
|
665
868
|
list.take(length)
|
666
869
|
end
|
667
870
|
end
|
668
|
-
|
871
|
+
alias :[] :slice
|
669
872
|
|
670
|
-
#
|
671
|
-
#
|
873
|
+
# Return a `List` of indices of matching objects.
|
874
|
+
#
|
875
|
+
# @overload indices(object)
|
876
|
+
# Return a `List` of indices where `object` is found. Use `#==` for
|
877
|
+
# testing equality.
|
878
|
+
#
|
879
|
+
# @example
|
880
|
+
# Hamster::List[1, 2, 3, 4].indices(2)
|
881
|
+
# # => Hamster::List[1]
|
882
|
+
#
|
883
|
+
# @overload indices
|
884
|
+
# Pass each item successively to the block. Return a list of indices
|
885
|
+
# where the block returns true.
|
886
|
+
#
|
887
|
+
# @yield [item]
|
888
|
+
# @example
|
889
|
+
# Hamster::List[1, 2, 3, 4].indices { |e| e.even? }
|
890
|
+
# # => Hamster::List[1, 3]
|
672
891
|
#
|
673
892
|
# @return [List]
|
674
|
-
def
|
675
|
-
return
|
893
|
+
def indices(object = Undefined, i = 0, &block)
|
894
|
+
return indices { |item| item == object } if not block_given?
|
895
|
+
return EmptyList if empty?
|
676
896
|
LazyList.new do
|
677
897
|
node = self
|
678
898
|
while true
|
679
|
-
break Cons.new(i, node.tail.
|
899
|
+
break Cons.new(i, node.tail.indices(Undefined, i + 1, &block)) if yield(node.head)
|
680
900
|
node = node.tail
|
681
901
|
break EmptyList if node.empty?
|
682
902
|
i += 1
|
@@ -684,42 +904,25 @@ module Hamster
|
|
684
904
|
end
|
685
905
|
end
|
686
906
|
|
687
|
-
# Return a `List` of indices where `object` is found. Use `#==` for testing equality.
|
688
|
-
#
|
689
|
-
# @param object [Object] The object to search for
|
690
|
-
# @return [List]
|
691
|
-
def elem_indices(object)
|
692
|
-
find_indices { |item| item == object }
|
693
|
-
end
|
694
|
-
|
695
|
-
# Return a `List` of indices where the given object is found, or where the given
|
696
|
-
# block returns true.
|
697
|
-
#
|
698
|
-
# @overload indices(obj)
|
699
|
-
# Return a `List` of indices where `obj` is found. Use `#==` for testing equality.
|
700
|
-
# @overload indices { |item| ... }
|
701
|
-
# Pass each item successively to the block. Return a list of indices where the
|
702
|
-
# block returns true.
|
703
|
-
#
|
704
|
-
# @return [List]
|
705
|
-
def indices(object = Undefined, &block)
|
706
|
-
return elem_indices(object) unless object.equal?(Undefined)
|
707
|
-
find_indices(&block)
|
708
|
-
end
|
709
|
-
|
710
907
|
# Merge all the nested lists into a single list, using the given comparator
|
711
908
|
# block to determine the order which items should be shifted out of the nested
|
712
|
-
# lists and into the output list.
|
713
|
-
#
|
714
|
-
#
|
715
|
-
#
|
716
|
-
#
|
909
|
+
# lists and into the output list.
|
910
|
+
#
|
911
|
+
# @example
|
912
|
+
# list_1 = Hamster::List[1, -3, -5]
|
913
|
+
# list_2 = Hamster::List[-2, 4, 6]
|
914
|
+
# Hamster::List[list_1, list_2].merge { |a,b| a.abs <=> b.abs }
|
915
|
+
# # => Hamster::List[1, -2, -3, 4, -5, 6]
|
717
916
|
#
|
718
917
|
# @return [List]
|
918
|
+
# @yield [a, b] Pairs of items from matching indices in each list.
|
919
|
+
# @yieldreturn [Integer] Negative if the first element should be selected
|
920
|
+
# first, positive if the latter element, or zero if
|
921
|
+
# either.
|
719
922
|
def merge(&comparator)
|
720
923
|
return merge_by unless block_given?
|
721
924
|
LazyList.new do
|
722
|
-
sorted =
|
925
|
+
sorted = reject(&:empty?).sort do |a, b|
|
723
926
|
yield(a.head, b.head)
|
724
927
|
end
|
725
928
|
next EmptyList if sorted.empty?
|
@@ -733,11 +936,19 @@ module Hamster
|
|
733
936
|
# list. Whichever nested list's `#head` has the "lowest" sort key (according to
|
734
937
|
# their natural order) will be the first in the merged `List`.
|
735
938
|
#
|
939
|
+
# @example
|
940
|
+
# list_1 = Hamster::List[1, -3, -5]
|
941
|
+
# list_2 = Hamster::List[-2, 4, 6]
|
942
|
+
# Hamster::List[list_1, list_2].merge_by { |x| x.abs }
|
943
|
+
# # => Hamster::List[1, -2, -3, 4, -5, 6]
|
944
|
+
#
|
736
945
|
# @return [List]
|
946
|
+
# @yield [item] Once for each item in either list.
|
947
|
+
# @yieldreturn [Object] A sort key for the element.
|
737
948
|
def merge_by(&transformer)
|
738
949
|
return merge_by { |item| item } unless block_given?
|
739
950
|
LazyList.new do
|
740
|
-
sorted =
|
951
|
+
sorted = reject(&:empty?).sort_by do |list|
|
741
952
|
yield(list.head)
|
742
953
|
end
|
743
954
|
next EmptyList if sorted.empty?
|
@@ -753,12 +964,15 @@ module Hamster
|
|
753
964
|
|
754
965
|
# Return a new `List` with the given items inserted before the item at `index`.
|
755
966
|
#
|
967
|
+
# @example
|
968
|
+
# Hamster::List["A", "D", "E"].insert(1, "B", "C") # => Hamster::List["A", "B", "C", "D", "E"]
|
969
|
+
#
|
756
970
|
# @param index [Integer] The index where the new items should go
|
757
971
|
# @param items [Array] The items to add
|
758
972
|
# @return [List]
|
759
973
|
def insert(index, *items)
|
760
974
|
if index == 0
|
761
|
-
return items.
|
975
|
+
return List.from_enum(items).append(self)
|
762
976
|
elsif index > 0
|
763
977
|
LazyList.new do
|
764
978
|
Cons.new(head, tail.insert(index-1, *items))
|
@@ -769,8 +983,12 @@ module Hamster
|
|
769
983
|
end
|
770
984
|
end
|
771
985
|
|
772
|
-
# Return a
|
986
|
+
# Return a `List` with all elements equal to `obj` removed. `#==` is used
|
773
987
|
# for testing equality.
|
988
|
+
#
|
989
|
+
# @example
|
990
|
+
# Hamster::List[:a, :b, :a, :a, :c].delete(:a) # => Hamster::List[:b, :c]
|
991
|
+
#
|
774
992
|
# @param obj [Object] The object to remove.
|
775
993
|
# @return [List]
|
776
994
|
def delete(obj)
|
@@ -780,9 +998,13 @@ module Hamster
|
|
780
998
|
LazyList.new { Cons.new(list.head, list.tail.delete(obj)) }
|
781
999
|
end
|
782
1000
|
|
783
|
-
# Return a
|
1001
|
+
# Return a `List` containing the same items, minus the one at `index`.
|
784
1002
|
# If `index` is negative, it counts back from the end of the list.
|
785
1003
|
#
|
1004
|
+
# @example
|
1005
|
+
# Hamster::List[1, 2, 3].delete_at(1) # => Hamster::List[1, 3]
|
1006
|
+
# Hamster::List[1, 2, 3].delete_at(-1) # => Hamster::List[1, 2]
|
1007
|
+
#
|
786
1008
|
# @param index [Integer] The index of the item to remove
|
787
1009
|
# @return [List]
|
788
1010
|
def delete_at(index)
|
@@ -799,16 +1021,40 @@ module Hamster
|
|
799
1021
|
|
800
1022
|
# Replace a range of indexes with the given object.
|
801
1023
|
#
|
802
|
-
# @overload fill(
|
803
|
-
# Return a new `List` of the same size, with every
|
804
|
-
#
|
805
|
-
#
|
806
|
-
#
|
807
|
-
#
|
808
|
-
#
|
809
|
-
#
|
1024
|
+
# @overload fill(object)
|
1025
|
+
# Return a new `List` of the same size, with every index set to `object`.
|
1026
|
+
#
|
1027
|
+
# @param [Object] object Fill value.
|
1028
|
+
# @example
|
1029
|
+
# Hamster::List["A", "B", "C", "D", "E", "F"].fill("Z")
|
1030
|
+
# # => Hamster::List["Z", "Z", "Z", "Z", "Z", "Z"]
|
1031
|
+
#
|
1032
|
+
# @overload fill(object, index)
|
1033
|
+
# Return a new `List` with all indexes from `index` to the end of the
|
1034
|
+
# vector set to `obj`.
|
1035
|
+
#
|
1036
|
+
# @param [Object] object Fill value.
|
1037
|
+
# @param [Integer] index Starting index. May be negative.
|
1038
|
+
# @example
|
1039
|
+
# Hamster::List["A", "B", "C", "D", "E", "F"].fill("Z", 3)
|
1040
|
+
# # => Hamster::List["A", "B", "C", "Z", "Z", "Z"]
|
1041
|
+
#
|
1042
|
+
# @overload fill(object, index, length)
|
1043
|
+
# Return a new `List` with `length` indexes, beginning from `index`,
|
1044
|
+
# set to `obj`. Expands the `List` if `length` would extend beyond the
|
1045
|
+
# current length.
|
1046
|
+
#
|
1047
|
+
# @param [Object] object Fill value.
|
1048
|
+
# @param [Integer] index Starting index. May be negative.
|
1049
|
+
# @param [Integer] length
|
1050
|
+
# @example
|
1051
|
+
# Hamster::List["A", "B", "C", "D", "E", "F"].fill("Z", 3, 2)
|
1052
|
+
# # => Hamster::List["A", "B", "C", "Z", "Z", "F"]
|
1053
|
+
# Hamster::List["A", "B"].fill("Z", 1, 5)
|
1054
|
+
# # => Hamster::List["A", "Z", "Z", "Z", "Z", "Z"]
|
810
1055
|
#
|
811
1056
|
# @return [List]
|
1057
|
+
# @raise [IndexError] if index is out of negative range.
|
812
1058
|
def fill(obj, index = 0, length = nil)
|
813
1059
|
if index == 0
|
814
1060
|
length ||= size
|
@@ -837,7 +1083,17 @@ module Hamster
|
|
837
1083
|
#
|
838
1084
|
# If no block is given, an `Enumerator` is returned instead.
|
839
1085
|
#
|
1086
|
+
# @example
|
1087
|
+
# Hamster::List[1, 2, 3].permutation.to_a
|
1088
|
+
# # => [Hamster::List[1, 2, 3],
|
1089
|
+
# # Hamster::List[2, 1, 3],
|
1090
|
+
# # Hamster::List[2, 3, 1],
|
1091
|
+
# # Hamster::List[1, 3, 2],
|
1092
|
+
# # Hamster::List[3, 1, 2],
|
1093
|
+
# # Hamster::List[3, 2, 1]]
|
1094
|
+
#
|
840
1095
|
# @return [self, Enumerator]
|
1096
|
+
# @yield [list] Once for each permutation.
|
841
1097
|
def permutation(length = size, &block)
|
842
1098
|
return enum_for(:permutation, length) if not block_given?
|
843
1099
|
if length == 0
|
@@ -863,7 +1119,7 @@ module Hamster
|
|
863
1119
|
# counts as one sublist.)
|
864
1120
|
#
|
865
1121
|
# @example
|
866
|
-
# Hamster
|
1122
|
+
# Hamster::List[1, 2, 3].subsequences { |list| p list }
|
867
1123
|
# # prints:
|
868
1124
|
# # Hamster::List[1]
|
869
1125
|
# # Hamster::List[1, 2]
|
@@ -885,10 +1141,15 @@ module Hamster
|
|
885
1141
|
self
|
886
1142
|
end
|
887
1143
|
|
888
|
-
# Return
|
889
|
-
# evaluates to true, the second containing the rest.
|
1144
|
+
# Return two `List`s, the first containing all the elements for which the
|
1145
|
+
# block evaluates to true, the second containing the rest.
|
1146
|
+
#
|
1147
|
+
# @example
|
1148
|
+
# Hamster::List[1, 2, 3, 4, 5, 6].partition { |x| x.even? }
|
1149
|
+
# # => [Hamster::List[2, 4, 6], Hamster::List[1, 3, 5]]
|
890
1150
|
#
|
891
1151
|
# @return [List]
|
1152
|
+
# @yield [item] Once for each item.
|
892
1153
|
def partition(&block)
|
893
1154
|
return enum_for(:partition) if not block_given?
|
894
1155
|
partitioner = Partitioner.new(self, block)
|
@@ -920,12 +1181,13 @@ module Hamster
|
|
920
1181
|
reduce(0) { |hash, item| (hash << 5) - hash + item.hash }
|
921
1182
|
end
|
922
1183
|
|
923
|
-
# Return `self`.
|
1184
|
+
# Return `self`. Since this is an immutable object duplicates are
|
1185
|
+
# equivalent.
|
924
1186
|
# @return [List]
|
925
1187
|
def dup
|
926
1188
|
self
|
927
1189
|
end
|
928
|
-
|
1190
|
+
alias :clone :dup
|
929
1191
|
|
930
1192
|
# Return `self`.
|
931
1193
|
# @return [List]
|
@@ -971,13 +1233,21 @@ module Hamster
|
|
971
1233
|
|
972
1234
|
private
|
973
1235
|
|
1236
|
+
# Perform compositions of `car` and `cdr` operations (traditional shorthand
|
1237
|
+
# for `head` and `tail` respectively). Their names consist of a `c`,
|
1238
|
+
# followed by at least one `a` or `d`, and finally an `r`. The series of
|
1239
|
+
# `a`s and `d`s in the method name identify the series of `car` and `cdr`
|
1240
|
+
# operations performed, in inverse order.
|
1241
|
+
#
|
1242
|
+
# @return [Object, List]
|
1243
|
+
# @example
|
1244
|
+
# l = Hamster::List[nil, Hamster::List[1]]
|
1245
|
+
# l.car # => nil
|
1246
|
+
# l.cdr # => Hamster::List[Hamster::List[1]]
|
1247
|
+
# l.cadr # => Hamster::List[1]
|
1248
|
+
# l.caadr # => 1
|
974
1249
|
def method_missing(name, *args, &block)
|
975
1250
|
if name.to_s.match(CADR)
|
976
|
-
# Perform compositions of car and cdr operations. Their names consist of a 'c',
|
977
|
-
# followed by at least one 'a' or 'd', and finally an 'r'. The series of 'a's and
|
978
|
-
# 'd's in the method name identify the series of car and cdr operations performed.
|
979
|
-
# The order in which the 'a's and 'd's appear is the inverse of the order in which
|
980
|
-
# the corresponding operations are performed.
|
981
1251
|
code = "def #{name}; self."
|
982
1252
|
code << Regexp.last_match[1].reverse.chars.map do |char|
|
983
1253
|
{'a' => 'head', 'd' => 'tail'}[char]
|
@@ -1020,6 +1290,7 @@ module Hamster
|
|
1020
1290
|
def size
|
1021
1291
|
@size ||= super
|
1022
1292
|
end
|
1293
|
+
alias :length :size
|
1023
1294
|
|
1024
1295
|
def cached_size?
|
1025
1296
|
@size != nil
|
@@ -1031,7 +1302,7 @@ module Hamster
|
|
1031
1302
|
# only called) when one of these operations is performed.
|
1032
1303
|
#
|
1033
1304
|
# By returning a `Cons` that in turn has a {LazyList} as its tail, one can
|
1034
|
-
# construct infinite
|
1305
|
+
# construct infinite `List`s.
|
1035
1306
|
#
|
1036
1307
|
# @private
|
1037
1308
|
class LazyList
|
@@ -1040,7 +1311,7 @@ module Hamster
|
|
1040
1311
|
def initialize(&block)
|
1041
1312
|
@head = block # doubles as storage for block while yet unrealized
|
1042
1313
|
@tail = nil
|
1043
|
-
@atomic = Atomic.new(0) # haven't yet run block
|
1314
|
+
@atomic = Concurrent::Atomic.new(0) # haven't yet run block
|
1044
1315
|
@size = nil
|
1045
1316
|
end
|
1046
1317
|
|
@@ -1048,6 +1319,7 @@ module Hamster
|
|
1048
1319
|
realize if @atomic.get != 2
|
1049
1320
|
@head
|
1050
1321
|
end
|
1322
|
+
alias :first :head
|
1051
1323
|
|
1052
1324
|
def tail
|
1053
1325
|
realize if @atomic.get != 2
|
@@ -1062,6 +1334,7 @@ module Hamster
|
|
1062
1334
|
def size
|
1063
1335
|
@size ||= super
|
1064
1336
|
end
|
1337
|
+
alias :length :size
|
1065
1338
|
|
1066
1339
|
def cached_size?
|
1067
1340
|
@size != nil
|
@@ -1106,7 +1379,7 @@ module Hamster
|
|
1106
1379
|
end
|
1107
1380
|
end
|
1108
1381
|
|
1109
|
-
# Common behavior for other classes which implement various kinds of
|
1382
|
+
# Common behavior for other classes which implement various kinds of `List`s
|
1110
1383
|
# @private
|
1111
1384
|
class Realizable
|
1112
1385
|
include List
|
@@ -1119,6 +1392,7 @@ module Hamster
|
|
1119
1392
|
realize if @head == Undefined
|
1120
1393
|
@head
|
1121
1394
|
end
|
1395
|
+
alias :first :head
|
1122
1396
|
|
1123
1397
|
def tail
|
1124
1398
|
realize if @tail == Undefined
|
@@ -1133,6 +1407,7 @@ module Hamster
|
|
1133
1407
|
def size
|
1134
1408
|
@size ||= super
|
1135
1409
|
end
|
1410
|
+
alias :length :size
|
1136
1411
|
|
1137
1412
|
def cached_size?
|
1138
1413
|
@size != nil
|
@@ -1143,7 +1418,7 @@ module Hamster
|
|
1143
1418
|
end
|
1144
1419
|
end
|
1145
1420
|
|
1146
|
-
# This class can divide a collection into 2
|
1421
|
+
# This class can divide a collection into 2 `List`s, one of items
|
1147
1422
|
# for which the block returns true, and another for false
|
1148
1423
|
# At the same time, it guarantees the block will only be called ONCE for each item
|
1149
1424
|
#
|
@@ -1167,7 +1442,7 @@ module Hamster
|
|
1167
1442
|
end
|
1168
1443
|
end
|
1169
1444
|
|
1170
|
-
# One of the
|
1445
|
+
# One of the `List`s which gets its items from a Partitioner
|
1171
1446
|
# @private
|
1172
1447
|
class Partitioned < Realizable
|
1173
1448
|
def initialize(partitioner, buffer, mutex)
|
@@ -1176,7 +1451,9 @@ module Hamster
|
|
1176
1451
|
end
|
1177
1452
|
|
1178
1453
|
def realize
|
1179
|
-
@mutex
|
1454
|
+
# another thread may get ahead of us and null out @mutex
|
1455
|
+
mutex = @mutex
|
1456
|
+
mutex && mutex.synchronize do
|
1180
1457
|
return if @head != Undefined # another thread got ahead of us
|
1181
1458
|
while true
|
1182
1459
|
if !@buffer.empty?
|
@@ -1198,9 +1475,10 @@ module Hamster
|
|
1198
1475
|
end
|
1199
1476
|
end
|
1200
1477
|
|
1201
|
-
# This class can divide a list up into 2
|
1202
|
-
#
|
1203
|
-
# It guarantees that the block will only be called ONCE for each
|
1478
|
+
# This class can divide a list up into 2 `List`s, one for the prefix of
|
1479
|
+
# elements for which the block returns true, and another for all the elements
|
1480
|
+
# after that. It guarantees that the block will only be called ONCE for each
|
1481
|
+
# item
|
1204
1482
|
#
|
1205
1483
|
# @private
|
1206
1484
|
class Splitter
|
@@ -1226,6 +1504,7 @@ module Hamster
|
|
1226
1504
|
@list.empty?
|
1227
1505
|
end
|
1228
1506
|
|
1507
|
+
# @private
|
1229
1508
|
class Left < Realizable
|
1230
1509
|
def initialize(splitter, buffer, mutex)
|
1231
1510
|
super()
|
@@ -1233,7 +1512,9 @@ module Hamster
|
|
1233
1512
|
end
|
1234
1513
|
|
1235
1514
|
def realize
|
1236
|
-
@mutex
|
1515
|
+
# another thread may get ahead of us and null out @mutex
|
1516
|
+
mutex = @mutex
|
1517
|
+
mutex && mutex.synchronize do
|
1237
1518
|
return if @head != Undefined # another thread got ahead of us
|
1238
1519
|
while true
|
1239
1520
|
if !@buffer.empty?
|
@@ -1253,6 +1534,7 @@ module Hamster
|
|
1253
1534
|
end
|
1254
1535
|
end
|
1255
1536
|
|
1537
|
+
# @private
|
1256
1538
|
class Right < Realizable
|
1257
1539
|
def initialize(splitter, mutex)
|
1258
1540
|
super()
|
@@ -1260,7 +1542,8 @@ module Hamster
|
|
1260
1542
|
end
|
1261
1543
|
|
1262
1544
|
def realize
|
1263
|
-
@mutex
|
1545
|
+
mutex = @mutex
|
1546
|
+
mutex && mutex.synchronize do
|
1264
1547
|
return if @head != Undefined
|
1265
1548
|
@splitter.next_item until @splitter.done?
|
1266
1549
|
if @splitter.right.empty?
|
@@ -1275,7 +1558,7 @@ module Hamster
|
|
1275
1558
|
end
|
1276
1559
|
|
1277
1560
|
# A list without any elements. This is a singleton, since all empty lists are equivalent.
|
1278
|
-
#
|
1561
|
+
# @private
|
1279
1562
|
module EmptyList
|
1280
1563
|
class << self
|
1281
1564
|
include List
|
@@ -1285,6 +1568,7 @@ module Hamster
|
|
1285
1568
|
def head
|
1286
1569
|
nil
|
1287
1570
|
end
|
1571
|
+
alias :first :head
|
1288
1572
|
|
1289
1573
|
# There are no subsequent elements, so return an empty list.
|
1290
1574
|
# @return [self]
|
@@ -1301,10 +1585,11 @@ module Hamster
|
|
1301
1585
|
def size
|
1302
1586
|
0
|
1303
1587
|
end
|
1588
|
+
alias :length :size
|
1304
1589
|
|
1305
1590
|
def cached_size?
|
1306
1591
|
true
|
1307
1592
|
end
|
1308
1593
|
end
|
1309
1594
|
end
|
1310
|
-
end
|
1595
|
+
end.freeze
|