aboutsummaryrefslogtreecommitdiff
path: root/lib/Hash/Merge.pm6
blob: 607e17b8854e077b912410063b66b363b48f6fdf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#! /usr/bin/env false

use v6.c;

unit module Hash::Merge;

#| Merge any number of Hashes together.
sub merge-hashes(
    *@hashes, #= Hashes to merge together
    --> Hash
) is export {
    my %merge-into = @hashes.shift;

    # Nothing to do if we only got 1 argument
    return %merge-into unless @hashes.elems;

    for ^@hashes.elems {
        %merge-into = merge-hash(%merge-into, @hashes.shift);
    }

    %merge-into;
}

#| Merge two hashes together.
sub merge-hash(
    %merge-into,   #= The original Hash that should be merged into.
    %merge-source, #= Another Hash to merge into the original Hash.
    Bool:D :$no-append-array = False,
    --> Hash
) is export {
    for %merge-source.keys -> $key {
        if %merge-into{$key}:exists {
            given %merge-source{$key} {
                when Hash {
                    merge-hash(%merge-into{$key}, %merge-source{$key}, :$no-append-array);
                }
                when Positional {
                    %merge-into{$key} = $no-append-array
                    ?? %merge-source{$key}
                    !!
                    do {
                        my @a;
                        @a.push: $_ for %merge-into{$key}.list;
                        @a.push: $_ for %merge-source{$key}.list;
                        @a;
                    }
                }
                default {
                    %merge-into{$key} = %merge-source{$key}
                }
            }
        } else {
            %merge-into{$key} = %merge-source{$key};
        }
    }

    %merge-into;
}

# vim: ft=perl6 ts=4 sw=4 et