Hash-Merge-Simple-0.051000755000765000024 011477513615 13746 5ustar00robstaff000000000000README000644000765000024 722311477513615 14712 0ustar00robstaff000000000000Hash-Merge-Simple-0.051NAME Hash::Merge::Simple - Recursively merge two or more hashes, simply VERSION version 0.051 SYNOPSIS use Hash::Merge::Simple qw/ merge /; my $a = { a => 1 }; my $b = { a => 100, b => 2}; # Merge with righthand hash taking precedence my $c = merge $a, $b; # $c is { a => 100, b => 2 } ... Note: a => 100 has overridden => 1 # Also, merge will take care to recursively merge any subordinate hashes found my $a = { a => 1, c => 3, d => { i => 2 }, r => {} }; my $b = { b => 2, a => 100, d => { l => 4 } }; my $c = merge $a, $b; # $c is { a => 100, b => 2, c => 3, d => { i => 2, l => 4 }, r => {} } # You can also merge more than two hashes at the same time # The precedence increases from left to right (the rightmost has the most precedence) my $everything = merge $this, $that, $mine, $yours, $kitchen_sink, ...; DESCRIPTION Hash::Merge::Simple will recursively merge two or more hashes and return the result as a new hash reference. The merge function will descend and merge hashes that exist under the same node in both the left and right hash, but doesn't attempt to combine arrays, objects, scalars, or anything else. The rightmost hash also takes precedence, replacing whatever was in the left hash if a conflict occurs. This code was pretty much taken straight from Catalyst::Utils, and modified to handle more than 2 hashes at the same time. USAGE Hash::Merge::Simple->merge( , , , ..., ) Hash::Merge::Simple::merge( , , , ..., ) Merge through , with the nth-most (rightmost) hash taking precedence. Returns a new hash reference representing the merge. NOTE: The code does not currently check for cycles, so infinite loops are possible: my $a = {}; $a->{b} = $a; merge $a, $a; NOTE: If you want to avoid giving/receiving side effects with the merged result, use "clone_merge" or "dclone_merge" An example of this problem (thanks Uri): my $left = { a => { b => 2 } } ; my $right = { c => 4 } ; my $result = merge( $left, $right ) ; $left->{a}{b} = 3 ; $left->{a}{d} = 5 ; # $result->{a}{b} == 3 ! # $result->{a}{d} == 5 ! Hash::Merge::Simple->clone_merge( , , , ..., ) Hash::Merge::Simple::clone_merge( , , , ..., ) Perform a merge, clone the merge, and return the result This is useful in cases where you need to ensure that the result can be tweaked without fear of giving/receiving any side effects This method will use Clone to do the cloning Hash::Merge::Simple->dclone_merge( , , , ..., ) Hash::Merge::Simple::dclone_merge( , , , ..., ) Perform a merge, clone the merge, and return the result This is useful in cases where you need to ensure that the result can be tweaked without fear of giving/receiving any side effects This method will use Storable (dclone) to do the cloning SEE ALSO Hash::Merge Catalyst::Utils Clone Storable ACKNOWLEDGEMENTS This code was pretty much taken directly from Catalyst::Utils: Sebastian Riedel "sri@cpan.org" Yuval Kogman "nothingmuch@woobling.org" AUTHOR Robert Krimen COPYRIGHT AND LICENSE This software is copyright (c) 2010 by Robert Krimen. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. Changes000644000765000024 163611477513615 15327 0ustar00robstaff000000000000Hash-Merge-Simple-0.051TODO: - merge => _merge - merge( clone => ... - merge( dclone / deep_clone / storable_clone => ... - merge( [] ) # Transform even-element array into a hash - merge( [], [], ... ) # Merge even-element arrays (at the top level only) 0.051 Tuesday December 07 12:21:04 PST 2010: - Duh, require Exporter. Thanks, EVERYBODY/KENTNL 0.050 Thursday May 13 11:24:29 PDT 2010: - Conversion to Dist::Zilla (Dzpl), losing auto_install 0.04 Saturday February 21 23:22:34 PST 2009: - Addressed bug 41738: https://rt.cpan.org/Ticket/Display.html?id=41738 (thanks Uri) - Updated boilerplate and Makefile.PL - Conversion of repository to git (github) 0.03 Sunday May 04 02:39:59 PDT 2008: - Tweak acknowledgements - Reference Hash::Merge in SEE ALSO 0.02 Wednesday April 23 14:34:59 PDT 2008: - Minor documentation tweak 0.01 Monday April 21 22:12:45 PDT 2008: - Initial release META.yml000644000765000024 73211477513615 15261 0ustar00robstaff000000000000Hash-Merge-Simple-0.051--- abstract: 'Recursively merge two or more hashes, simply' author: - 'Robert Krimen ' build_requires: Test::Most: 0 configure_requires: ExtUtils::MakeMaker: 6.31 dynamic_config: 0 generated_by: 'Dist::Zilla version 4.102345, CPAN::Meta::Converter version 2.102400' license: perl meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: 1.4 name: Hash-Merge-Simple requires: Clone: 0 Storable: 0 version: 0.051 MANIFEST000644000765000024 21211477513615 15132 0ustar00robstaff000000000000Hash-Merge-Simple-0.051Changes MANIFEST META.yml Makefile.PL README lib/Hash/Merge/Simple.pm t/00-load.t t/01-basic.t t/9000-bug-41738-merge-with-side-effects.t t000755000765000024 011477513615 14132 5ustar00robstaff000000000000Hash-Merge-Simple-0.05100-load.t000644000765000024 24711477513615 15575 0ustar00robstaff000000000000Hash-Merge-Simple-0.051/t#!perl -T use Test::More tests => 1; BEGIN { use_ok( 'Hash::Merge::Simple' ); } diag( "Testing Hash::Merge::Simple $Hash::Merge::Simple::VERSION, Perl $], $^X" ); Makefile.PL000644000765000024 204611477513615 16002 0ustar00robstaff000000000000Hash-Merge-Simple-0.051 use strict; use warnings; use ExtUtils::MakeMaker 6.31; my %WriteMakefileArgs = ( 'ABSTRACT' => 'Recursively merge two or more hashes, simply', 'AUTHOR' => 'Robert Krimen ', 'BUILD_REQUIRES' => { 'Test::Most' => '0' }, 'CONFIGURE_REQUIRES' => { 'ExtUtils::MakeMaker' => '6.31' }, 'DISTNAME' => 'Hash-Merge-Simple', 'EXE_FILES' => [], 'LICENSE' => 'perl', 'NAME' => 'Hash::Merge::Simple', 'PREREQ_PM' => { 'Clone' => '0', 'Storable' => '0' }, 'VERSION' => '0.051', 'test' => { 'TESTS' => 't/*.t' } ); unless ( eval { ExtUtils::MakeMaker->VERSION(6.56) } ) { my $br = delete $WriteMakefileArgs{BUILD_REQUIRES}; my $pp = $WriteMakefileArgs{PREREQ_PM}; for my $mod ( keys %$br ) { if ( exists $pp->{$mod} ) { $pp->{$mod} = $br->{$mod} if $br->{$mod} > $pp->{$mod}; } else { $pp->{$mod} = $br->{$mod}; } } } delete $WriteMakefileArgs{CONFIGURE_REQUIRES} unless eval { ExtUtils::MakeMaker->VERSION(6.52) }; WriteMakefile(%WriteMakefileArgs); 01-basic.t000644000765000024 200511477513615 15752 0ustar00robstaff000000000000Hash-Merge-Simple-0.051/tuse Test::More; use Test::Deep; plan qw/no_plan/; use Hash::Merge::Simple qw/merge/; { my $a = { a => 1 }; my $b = { a => 100, b => 2}; my $c = merge $a, $b; ok($c); cmp_deeply($c, { a => 100, b => 2 }); } { my $a = { a => 1, c => 3, d => { i => 2 }, r => {} }; my $b = { b => 2, a => 100, d => { l => 4 } }; my $c = merge $a, $b; ok($c); cmp_deeply($c, { a => 100, b => 2, c => 3, d => { i => 2, l => 4 }, r => {} }); } { cmp_deeply(merge({ a => 1 }, { a => 2 }, { a => 3 }, { a => 4 }, { a => 5 }), { a => 5 }); cmp_deeply(merge({ a => 1, b => [] }, { a => 2 }, { a => 3 }, { a => 4 }, { a => 5 }), { a => 5, b => [] }); cmp_deeply(merge({ a => 1, b => [ 3 ] }, { a => 2 }, { a => 3 }, { a => 4, b => [ 8 ] }, { a => 5 }), { a => 5, b => [ 8 ] }); cmp_deeply(merge({ a => 1 }, { b => 2 }, { c => 3 }, { d => 4 }, { e => 5 }), { qw/a 1 b 2 c 3 d 4 e 5/ }); } if (0) { exit; # Infinity-ty-ty-ty-ty my $a = {}; $a->{b} = $a; merge $a, $a; } Merge000755000765000024 011477513615 16357 5ustar00robstaff000000000000Hash-Merge-Simple-0.051/lib/HashSimple.pm000644000765000024 1133111477513615 20324 0ustar00robstaff000000000000Hash-Merge-Simple-0.051/lib/Hash/Mergepackage Hash::Merge::Simple; BEGIN { $Hash::Merge::Simple::VERSION = '0.051'; } # ABSTRACT: Recursively merge two or more hashes, simply use warnings; use strict; use vars qw/ @ISA @EXPORT_OK /; require Exporter; @ISA = qw/ Exporter /; @EXPORT_OK = qw/ merge clone_merge dclone_merge /; # This was stoled from Catalyst::Utils... thanks guys! sub merge (@); sub merge (@) { shift unless ref $_[0]; # Take care of the case we're called like Hash::Merge::Simple->merge(...) my ($left, @right) = @_; return $left unless @right; return merge($left, merge(@right)) if @right > 1; my ($right) = @right; my %merge = %$left; for my $key (keys %$right) { my ($hr, $hl) = map { ref $_->{$key} eq 'HASH' } $right, $left; if ($hr and $hl){ $merge{$key} = merge($left->{$key}, $right->{$key}); } else { $merge{$key} = $right->{$key}; } } return \%merge; } sub clone_merge { require Clone; my $result = merge @_; return Clone::clone( $result ); } sub dclone_merge { require Storable; my $result = merge @_; return Storable::dclone( $result ); } 1; __END__ =pod =head1 NAME Hash::Merge::Simple - Recursively merge two or more hashes, simply =head1 VERSION version 0.051 =head1 SYNOPSIS use Hash::Merge::Simple qw/ merge /; my $a = { a => 1 }; my $b = { a => 100, b => 2}; # Merge with righthand hash taking precedence my $c = merge $a, $b; # $c is { a => 100, b => 2 } ... Note: a => 100 has overridden => 1 # Also, merge will take care to recursively merge any subordinate hashes found my $a = { a => 1, c => 3, d => { i => 2 }, r => {} }; my $b = { b => 2, a => 100, d => { l => 4 } }; my $c = merge $a, $b; # $c is { a => 100, b => 2, c => 3, d => { i => 2, l => 4 }, r => {} } # You can also merge more than two hashes at the same time # The precedence increases from left to right (the rightmost has the most precedence) my $everything = merge $this, $that, $mine, $yours, $kitchen_sink, ...; =head1 DESCRIPTION Hash::Merge::Simple will recursively merge two or more hashes and return the result as a new hash reference. The merge function will descend and merge hashes that exist under the same node in both the left and right hash, but doesn't attempt to combine arrays, objects, scalars, or anything else. The rightmost hash also takes precedence, replacing whatever was in the left hash if a conflict occurs. This code was pretty much taken straight from L, and modified to handle more than 2 hashes at the same time. =head1 USAGE =head2 Hash::Merge::Simple->merge( , , , ..., ) =head2 Hash::Merge::Simple::merge( , , , ..., ) Merge through , with the nth-most (rightmost) hash taking precedence. Returns a new hash reference representing the merge. NOTE: The code does not currently check for cycles, so infinite loops are possible: my $a = {}; $a->{b} = $a; merge $a, $a; NOTE: If you want to avoid giving/receiving side effects with the merged result, use C or C An example of this problem (thanks Uri): my $left = { a => { b => 2 } } ; my $right = { c => 4 } ; my $result = merge( $left, $right ) ; $left->{a}{b} = 3 ; $left->{a}{d} = 5 ; # $result->{a}{b} == 3 ! # $result->{a}{d} == 5 ! =head2 Hash::Merge::Simple->clone_merge( , , , ..., ) =head2 Hash::Merge::Simple::clone_merge( , , , ..., ) Perform a merge, clone the merge, and return the result This is useful in cases where you need to ensure that the result can be tweaked without fear of giving/receiving any side effects This method will use L to do the cloning =head2 Hash::Merge::Simple->dclone_merge( , , , ..., ) =head2 Hash::Merge::Simple::dclone_merge( , , , ..., ) Perform a merge, clone the merge, and return the result This is useful in cases where you need to ensure that the result can be tweaked without fear of giving/receiving any side effects This method will use L (dclone) to do the cloning =head1 SEE ALSO L L L L =head1 ACKNOWLEDGEMENTS This code was pretty much taken directly from L: Sebastian Riedel C Yuval Kogman C =head1 AUTHOR Robert Krimen =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2010 by Robert Krimen. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut 9000-bug-41738-merge-with-side-effects.t000644000765000024 231411477513615 22712 0ustar00robstaff000000000000Hash-Merge-Simple-0.051/tuse strict; use warnings; use Test::Most; use Test::Deep; plan qw/no_plan/; #use Data::Dump qw/dump/; #print dump($left), "\n"; #print dump($merged), "\n"; use Hash::Merge::Simple qw/merge clone_merge dclone_merge/; my ($left, $right, $result); SKIP: { eval "require Clone;" or skip "Clone required for this test"; $left = { foo => { bar => 2 } }; $right = { baz => 4 }; $result = clone_merge( $left, $right ); $left->{foo}{bar} = 3 ; $left->{foo}{aaa} = 5 ; cmp_deeply $left, { foo => { bar => 3, aaa => 5 } }; cmp_deeply $result, { foo => { bar => 2 }, baz => 4 }; } SKIP: { eval "require Storable;" or skip "Storable required for this test"; $left = { foo => { bar => 2 } }; $right = { baz => 4 }; $result = dclone_merge( $left, $right ); $left->{foo}{bar} = 3 ; $left->{foo}{aaa} = 5 ; cmp_deeply $left, { foo => { bar => 3, aaa => 5 } }; cmp_deeply $result, { foo => { bar => 2 }, baz => 4 }; } $left = { foo => { bar => 2 } }; $right = { baz => 4 }; $result = merge( $left, $right ); $left->{foo}{bar} = 3 ; $left->{foo}{aaa} = 5 ; cmp_deeply $left, { foo => { bar => 3, aaa => 5 } }; cmp_deeply $result, { foo => { aaa => 5, bar => 3 }, baz => 4 };