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/mutable_hash.rb
CHANGED
@@ -1,16 +1,15 @@
|
|
1
|
-
require "forwardable"
|
2
1
|
require "hamster/hash"
|
3
2
|
require "hamster/read_copy_update"
|
4
3
|
|
5
4
|
module Hamster
|
6
|
-
|
7
|
-
MutableHash.new(hash(pairs, &block))
|
8
|
-
end
|
9
|
-
|
5
|
+
# @api private
|
10
6
|
class MutableHash
|
11
|
-
extend Forwardable
|
12
7
|
include ReadCopyUpdate
|
13
8
|
|
9
|
+
def self.[](pairs = {})
|
10
|
+
MutableHash.new(Hash[pairs])
|
11
|
+
end
|
12
|
+
|
14
13
|
def put(key, value = Undefined, &block)
|
15
14
|
transform { |hash| hash.put(key, value, &block) }
|
16
15
|
end
|
@@ -19,7 +18,7 @@ module Hamster
|
|
19
18
|
put(key, value)
|
20
19
|
value
|
21
20
|
end
|
22
|
-
|
21
|
+
alias :[]= :store
|
23
22
|
|
24
23
|
def delete(key)
|
25
24
|
old_value = nil
|
@@ -0,0 +1,78 @@
|
|
1
|
+
require "set"
|
2
|
+
require "hamster/hash"
|
3
|
+
require "hamster/set"
|
4
|
+
require "hamster/vector"
|
5
|
+
require "hamster/sorted_set"
|
6
|
+
require "hamster/list"
|
7
|
+
require "hamster/deque"
|
8
|
+
require "hamster/core_ext/struct"
|
9
|
+
|
10
|
+
module Hamster
|
11
|
+
class << self
|
12
|
+
|
13
|
+
# Create a Hamster immutable data structure with nested Hamster data
|
14
|
+
# structure from a nested Ruby object `obj`. This method recursively
|
15
|
+
# "walks" the Ruby object, converting Ruby `Hash` to {Hamster::Hash}, Ruby
|
16
|
+
# `Array` to {Hamster::Vector}, Ruby `Set` to {Hamster::Set}, and Ruby
|
17
|
+
# `SortedSet` to {Hamster::SortedSet}. Other objects are left as-is.
|
18
|
+
#
|
19
|
+
# @example
|
20
|
+
# h = Hamster.from({ "a" => [1, 2], "b" => "c" })
|
21
|
+
# # => Hamster::Hash["a" => Hamster::Vector[1, 2], "b" => "c"]
|
22
|
+
#
|
23
|
+
# @return [Hash, Vector, Set, SortedSet, Object]
|
24
|
+
def from(obj)
|
25
|
+
case obj
|
26
|
+
when ::Hash
|
27
|
+
res = obj.map { |key, value| [from(key), from(value)] }
|
28
|
+
Hamster::Hash.new(res)
|
29
|
+
when Hamster::Hash
|
30
|
+
obj.map { |key, value| [from(key), from(value)] }
|
31
|
+
when ::Struct
|
32
|
+
from(obj.to_h)
|
33
|
+
when ::Array
|
34
|
+
res = obj.map { |element| from(element) }
|
35
|
+
Hamster::Vector.new(res)
|
36
|
+
when ::SortedSet
|
37
|
+
# This clause must go before ::Set clause, since ::SortedSet is a ::Set.
|
38
|
+
res = obj.map { |element| from(element) }
|
39
|
+
Hamster::SortedSet.new(res)
|
40
|
+
when ::Set
|
41
|
+
res = obj.map { |element| from(element) }
|
42
|
+
Hamster::Set.new(res)
|
43
|
+
when Hamster::Vector, Hamster::Set, Hamster::SortedSet
|
44
|
+
obj.map { |element| from(element) }
|
45
|
+
else
|
46
|
+
obj
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# Create a Ruby object from Hamster data. This method recursively "walks"
|
51
|
+
# the Hamster object, converting {Hamster::Hash} to Ruby `Hash`,
|
52
|
+
# {Hamster::Vector} and {Hamster::Deque} to Ruby `Array`, {Hamster::Set}
|
53
|
+
# to Ruby `Set`, and {Hamster::SortedSet} to Ruby `SortedSet`. Other
|
54
|
+
# objects are left as-is.
|
55
|
+
#
|
56
|
+
# @example
|
57
|
+
# h = Hamster.to_ruby(Hamster.from({ "a" => [1, 2], "b" => "c" }))
|
58
|
+
# # => { "a" => [1, 2], "b" => "c" }
|
59
|
+
#
|
60
|
+
# @return [::Hash, ::Array, ::Set, ::SortedSet, Object]
|
61
|
+
def to_ruby(obj)
|
62
|
+
case obj
|
63
|
+
when Hamster::Hash, ::Hash
|
64
|
+
obj.each_with_object({}) { |keyval, hash| hash[to_ruby(keyval[0])] = to_ruby(keyval[1]) }
|
65
|
+
when Hamster::Vector, ::Array
|
66
|
+
obj.each_with_object([]) { |element, arr| arr << to_ruby(element) }
|
67
|
+
when Hamster::Set, ::Set
|
68
|
+
obj.each_with_object(::Set.new) { |element, set| set << to_ruby(element) }
|
69
|
+
when Hamster::SortedSet, ::SortedSet
|
70
|
+
obj.each_with_object(::SortedSet.new) { |element, set| set << to_ruby(element) }
|
71
|
+
when Hamster::Deque
|
72
|
+
obj.to_a.tap { |arr| arr.map! { |element| to_ruby(element) }}
|
73
|
+
else
|
74
|
+
obj
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
data/lib/hamster/set.rb
CHANGED
@@ -1,17 +1,15 @@
|
|
1
|
-
require "forwardable"
|
2
1
|
require "hamster/immutable"
|
3
2
|
require "hamster/undefined"
|
4
3
|
require "hamster/enumerable"
|
4
|
+
require "hamster/hash"
|
5
5
|
require "hamster/trie"
|
6
6
|
require "hamster/sorted_set"
|
7
|
+
require "set"
|
7
8
|
|
8
9
|
module Hamster
|
9
|
-
def self.set(*items)
|
10
|
-
items.empty? ? EmptySet : Set.new(items)
|
11
|
-
end
|
12
10
|
|
13
11
|
# `Hamster::Set` is a collection of unordered values with no duplicates. Testing whether
|
14
|
-
# an object is present in the `Set`
|
12
|
+
# an object is present in the `Set` can be done in constant time. `Set` is also `Enumerable`, so you can
|
15
13
|
# iterate over the members of the set with {#each}, transform them with {#map}, filter
|
16
14
|
# them with {#select}, and so on. Some of the `Enumerable` methods are overridden to
|
17
15
|
# return Hamster collections.
|
@@ -24,15 +22,13 @@ module Hamster
|
|
24
22
|
#
|
25
23
|
# `Set`s have no natural ordering and cannot be compared using `#<=>`. However, they
|
26
24
|
# define {#<}, {#>}, {#<=}, and {#>=} as shorthand for {#proper_subset?},
|
27
|
-
# {#proper_superset?}, {#subset?}, and {#superset?}
|
25
|
+
# {#proper_superset?}, {#subset?}, and {#superset?} respectively.
|
28
26
|
#
|
29
27
|
# The basic set-theoretic operations {#union}, {#intersection}, {#difference}, and
|
30
|
-
# {#exclusion} work with any `Enumerable` object.
|
31
|
-
# with another `Hamster::Set`, or a RubySet.
|
28
|
+
# {#exclusion} work with any `Enumerable` object.
|
32
29
|
#
|
33
|
-
# A `Set` can be created in
|
30
|
+
# A `Set` can be created in either of the following ways:
|
34
31
|
#
|
35
|
-
# Hamster.set('Tom', 'Dick', 'Harry')
|
36
32
|
# Hamster::Set.new([1, 2, 3]) # any Enumerable can be used to initialize
|
37
33
|
# Hamster::Set['A', 'B', 'C', 'D']
|
38
34
|
#
|
@@ -43,8 +39,7 @@ module Hamster
|
|
43
39
|
# actually return a new set and leave the existing one unchanged.
|
44
40
|
#
|
45
41
|
# @example
|
46
|
-
#
|
47
|
-
# set1 = Hamster.set(1, 2) # => Hamster::Set[1, 2]
|
42
|
+
# set1 = Hamster::Set[1, 2] # => Hamster::Set[1, 2]
|
48
43
|
# set2 = Hamster::Set[1, 2] # => Hamster::Set[1, 2]
|
49
44
|
# set1 == set2 # => true
|
50
45
|
# set3 = set1.add("foo") # => Hamster::Set[1, 2, "foo"]
|
@@ -53,7 +48,6 @@ module Hamster
|
|
53
48
|
# set1.subset?(set3) # => true
|
54
49
|
#
|
55
50
|
class Set
|
56
|
-
extend Forwardable
|
57
51
|
include Immutable
|
58
52
|
include Enumerable
|
59
53
|
|
@@ -61,7 +55,7 @@ module Hamster
|
|
61
55
|
# Create a new `Set` populated with the given items.
|
62
56
|
# @return [Set]
|
63
57
|
def [](*items)
|
64
|
-
new(items)
|
58
|
+
items.empty? ? empty : new(items)
|
65
59
|
end
|
66
60
|
|
67
61
|
# Return an empty `Set`. If used on a subclass, returns an empty instance
|
@@ -92,30 +86,35 @@ module Hamster
|
|
92
86
|
def empty?
|
93
87
|
@trie.empty?
|
94
88
|
end
|
95
|
-
def_delegator :self, :empty?, :null?
|
96
89
|
|
97
90
|
# Return the number of items in this `Set`.
|
98
91
|
# @return [Integer]
|
99
92
|
def size
|
100
93
|
@trie.size
|
101
94
|
end
|
102
|
-
|
95
|
+
alias :length :size
|
103
96
|
|
104
97
|
# Return a new `Set` with `item` added. If `item` is already in the set,
|
105
98
|
# return `self`.
|
106
99
|
#
|
100
|
+
# @example
|
101
|
+
# Hamster::Set[1, 2, 3].add(4) # => Hamster::Set[1, 2, 4, 3]
|
102
|
+
# Hamster::Set[1, 2, 3].add(2) # => Hamster::Set[1, 2, 3]
|
103
|
+
#
|
107
104
|
# @param item [Object] The object to add
|
108
105
|
# @return [Set]
|
109
106
|
def add(item)
|
110
107
|
include?(item) ? self : self.class.alloc(@trie.put(item, nil))
|
111
108
|
end
|
112
|
-
|
113
|
-
def_delegator :self, :add, :conj
|
114
|
-
def_delegator :self, :add, :conjoin
|
109
|
+
alias :<< :add
|
115
110
|
|
116
111
|
# If `item` is not a member of this `Set`, return a new `Set` with `item` added.
|
117
112
|
# Otherwise, return `false`.
|
118
113
|
#
|
114
|
+
# @example
|
115
|
+
# Hamster::Set[1, 2, 3].add?(4) # => Hamster::Set[1, 2, 4, 3]
|
116
|
+
# Hamster::Set[1, 2, 3].add?(2) # => false
|
117
|
+
#
|
119
118
|
# @param item [Object] The object to add
|
120
119
|
# @return [Set, false]
|
121
120
|
def add?(item)
|
@@ -125,22 +124,24 @@ module Hamster
|
|
125
124
|
# Return a new `Set` with `item` removed. If `item` is not a member of the set,
|
126
125
|
# return `self`.
|
127
126
|
#
|
127
|
+
# @example
|
128
|
+
# Hamster::Set[1, 2, 3].delete(1) # => Hamster::Set[2, 3]
|
129
|
+
# Hamster::Set[1, 2, 3].delete(99) # => Hamster::Set[1, 2, 3]
|
130
|
+
#
|
128
131
|
# @param item [Object] The object to remove
|
129
132
|
# @return [Set]
|
130
133
|
def delete(item)
|
131
134
|
trie = @trie.delete(item)
|
132
|
-
|
133
|
-
self
|
134
|
-
elsif trie.empty?
|
135
|
-
self.class.empty
|
136
|
-
else
|
137
|
-
self.class.alloc(trie)
|
138
|
-
end
|
135
|
+
new_trie(trie)
|
139
136
|
end
|
140
137
|
|
141
138
|
# If `item` is a member of this `Set`, return a new `Set` with `item` removed.
|
142
139
|
# Otherwise, return `false`.
|
143
140
|
#
|
141
|
+
# @example
|
142
|
+
# Hamster::Set[1, 2, 3].delete?(1) # => Hamster::Set[2, 3]
|
143
|
+
# Hamster::Set[1, 2, 3].delete?(99) # => false
|
144
|
+
#
|
144
145
|
# @param item [Object] The object to remove
|
145
146
|
# @return [Set, false]
|
146
147
|
def delete?(item)
|
@@ -148,9 +149,18 @@ module Hamster
|
|
148
149
|
end
|
149
150
|
|
150
151
|
# Call the block once for each item in this `Set`. No specific iteration order
|
151
|
-
# is guaranteed
|
152
|
+
# is guaranteed, but the order will be stable for any particular `Set`. If
|
153
|
+
# no block is given, an `Enumerator` is returned instead.
|
152
154
|
#
|
153
|
-
# @
|
155
|
+
# @example
|
156
|
+
# Hamster::Set["Dog", "Elephant", "Lion"].each { |e| puts e }
|
157
|
+
# Elephant
|
158
|
+
# Dog
|
159
|
+
# Lion
|
160
|
+
# # => Hamster::Set["Dog", "Elephant", "Lion"]
|
161
|
+
#
|
162
|
+
# @yield [item] Once for each item.
|
163
|
+
# @return [self, Enumerator]
|
154
164
|
def each
|
155
165
|
return to_enum if not block_given?
|
156
166
|
@trie.each { |key, _| yield(key) }
|
@@ -158,8 +168,17 @@ module Hamster
|
|
158
168
|
end
|
159
169
|
|
160
170
|
# Call the block once for each item in this `Set`. Iteration order will be
|
161
|
-
# the opposite of {#each}.
|
171
|
+
# the opposite of {#each}. If no block is given, an `Enumerator` is
|
172
|
+
# returned instead.
|
162
173
|
#
|
174
|
+
# @example
|
175
|
+
# Hamster::Set["Dog", "Elephant", "Lion"].reverse_each { |e| puts e }
|
176
|
+
# Lion
|
177
|
+
# Dog
|
178
|
+
# Elephant
|
179
|
+
# # => Hamster::Set["Dog", "Elephant", "Lion"]
|
180
|
+
#
|
181
|
+
# @yield [item] Once for each item.
|
163
182
|
# @return [self]
|
164
183
|
def reverse_each
|
165
184
|
return enum_for(:reverse_each) if not block_given?
|
@@ -169,65 +188,93 @@ module Hamster
|
|
169
188
|
|
170
189
|
# Return a new `Set` with all the items for which the block returns true.
|
171
190
|
#
|
191
|
+
# @example
|
192
|
+
# Hamster::Set["Elephant", "Dog", "Lion"].select { |e| e.size >= 4 }
|
193
|
+
# # => Hamster::Set["Elephant", "Lion"]
|
194
|
+
# @yield [item] Once for each item.
|
172
195
|
# @return [Set]
|
173
|
-
def
|
174
|
-
return enum_for(:
|
175
|
-
trie = @trie.
|
176
|
-
|
177
|
-
trie.equal?(@trie) ? self : self.class.alloc(trie)
|
196
|
+
def select
|
197
|
+
return enum_for(:select) unless block_given?
|
198
|
+
trie = @trie.select { |key, _| yield(key) }
|
199
|
+
new_trie(trie)
|
178
200
|
end
|
201
|
+
alias :find_all :select
|
202
|
+
alias :keep_if :select
|
179
203
|
|
180
|
-
|
181
|
-
|
182
|
-
#
|
183
|
-
# All the values returned from the block will be gathered into a new `Set`.
|
204
|
+
# Call the block once for each item in this `Set`. All the values returned
|
205
|
+
# from the block will be gathered into a new `Set`. If no block is given,
|
206
|
+
# an `Enumerator` is returned instead.
|
184
207
|
#
|
208
|
+
# @example
|
209
|
+
# Hamster::Set["Cat", "Elephant", "Dog", "Lion"].map { |e| e.size }
|
210
|
+
# # => Hamster::Set[8, 4, 3]
|
211
|
+
#
|
212
|
+
# @yield [item] Once for each item.
|
185
213
|
# @return [Set]
|
186
214
|
def map
|
187
215
|
return enum_for(:map) if not block_given?
|
188
216
|
return self if empty?
|
189
217
|
self.class.new(super)
|
190
218
|
end
|
191
|
-
|
219
|
+
alias :collect :map
|
192
220
|
|
193
221
|
# Return `true` if the given item is present in this `Set`. More precisely,
|
194
222
|
# return `true` if an object with the same `#hash` code, and which is also `#eql?`
|
195
223
|
# to the given object is present.
|
196
224
|
#
|
225
|
+
# @example
|
226
|
+
# Hamster::Set["A", "B", "C"].include?("B") # => true
|
227
|
+
# Hamster::Set["A", "B", "C"].include?("Z") # => false
|
228
|
+
#
|
197
229
|
# @param object [Object] The object to check for
|
198
230
|
# @return [Boolean]
|
199
231
|
def include?(object)
|
200
232
|
@trie.key?(object)
|
201
233
|
end
|
202
|
-
|
234
|
+
alias :member? :include?
|
203
235
|
|
204
236
|
# Return a member of this `Set`. The member chosen will be the first one which
|
205
237
|
# would be yielded by {#each}. If the set is empty, return `nil`.
|
206
238
|
#
|
239
|
+
# @example
|
240
|
+
# Hamster::Set["A", "B", "C"].first # => "C"
|
241
|
+
#
|
207
242
|
# @return [Object]
|
208
243
|
def first
|
209
244
|
(entry = @trie.at(0)) && entry[0]
|
210
245
|
end
|
211
|
-
def_delegator :self, :first, :head
|
212
246
|
|
213
247
|
# Return a {SortedSet} which contains the same items as this `Set`, ordered by
|
214
|
-
# the given comparator block.
|
215
|
-
# return 0, 1, or -1 depending on whether the first parameter is equal, greater than,
|
216
|
-
# or less than the second.
|
248
|
+
# the given comparator block.
|
217
249
|
#
|
218
|
-
# @
|
219
|
-
#
|
250
|
+
# @example
|
251
|
+
# Hamster::Set["Elephant", "Dog", "Lion"].sort
|
252
|
+
# # => Hamster::SortedSet["Dog", "Elephant", "Lion"]
|
253
|
+
# Hamster::Set["Elephant", "Dog", "Lion"].sort { |a,b| a.size <=> b.size }
|
254
|
+
# # => Hamster::SortedSet["Dog", "Lion", "Elephant"]
|
255
|
+
#
|
256
|
+
# @yield [a, b] Any number of times with different pairs of elements.
|
257
|
+
# @yieldreturn [Integer] Negative if the first element should be sorted
|
258
|
+
# lower, positive if the latter element, or 0 if
|
259
|
+
# equal.
|
220
260
|
# @return [SortedSet]
|
221
261
|
def sort(&comparator)
|
222
262
|
SortedSet.new(self.to_a, &comparator)
|
223
263
|
end
|
224
264
|
|
225
|
-
# Return a {SortedSet} which contains the same items as this `Set`, ordered
|
226
|
-
# mapping each item through the provided block to obtain sort keys, and
|
227
|
-
# sorting the keys.
|
265
|
+
# Return a {SortedSet} which contains the same items as this `Set`, ordered
|
266
|
+
# by mapping each item through the provided block to obtain sort keys, and
|
267
|
+
# then sorting the keys.
|
228
268
|
#
|
229
|
-
# @
|
230
|
-
#
|
269
|
+
# @example
|
270
|
+
# Hamster::Set["Elephant", "Dog", "Lion"].sort_by { |e| e.size }
|
271
|
+
# # => Hamster::SortedSet["Dog", "Lion", "Elephant"]
|
272
|
+
#
|
273
|
+
# @yield [item] Once for each item to create the set, and then potentially
|
274
|
+
# again depending on what operations are performed on the
|
275
|
+
# returned {SortedSet}. As such, it is recommended that the
|
276
|
+
# block be a pure function.
|
277
|
+
# @yieldreturn [Object] sort key for the item
|
231
278
|
# @return [SortedSet]
|
232
279
|
def sort_by(&mapper)
|
233
280
|
SortedSet.new(self.to_a, &mapper)
|
@@ -242,22 +289,29 @@ module Hamster
|
|
242
289
|
# @param other [Enumerable] The collection to merge with
|
243
290
|
# @return [Set]
|
244
291
|
def union(other)
|
245
|
-
if other.is_a?(Hamster::Set)
|
246
|
-
|
247
|
-
|
292
|
+
if other.is_a?(Hamster::Set)
|
293
|
+
if other.size > size
|
294
|
+
small_set_pairs = @trie
|
295
|
+
large_set_trie = other.instance_variable_get(:@trie)
|
296
|
+
else
|
297
|
+
small_set_pairs = other.instance_variable_get(:@trie)
|
298
|
+
large_set_trie = @trie
|
299
|
+
end
|
248
300
|
else
|
249
|
-
|
301
|
+
if other.respond_to?(:lazy)
|
302
|
+
small_set_pairs = other.lazy.map { |e| [e, nil] }
|
303
|
+
else
|
304
|
+
small_set_pairs = other.map { |e| [e, nil] }
|
305
|
+
end
|
250
306
|
large_set_trie = @trie
|
251
307
|
end
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
end
|
256
|
-
trie.equal?(@trie) ? self : self.class.alloc(trie)
|
308
|
+
|
309
|
+
trie = large_set_trie.bulk_put(small_set_pairs)
|
310
|
+
new_trie(trie)
|
257
311
|
end
|
258
|
-
|
259
|
-
|
260
|
-
|
312
|
+
alias :| :union
|
313
|
+
alias :+ :union
|
314
|
+
alias :merge :union
|
261
315
|
|
262
316
|
# Return a new `Set` which contains all the items which are members of both
|
263
317
|
# this `Set` and `other`. `other` can be any `Enumerable` object.
|
@@ -268,15 +322,19 @@ module Hamster
|
|
268
322
|
# @param other [Enumerable] The collection to intersect with
|
269
323
|
# @return [Set]
|
270
324
|
def intersection(other)
|
271
|
-
if
|
272
|
-
|
325
|
+
if other.size < @trie.size
|
326
|
+
if other.is_a?(Hamster::Set)
|
327
|
+
trie = other.instance_variable_get(:@trie).select { |key, _| include?(key) }
|
328
|
+
else
|
329
|
+
trie = Trie.new(0)
|
330
|
+
other.each { |obj| trie.put!(obj, nil) if include?(obj) }
|
331
|
+
end
|
273
332
|
else
|
274
|
-
trie = @trie.
|
333
|
+
trie = @trie.select { |key, _| other.include?(key) }
|
275
334
|
end
|
276
|
-
|
335
|
+
new_trie(trie)
|
277
336
|
end
|
278
|
-
|
279
|
-
def_delegator :self, :intersection, :&
|
337
|
+
alias :& :intersection
|
280
338
|
|
281
339
|
# Return a new `Set` with all the items in `other` removed. `other` can be
|
282
340
|
# any `Enumerable` object.
|
@@ -288,15 +346,14 @@ module Hamster
|
|
288
346
|
# @return [Set]
|
289
347
|
def difference(other)
|
290
348
|
trie = if (@trie.size <= other.size) && (other.is_a?(Hamster::Set) || (defined?(::Set) && other.is_a?(::Set)))
|
291
|
-
@trie.
|
349
|
+
@trie.select { |key, _| !other.include?(key) }
|
292
350
|
else
|
293
|
-
|
351
|
+
@trie.bulk_delete(other)
|
294
352
|
end
|
295
|
-
|
353
|
+
new_trie(trie)
|
296
354
|
end
|
297
|
-
|
298
|
-
|
299
|
-
def_delegator :self, :difference, :-
|
355
|
+
alias :subtract :difference
|
356
|
+
alias :- :difference
|
300
357
|
|
301
358
|
# Return a new `Set` which contains all the items which are members of this
|
302
359
|
# `Set` or of `other`, but not both. `other` can be any `Enumerable` object.
|
@@ -309,20 +366,39 @@ module Hamster
|
|
309
366
|
def exclusion(other)
|
310
367
|
((self | other) - (self & other))
|
311
368
|
end
|
312
|
-
|
369
|
+
alias :^ :exclusion
|
313
370
|
|
314
371
|
# Return `true` if all items in this `Set` are also in `other`.
|
315
372
|
#
|
373
|
+
# @example
|
374
|
+
# Hamster::Set[2, 3].subset?(Hamster::Set[1, 2, 3]) # => true
|
375
|
+
#
|
316
376
|
# @param other [Set]
|
317
377
|
# @return [Boolean]
|
318
378
|
def subset?(other)
|
319
379
|
return false if other.size < size
|
380
|
+
|
381
|
+
# This method has the potential to be very slow if 'other' is a large Array, so to avoid that,
|
382
|
+
# we convert those Arrays to Sets before checking presence of items
|
383
|
+
# Time to convert Array -> Set is linear in array.size
|
384
|
+
# Time to check for presence of all items in an Array is proportional to set.size * array.size
|
385
|
+
# Note that both sides of that equation have array.size -- hence those terms cancel out,
|
386
|
+
# and the break-even point is solely dependent on the size of this collection
|
387
|
+
# After doing some benchmarking to estimate the constants, it appears break-even is at ~190 items
|
388
|
+
# We also check other.size, to avoid the more expensive #is_a? checks in cases where it doesn't matter
|
389
|
+
#
|
390
|
+
if other.size >= 150 && @trie.size >= 190 && !(other.is_a?(Hamster::Set) || other.is_a?(::Set))
|
391
|
+
other = ::Set.new(other)
|
392
|
+
end
|
320
393
|
all? { |item| other.include?(item) }
|
321
394
|
end
|
322
395
|
alias :<= :subset?
|
323
396
|
|
324
397
|
# Return `true` if all items in `other` are also in this `Set`.
|
325
398
|
#
|
399
|
+
# @example
|
400
|
+
# Hamster::Set[1, 2, 3].superset?(Hamster::Set[2, 3]) # => true
|
401
|
+
#
|
326
402
|
# @param other [Set]
|
327
403
|
# @return [Boolean]
|
328
404
|
def superset?(other)
|
@@ -333,10 +409,18 @@ module Hamster
|
|
333
409
|
# Returns `true` if `other` contains all the items in this `Set`, plus at least
|
334
410
|
# one item which is not in this set.
|
335
411
|
#
|
412
|
+
# @example
|
413
|
+
# Hamster::Set[2, 3].proper_subset?(Hamster::Set[1, 2, 3]) # => true
|
414
|
+
# Hamster::Set[1, 2, 3].proper_subset?(Hamster::Set[1, 2, 3]) # => false
|
415
|
+
#
|
336
416
|
# @param other [Set]
|
337
417
|
# @return [Boolean]
|
338
418
|
def proper_subset?(other)
|
339
419
|
return false if other.size <= size
|
420
|
+
# See comments above
|
421
|
+
if other.size >= 150 && @trie.size >= 190 && !(other.is_a?(Hamster::Set) || other.is_a?(::Set))
|
422
|
+
other = ::Set.new(other)
|
423
|
+
end
|
340
424
|
all? { |item| other.include?(item) }
|
341
425
|
end
|
342
426
|
alias :< :proper_subset?
|
@@ -344,6 +428,10 @@ module Hamster
|
|
344
428
|
# Returns `true` if this `Set` contains all the items in `other`, plus at least
|
345
429
|
# one item which is not in `other`.
|
346
430
|
#
|
431
|
+
# @example
|
432
|
+
# Hamster::Set[1, 2, 3].proper_superset?(Hamster::Set[2, 3]) # => true
|
433
|
+
# Hamster::Set[1, 2, 3].proper_superset?(Hamster::Set[1, 2, 3]) # => false
|
434
|
+
#
|
347
435
|
# @param other [Set]
|
348
436
|
# @return [Boolean]
|
349
437
|
def proper_superset?(other)
|
@@ -353,19 +441,29 @@ module Hamster
|
|
353
441
|
|
354
442
|
# Return `true` if this `Set` and `other` do not share any items.
|
355
443
|
#
|
444
|
+
# @example
|
445
|
+
# Hamster::Set[1, 2].disjoint?(Hamster::Set[8, 9]) # => true
|
446
|
+
#
|
356
447
|
# @param other [Set]
|
357
448
|
# @return [Boolean]
|
358
449
|
def disjoint?(other)
|
359
|
-
if size
|
360
|
-
each { |item| return false if other.include?(item) }
|
361
|
-
else
|
450
|
+
if other.size <= size
|
362
451
|
other.each { |item| return false if include?(item) }
|
452
|
+
else
|
453
|
+
# See comment on #subset?
|
454
|
+
if other.size >= 150 && @trie.size >= 190 && !(other.is_a?(Hamster::Set) || other.is_a?(::Set))
|
455
|
+
other = ::Set.new(other)
|
456
|
+
end
|
457
|
+
each { |item| return false if other.include?(item) }
|
363
458
|
end
|
364
459
|
true
|
365
460
|
end
|
366
461
|
|
367
462
|
# Return `true` if this `Set` and `other` have at least one item in common.
|
368
463
|
#
|
464
|
+
# @example
|
465
|
+
# Hamster::Set[1, 2].intersect?(Hamster::Set[2, 3]) # => true
|
466
|
+
#
|
369
467
|
# @param other [Set]
|
370
468
|
# @return [Boolean]
|
371
469
|
def intersect?(other)
|
@@ -387,11 +485,14 @@ module Hamster
|
|
387
485
|
end
|
388
486
|
end
|
389
487
|
|
390
|
-
|
391
|
-
|
488
|
+
alias :group :group_by
|
489
|
+
alias :classify :group_by
|
392
490
|
|
393
491
|
# Return a randomly chosen item from this `Set`. If the set is empty, return `nil`.
|
394
492
|
#
|
493
|
+
# @example
|
494
|
+
# Hamster::Set[1, 2, 3, 4, 5].sample # => 3
|
495
|
+
#
|
395
496
|
# @return [Object]
|
396
497
|
def sample
|
397
498
|
empty? ? nil : @trie.at(rand(size))[0]
|
@@ -400,7 +501,7 @@ module Hamster
|
|
400
501
|
# Return an empty `Set` instance, of the same class as this one. Useful if you
|
401
502
|
# have multiple subclasses of `Set` and want to treat them polymorphically.
|
402
503
|
#
|
403
|
-
# @return [
|
504
|
+
# @return [Set]
|
404
505
|
def clear
|
405
506
|
self.class.empty
|
406
507
|
end
|
@@ -419,7 +520,7 @@ module Hamster
|
|
419
520
|
end
|
420
521
|
true
|
421
522
|
end
|
422
|
-
|
523
|
+
alias :== :eql?
|
423
524
|
|
424
525
|
# See `Object#hash`.
|
425
526
|
# @return [Integer]
|
@@ -430,10 +531,6 @@ module Hamster
|
|
430
531
|
undef :"<=>" # Sets are not ordered, so Enumerable#<=> will give a meaningless result
|
431
532
|
undef :each_index # Set members cannot be accessed by 'index', so #each_index is not meaningful
|
432
533
|
|
433
|
-
def_delegator :self, :dup, :uniq
|
434
|
-
def_delegator :self, :dup, :nub
|
435
|
-
def_delegator :self, :dup, :remove_duplicates
|
436
|
-
|
437
534
|
# Return `self`.
|
438
535
|
#
|
439
536
|
# @return [self]
|
@@ -456,11 +553,24 @@ module Hamster
|
|
456
553
|
trie.put(key_value.first, nil)
|
457
554
|
end
|
458
555
|
end
|
556
|
+
|
557
|
+
private
|
558
|
+
|
559
|
+
def new_trie(trie)
|
560
|
+
if trie.empty?
|
561
|
+
self.class.empty
|
562
|
+
elsif trie.equal?(@trie)
|
563
|
+
self
|
564
|
+
else
|
565
|
+
self.class.alloc(trie)
|
566
|
+
end
|
567
|
+
end
|
459
568
|
end
|
460
569
|
|
461
|
-
# The canonical empty `Set`. Returned by `
|
570
|
+
# The canonical empty `Set`. Returned by `Set[]` when
|
462
571
|
# invoked with no arguments; also returned by `Set.empty`. Prefer using this
|
463
572
|
# one rather than creating many empty sets using `Set.new`.
|
464
573
|
#
|
574
|
+
# @private
|
465
575
|
EmptySet = Hamster::Set.empty
|
466
576
|
end
|