diff options
-rw-r--r-- | lib/mergehash.pm6 | 28 | ||||
-rw-r--r-- | t/01-thing.t | 21 |
2 files changed, 32 insertions, 17 deletions
diff --git a/lib/mergehash.pm6 b/lib/mergehash.pm6 index cc9b9cb..1db7e60 100644 --- a/lib/mergehash.pm6 +++ b/lib/mergehash.pm6 @@ -1,24 +1,32 @@ use MONKEY; augment class Hash { - method merge (%b) { - hashmerge self, %b; + #|Merges one a second hash into the hash the method is called on + #|Traverses the full tree, replacing items in the original hash with the + #|hash given in the argument. Does not replace positional elements by default, + #|and instead appends the items from the supplied hash's array to the original + #| hash's array. Use :no-append-array to replace arrays and positionals instead + #|The object type of positionals is not retained and instead becomes an Array type + method merge (%b; Bool:D :$no-append-array = False) { + hashmerge self, %b, :$no-append-array; } - sub hashmerge (%merge-into, %merge-source) { + sub hashmerge (%merge-into, %merge-source, Bool:D :$no-append-array) { for %merge-source.keys -> $key { if %merge-into{$key}:exists { if %merge-source{$key} ~~ Hash { - hashmerge %merge-into{$key}, %merge-source{$key}; + hashmerge %merge-into{$key}, %merge-source{$key}, :$no-append-array; } elsif %merge-source{$key} ~~ Positional { - my @a; - for %merge-into{$key}.list { - @a.push: $_; + if $no-append-array { + %merge-into{$key} = %merge-source{$key}; } - for %merge-source{$key}.list { - @a.push: $_; + else { + my @a; + @a.push: $_ for %merge-into{$key}.list; + @a.push: $_ for %merge-source{$key}.list; + %merge-into{$key} = @a; } - %merge-into{$key} = @a; } + # Non-positionals, so strings or Bools or whatever else { %merge-into{$key} = %merge-source{$key}; } diff --git a/t/01-thing.t b/t/01-thing.t index 402c157..68b092e 100644 --- a/t/01-thing.t +++ b/t/01-thing.t @@ -25,12 +25,19 @@ is-deeply %a, {:a(2), :b(1), :y(${:a(1), :z(2)})}; %a.merge(%b); is-deeply %a, {Z => 'new', a => 2, b => 1, y => {a => 1, z => 2}}; - -my (%z, %y); -%z<y><p> = (1,2,3,4); -%y<y><p> = (5,4,6,7); -%z.merge(%y); -is %z, {y => {p => [1, 2, 3, 4, 5, 4, 6, 7]}}, "merges arrays"; - +{ + my (%z, %y); + %z<y><p> = (1,2,3,4); + %y<y><p> = (5,4,6,7); + %z.merge(%y); + is %z, {y => {p => [1, 2, 3, 4, 5, 4, 6, 7]}}, "appends arrays"; +} +{ + my (%z, %y); + %z<y><p> = (1,2,3,4); + %y<y><p> = (5,4,6,7); + %z.merge(%y, :no-append-array); + is-deeply %z, ${:y(${:p($(5, 4, 6, 7))})}, "no-append-array (replaces the instead)"; +} done-testing; |