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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
|
#! /usr/bin/env false
use v6.d;
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 (
#| The original Hash to merge the second Hash into.
%first,
#| The second hash, which will be merged into the first Hash.
%second,
#| Boolean to set whether Associative objects should be merged on their
#| own. When set to False, Associative objects in %second will
#| overwrite those from %first.
Bool:D :$deep = True,
#| Boolean to set whether Positional objects should be appended. When
#| set to False, Positional objects in %second will overwrite those
#| from %first.
Bool:D :$positional-append = True,
--> Hash
) is export {
my %result = %first;
for %second.keys -> $key {
# If the key doesn't exist yet in %first, it can be inserted without worry.
if (%first{$key}:!exists) {
%result{$key} = %second{$key};
next;
}
given (%first{$key}) {
# Associative objects need to be merged deeply.
when Associative {
%result{$key} = $deep
?? merge-hash(%first{$key}, %second{$key}, :$deep, :$positional-append)
!! %second{$key}
}
# Positional objects can be merged or overwritten depending on $append-array.
when Positional {
%result{$key} = $positional-append
?? (|%first{$key}, |%second{$key})
!! %second{$key}
}
# Anything else will just overwrite.
default {
%result{$key} = %second{$key};
}
}
}
%result;
}
# vim: ft=perl6 ts=4 sw=4 et
|