File Coverage

blib/lib/Hash/Map.pm
Criterion Covered Total %
statement 21 21 100.0
branch n/a
condition n/a
subroutine 7 7 100.0
pod n/a
total 28 28 100.0


line stmt bran cond sub pod time code
1             package Hash::Map; ## no critic (TidyCode)
2              
3 3     3   485130 use strict;
  3         4  
  3         70  
4 3     3   10 use warnings;
  3         4  
  3         72  
5              
6 3     3   9 use Carp qw(confess);
  3         7  
  3         112  
7 3     3   1090 use Clone qw(clone);
  3         5527  
  3         141  
8 3     3   14 use Scalar::Util qw(blessed);
  3         4  
  3         94  
9 3     3   828 use Try::Tiny;
  3         3130  
  3         153  
10              
11             our $VERSION = '0.015';
12              
13 3     3   727 use parent qw( Exporter::Tiny );
  3         408  
  3         13  
14              
15             our @EXPORT_OK = qw(
16             hashref_map
17             hash_map
18             );
19              
20             sub new {
21             return bless
22             {
23             source => {},
24             target => {},
25             },
26             shift;
27             }
28              
29             sub _hashref {
30             my ($self, $key, $hashref) = @_;
31              
32             if ( defined $hashref ) {
33             ref $hashref eq 'HASH'
34             or confess 'Hash reference expected';
35             if ( ! blessed $self ) {
36             $self = $self->new; # this method used as constructor
37             }
38             $self->{$key} = $hashref;
39             return $self;
40             }
41              
42             return $self->{$key};
43             }
44              
45             sub _hash {
46             my ($self, $key, @more) = @_;
47              
48             @more
49             and return $self->_set_hash($key, @more);
50              
51             return %{ $self->_hashref($key) };
52             }
53              
54             sub _set_hash {
55             my ($self, $key, @more) = @_;
56              
57             my $hashref;
58             try {
59             $hashref = { @more };
60             }
61             catch {
62             confess 'Hash expected ', $_;
63             };
64             if ( ! blessed $self ) {
65             $self = $self->new; # this method used as constructor
66             }
67             $self->_hashref($key, $hashref);
68              
69             return $self;
70             }
71              
72             ## no critic (ArgUnpacking);
73             sub source_ref { return shift->_hashref(source => @_) }
74             sub target_ref { return shift->_hashref(target => @_) }
75             sub set_source_ref { return shift->_hashref(source => @_) }
76             sub set_target_ref { return shift->_hashref(target => @_) }
77             sub source { return shift->_hash(source => @_) }
78             sub target { return shift->_hash(target => @_) }
79             sub set_source { return shift->_set_hash(source => @_) }
80             sub set_target { return shift->_set_hash(target => @_) }
81              
82             sub source_keys { return keys %{ shift->source_ref } }
83             sub target_keys { return keys %{ shift->target_ref } }
84             sub source_values { return values %{ shift->source_ref } }
85             sub target_values { return values %{ shift->target_ref } }
86              
87             sub source_keys_ref { return [ shift->source_keys ] }
88             sub target_keys_ref { return [ shift->target_keys ] }
89             sub source_values_ref { return [ shift->source_values ] }
90             sub target_values_ref { return [ shift->target_values ] }
91              
92             sub exists_source { return exists shift->source_ref->{ ( shift )} }
93             sub exists_target { return exists shift->target_ref->{ ( shift ) } }
94             ## use critic (ArgUnpacking);
95              
96             sub combine {
97             my ($self, @hash_maps) = @_;
98              
99             if ( ! blessed $self ) {
100             $self = $self->new; # this method used as constructor
101             }
102             for my $hash_map (@hash_maps) {
103             $self->merge_hashref( $hash_map->target_ref );
104             }
105              
106             return $self;
107             }
108              
109             sub clone_source {
110             my $self = shift;
111              
112             $self->source_ref( clone( $self->source_ref ) );
113              
114             return $self;
115             }
116              
117             sub clone_target {
118             my $self = shift;
119              
120             $self->target_ref( clone( $self->target_ref ) );
121              
122             return $self;
123             }
124              
125             sub delete_keys_ref {
126             my ($self, $keys_ref) = @_;
127              
128             ref $keys_ref eq 'ARRAY'
129             or confess 'Array reference expected';
130             delete @{ $self->target_ref }{ @{$keys_ref} };
131              
132             return $self;
133             }
134              
135             sub delete_keys {
136             my ($self, @keys) = @_;
137              
138             return $self->delete_keys_ref(\@keys);
139             }
140              
141             # begin from source to target
142              
143             sub copy_keys_ref {
144             my ($self, $keys_ref, $code_ref) = @_;
145              
146             ref $keys_ref eq 'ARRAY'
147             or confess 'Array reference expected';
148             if ( ref $code_ref eq 'CODE' ) {
149             return $self->map_keys_ref({
150             map { ## no critic (MutatingListFunctions VoidMap)
151             $_ => do {
152             local $_ = $_;
153             scalar $code_ref->($self);
154             };
155             } @{$keys_ref}
156             });
157             }
158              
159             @{ $self->target_ref }{ @{$keys_ref} }
160             = @{ $self->source_ref }{ @{$keys_ref} };
161              
162             return $self;
163             }
164              
165             sub copy_keys {
166             my ($self, @keys) = @_;
167              
168             if ( @keys && ref $keys[-1] eq 'CODE' ) {
169             my $code_ref = pop @keys;
170             return $self->map_keys_ref({
171             map { ## no critic (MutatingListFunctions VoidMap)
172             $_ => do {
173             local $_ = $_;
174             scalar $code_ref->($self);
175             };
176             } @keys
177             });
178             }
179              
180             return $self->copy_keys_ref(\@keys);
181             }
182              
183             sub map_keys_ref {
184             my ($self, $map_ref) = @_;
185              
186             ref $map_ref eq 'HASH'
187             or confess 'Hash reference expected';
188             @{ $self->target_ref }{ values %{$map_ref} }
189             = @{ $self->source_ref }{ keys %{$map_ref} };
190              
191             return $self;
192             }
193              
194             sub map_keys {
195             my ($self, @more) = @_;
196              
197             my $map_ref;
198             try {
199             $map_ref = { @more };
200             }
201             catch {
202             confess 'Hash expected ', $_;
203             };
204              
205             return $self->map_keys_ref($map_ref);
206             }
207              
208             # begin copy from source to target
209              
210             sub merge_hashref {
211             my ($self, $hashref) = @_;
212              
213             ref $hashref eq 'HASH'
214             or confess 'Hash reference expected';
215             @{ $self->target_ref }{ keys %{$hashref} } = values %{$hashref};
216              
217             return $self;
218             }
219              
220             sub merge_hash {
221             my ($self, @more) = @_;
222              
223             my $hashref;
224             try {
225             $hashref = { @more };
226             }
227             catch {
228             confess 'Hash expected ', $_;
229             };
230              
231             return $self->merge_hashref($hashref);
232             }
233              
234             sub modify_ref {
235             my ($self, $modify_ref) = @_;
236              
237             ref $modify_ref eq 'HASH'
238             or confess 'Hash reference expected';
239             my $target_ref = $self->target_ref;
240             while ( my ($key, $code_ref) = each %{$modify_ref} ) {
241             local $_ = $target_ref->{$key};
242             $target_ref->{$key} = $code_ref->($self);
243             }
244              
245             return $self;
246             }
247              
248             # end copy from source to target
249              
250             sub modify {
251             my ($self, @more) = @_;
252              
253             my $modify_ref;
254             try {
255             $modify_ref = { @more };
256             }
257             catch {
258             confess 'Hash expected ', $_;
259             };
260              
261             return $self->modify_ref($modify_ref);
262             }
263              
264             # begin copy from source to target
265              
266             sub copy_modify_ref {
267             my ($self, $copy_modify_ref) = @_;
268              
269             ref $copy_modify_ref eq 'HASH'
270             or confess 'Hash reference expected';
271             $self->copy_keys( keys %{$copy_modify_ref} );
272              
273             return $self->modify_ref($copy_modify_ref);
274             }
275              
276             sub copy_modify {
277             my ($self, @more) = @_;
278              
279             my $copy_modify_ref;
280             try {
281             $copy_modify_ref = { @more };
282             }
283             catch {
284             confess 'Hash expected ', $_;
285             };
286              
287             return $self->copy_modify_ref($copy_modify_ref);
288             }
289              
290             sub copy_modify_identical_ref {
291             my ($self, $keys_ref, $code_ref) = @_;
292              
293             ref $keys_ref eq 'ARRAY'
294             or confess 'Array reference for keys expected';
295             ref $code_ref eq 'CODE'
296             or confess 'Code reference for modify expected';
297             my $source_ref = $self->source_ref;
298             my $target_ref = $self->target_ref;
299             for my $key ( @{$keys_ref} ) {
300             $target_ref->{$key} = $source_ref->{$key};
301             local $_ = $target_ref->{$key};
302             $target_ref->{$key} = $code_ref->($self, $key);
303             }
304              
305             return $self;
306             }
307              
308             sub copy_modify_identical {
309             my ($self, @keys) = @_;
310              
311             my $code_ref = pop @keys;
312             ref $code_ref eq 'CODE'
313             or confess 'Code reference as last parameter expected';
314              
315             return $self->copy_modify_identical_ref(\@keys, $code_ref);
316             }
317              
318             sub map_modify_ref {
319             my ($self, $map_modify_ref) = @_;
320              
321             ref $map_modify_ref eq 'ARRAY'
322             or confess 'Array reference expected';
323              
324             @{$map_modify_ref} % 3 ## no critic (MagicNumber)
325             and confess
326             scalar @{$map_modify_ref},
327             ' elements in array are not a group of 3';
328             my @map_modify = @{$map_modify_ref};
329             my $source_ref = $self->source_ref;
330             my $target_ref = $self->target_ref;
331             while ( my ($source_key, $target_key, $code_ref) = splice @map_modify, 0, 3 ) { ## no critic (MagicNumber)
332             $target_ref->{$target_key} = $source_ref->{$source_key};
333             local $_ = $target_ref->{$target_key};
334             $target_ref->{$target_key} = $code_ref->($self);
335             };
336              
337             return $self;
338             }
339              
340             sub map_modify {
341             my ($self, @map_modify) = @_;
342              
343             return $self->map_modify_ref(\@map_modify);
344             }
345              
346             sub map_modify_identical_ref {
347             my ($self, $hash_ref, $code_ref) = @_;
348              
349             ref $hash_ref eq 'HASH'
350             or confess 'Hash reference expected';
351             ref $code_ref eq 'CODE'
352             or confess 'Code reference as last parameter expected';
353             my $source_ref = $self->source_ref;
354             my $target_ref = $self->target_ref;
355             while ( my ($source_key, $target_key) = each %{$hash_ref} ) {
356             $target_ref->{$target_key} = $source_ref->{$source_key};
357             local $_ = $target_ref->{$target_key};
358             $target_ref->{$target_key} = $code_ref->($self, $source_key, $target_key);
359             };
360              
361             return $self;
362             }
363              
364             sub map_modify_identical {
365             my ($self, @map_modify) = @_;
366              
367             my $code_ref = pop @map_modify;
368             @map_modify % 2
369             and confess
370             scalar @map_modify,
371             ' elements in array are not pairwise';
372             ref $code_ref eq 'CODE'
373             or confess 'Code reference as last parameter expected';
374              
375             return $self->map_modify_identical_ref({ @map_modify }, $code_ref);
376             }
377              
378             # end copy from source to target
379              
380             # begin iterator stuff
381              
382             sub each_source { return each %{ shift->source_ref } }
383             sub each_target { return each %{ shift->target_ref } }
384              
385             sub source_iterator {
386             my $self = shift;
387              
388             return sub {
389             return $self->each_source;
390             };
391             }
392              
393             sub target_iterator {
394             my $self = shift;
395              
396             return sub {
397             return $self->each_target;
398             };
399             }
400              
401             # end iterator stuff
402              
403             sub hashref_map {
404             my ($source_ref, @more) = @_;
405              
406             my $self = Hash::Map->source_ref($source_ref);
407             ITEM:
408             for my $item (@more) {
409             if ( ref $item eq 'ARRAY' ) {
410             $self->copy_keys( @{$item} );
411             next ITEM;
412             }
413             if ( ref $item eq 'HASH' ) {
414             while ( my ($key, $value) = each %{$item} ) {
415             ref $value eq 'CODE'
416             ? $self->modify($key, $value)
417             : $self->map_keys($key, $value);
418             }
419             next ITEM;
420             }
421             confess 'Array- or hash reference expected';
422             }
423              
424             return $self->target_ref;
425             }
426              
427             sub hash_map { ## no critic (ArgUnpacking)
428             return %{ hashref_map(@_) };
429             }
430              
431             # $Id$
432              
433             1;
434              
435             __END__
436              
437             =head1 NAME
438              
439             Hash::Map - Manipulate hashes map like
440              
441             =head1 VERSION
442              
443             0.014
444              
445             =head1 SYNOPSIS
446              
447             require Hash::Map;
448              
449             Instead of
450              
451             %hash = (
452             a => $other->{a},
453             b => $other->{b},
454             c => $other->{c},
455             d => $other->{d},
456             e => $other->{e},
457             f => 'bla bla',
458             );
459              
460             write with map
461              
462             %hash = (
463             (
464             map {
465             $_ => $other->{$_};
466             } 'a' .. 'e'
467             ),
468             f => 'bla bla',
469             );
470              
471             or more clear readable
472              
473             %hash = Hash::Map
474             ->source_ref($other)
475             ->copy_keys('a' .. 'e')
476             ->merge_hash(f => 'bla bla')
477             ->target;
478              
479             =head1 DESCRIPTION
480              
481             Often in code we find lots of copy/paste code
482             during prepare a hash or hash reference.
483             That data we got from other structures, objects or constants.
484              
485             =over
486              
487             =item *
488              
489             We map hashes that not match exactly to the expected API.
490              
491             =item *
492              
493             Or the method names, we call, matching not exactly to the hash keys.
494              
495             =item *
496              
497             Sometimes we forgot to write C<scalar>
498             if we call subroutines/methods for a hash value
499             and risk to have a value as key.
500              
501             =item *
502              
503             We use C<map>, C<for>, C<map>/C<push>
504             to build the expected hash or hash reference.
505              
506             =item *
507              
508             Accidentally we do not destroy the data we fetch.
509              
510             =item *
511              
512             We have to write C<defined>, C<? :> or C<do>.
513              
514             =back
515              
516             This Module lets you writing code without that copied noise.
517              
518             The goal of this module is to write clear code with less typing around.
519             Less typing for the user needs lots of specialized methods in this module.
520              
521             The code in the SYNOPSIS
522             is only a very simple but typical example to understand,
523             why that module was written.
524              
525             Look at your existing code for lots of similar lines of hash key/value pairs.
526             Then this module can help you.
527              
528             There is also a fuctional interface.
529             That is wrapped around the OO inferface.
530             Not all can be implemented functional.
531              
532             For more information read the L<Hash::Map::Tutorial|Hash::Map::Tutorial>.
533              
534             =head1 EXAMPLE
535              
536             Inside of this Distribution is a directory named example.
537             Run this *.pl files.
538              
539             =head1 SUBROUTINES/METHODS
540              
541             =head2 method new
542              
543             A simple constructor without any parameters.
544              
545             my $obj = Hash::Map->new;
546              
547             Typical you don't call method "new" directly.
548              
549             =head2 method source, source_ref, set_source and set_source_ref
550              
551             Set or get the source hash.
552              
553             Method "source" can not set an empty hash, but an empty hash is the default.
554             Otherwise use method "set_source".
555              
556             $obj = $obj->source(%source);
557             $obj = $obj->source_ref($source_hashref);
558             # if %source is or can be empty
559             $obj = $obj->set_source(%source);
560             # method exists for the sake of completeness
561             $obj = $obj->set_source_ref($target_ref);
562              
563             %source = $obj->source;
564             $source_hashref = $obj->source_ref;
565              
566             This methods are able to construct the object first.
567              
568             Hash::Map->source(...);
569             Hash::Map->source_ref(...);
570             Hash::Map->set_source(...);
571             Hash::Map->set_source_ref(...);
572              
573             =head2 method target, target_ref, set_target and set_target_ref
574              
575             Set or get the target hash.
576              
577             Method "target" can not set an empty hash, but an empty hash is the default.
578             Otherwise use method "set_target".
579              
580             $obj = $obj->target(%target);
581             $obj = $obj->target_ref($target_hashref);
582              
583             # if %target is or can be empty
584             $obj = $obj->set_target(%target);
585             # method exists for the sake of completeness
586             $obj = $obj->set_target_ref($target_ref);
587              
588             %target = $obj->target;
589             $target_hashref = $obj->target_ref;
590              
591             This methods are able to construct the object first.
592              
593             Hash::Map->target(...);
594             Hash::Map->target_ref(...);
595             Hash::Map->set_target(...);
596             Hash::Map->set_target_ref(...);
597              
598             Typical the source is set and not the target.
599             But it makes no sense to set the source
600             and copy then all from source.
601              
602             =head2 method source_keys, target_keys, source_keys_ref, target_keys_ref
603              
604             This methods get back all keys as array or array reference.
605              
606             @keys = $obj->source_keys;
607             @keys = $obj->target_keys;
608             $array_ref = $obj->source_keys_ref;
609             $array_ref = $obj->target_keys_ref;
610              
611             =head2 method source_values, target_values, source_values_ref, target_values_ref
612              
613             This methods get back all values as array or array reference.
614              
615             @values = $obj->source_values;
616             @values = $obj->target_values;
617             $array_ref = $obj->source_values_ref;
618             $array_ref = $obj->target_values_ref;
619              
620             =head2 method exists_source, exists_target
621              
622             This methods allows easy writing for exists.
623              
624             $boolean = $obj->exists_source($key);
625             $boolean = $obj->exists_target($key);
626              
627             =head2 method combine
628              
629             Merge targets of other Hash::Map objects into $obj target.
630              
631             $obj = $obj->combine(@hash_map_objects);
632              
633             This method is able to construct the object first.
634              
635             Hash::Map->combine(...);
636              
637             Typical used for clear code to prevent the change of the source hash/hashref.
638             It's strongly readable if source is set more than one time.
639              
640             =head2 method clone_source
641              
642             Using Module Clone to clone the source hash.
643              
644             $obj = $obj->clone_source;
645              
646             This method exists for the sake of completeness.
647              
648             =head2 method clone_target
649              
650             Using Module Clone to clone the target hash.
651              
652             $obj = $obj->clone_target;
653              
654             Only used after set of target hash reference
655             to prevent manpulations backwards.
656              
657             =head2 method delete_keys and delete_keys_ref
658              
659             Delete keys in target hash.
660              
661             $obj = $obj->delete_keys(@keys);
662             $obj = $obj->delete_keys_ref($keys_array_ref);
663              
664             =head2 method copy_keys and copy_keys_ref
665              
666             Copy data from source to target hash using keys.
667              
668             $obj = $obj->copy_keys(@keys);
669             $obj = $obj->copy_keys_ref($keys_array_ref);
670              
671             And rename all keys during copy.
672              
673             $obj = $obj->copy_keys(
674             @keys,
675             sub {
676             my $obj = shift;
677             my $key = $_;
678             return "new $key";
679             },
680             );
681             $obj = $obj->copy_keys_ref(
682             $keys_array_ref,
683             sub {
684             my $obj = shift;
685             my $key = $_;
686             return "new $key";
687             },
688             );
689              
690             The first parameter of the callback subroutine is the object itself.
691             The current key is in $_.
692             Return the new key.
693              
694             Replaces code like this:
695              
696             %target = (
697             a => $source->{a},
698             b => $source->{b},
699             ...
700             );
701             %target = (
702             p_a => $source->{a},
703             p_b => $source->{b},
704             ...
705             );
706              
707             =head2 method map_keys and map_keys_ref
708              
709             Copy data from source hash (key is key of map)
710             to target hash (key is value of map).
711              
712             $obj = $obj->map_keys(%map);
713             $obj = $obj->map_keys_ref($map_hashref);
714              
715             Replaces code like this:
716              
717             %target = (
718             a => $source->{z},
719             b => $source->{y},
720             ...
721             );
722              
723             =head2 method merge_hash and merge_hashref
724              
725             Merge the given hash into the target hash.
726              
727             $obj = $obj->merge_hash(%hash);
728             $obj = $obj->merge_hashref($hashref);
729              
730             Replaces code like this:
731              
732             %target = (
733             %hash,
734             ...
735             );
736              
737             =head2 method modify and modify_ref
738              
739             Modify the target hash inplace by given key and code for that.
740              
741             The first parameter of the callback subroutine is the object itself.
742             The old value of the target hash is in $_;
743             Return the new value.
744              
745             $obj = $obj->modify(
746             key1 => $code_ref1,
747             ...
748             );
749             $obj = $obj->modify_ref({
750             key1 => $code_ref1,
751             ...
752             });
753              
754             Typical the combinated methods are used:
755             "copy_modify",
756             "copy_modify_ref",
757             "copy_modify_identical",
758             "copy_modify_identical_ref",
759             "map_modify",
760             "map_modify_ref",
761             "map_modify_identical" and
762             "map_modify_identical_ref".
763              
764             =head2 method copy_modify and copy_modify_ref
765              
766             This is a combination of method "copy_keys" and "modify".
767              
768             The first parameter of the callback subroutine is the object itself.
769             The old value of the target hash is in $_;
770             Return the new value.
771              
772             $obj = $obj->copy_modify(
773             key1 => $code_ref1,
774             ...
775             );
776             $obj = $obj->copy_modify_ref({
777             key1 => $code_ref1,
778             ...
779             });
780              
781             It is not possible to rename all keys during copy.
782             Use method "map_modify" or "map_modify_ref" instead.
783              
784             This method exists for the sake of completeness.
785              
786             =head2 method copy_modify_identical and copy_modify_identical_ref
787              
788             This is another combination of method "copy_keys" and "modify".
789             All values are modified using a common code reference.
790              
791             The 1st parameter of the callback subroutine is the object itself.
792             The 2nd parameter is the key.
793             The old value of the target hash is in $_;
794             Return the new value.
795              
796             $obj = $obj->copy_modify_identical(
797             @keys,
798             $code_ref,
799             );
800             $obj = $obj->copy_modify_identical_ref(
801             $keys_array_ref,
802             $code_ref,
803             );
804              
805             It is not possible to rename all keys during copy.
806             Use method "map_modify_identical" or "map_modify_identical" instead.
807              
808             Replaces code like this:
809              
810             %target = (
811             a => $foo->bar('a'),
812             b => $foo->bar('b'),
813             ...
814             );
815             %target = (
816             a => $foo->a,
817             b => $foo->b,
818             ...
819             );
820              
821             =head2 method map_modify and map_modify_ref
822              
823             This is a combination of method "map_keys" and "modify".
824              
825             The first parameter of the callback subroutine is the object itself.
826             The old value of the target hash is in $_;
827             Return the new value.
828              
829             $obj = $obj->map_modify(
830             source_key1 => target_key1 => $code_ref1,
831             ...
832             );
833             $obj = $obj->map_modify_ref([
834             source_key1 => target_key1 => $code_ref1,
835             ...
836             ]);
837              
838             This method exists for the sake of completeness.
839              
840             =head2 method map_modify_identical and map_modify_identical_ref
841              
842             This is a combination of method "map_keys" and "modify".
843              
844             The 1st parameter of the callback subroutine is the object itself.
845             The 2nd parameter is the source key and the 3rd parameter is the target key.
846             The old value of the target hash is in $_;
847             Return the new value.
848              
849             $obj = $obj->map_modify_identical(
850             source_key1 => target_key1,
851             ...
852             $code_ref,
853             );
854             $obj = $obj->map_modify_identical_ref(
855             {
856             source_key1 => target_key1,
857             ...
858             },
859             $code_ref,
860             );
861              
862             Replaces code like this:
863              
864             %target = (
865             a => $foo->bar('z'),
866             b => $foo->bar('y'),
867             ...
868             );
869             %target = (
870             a => $foo->z,
871             b => $foo->y,
872             ...
873             );
874              
875             =head2 method each_source, each_target, source_iterator, target_iterator
876              
877             This methods allows to work with iterations.
878              
879             while ( my ($key, $value) = $self->each_source ) {
880             ...
881             }
882              
883             while ( my ($key, $value) = $self->each_target ) {
884             ...
885             }
886              
887             my $iterator_code = $self->source_iterator;
888             while ( my ($key, $value) = $iterator_code->() ) {
889             ...
890             }
891              
892             my $iterator_code = $self->target_iterator;
893             while ( my ($key, $value) = $iterator_code->() ) {
894             ...
895             }
896              
897             =head2 subroutine hash_map
898              
899             This subroutine is for the fuctional interface only.
900              
901             %target_hash = hash_map(
902             \%source_hash,
903             # The following references are sorted anyway.
904             # Running in order like written.
905             [ qw(key1 key2) ], # copy_keys from source to target hash
906             [ qw(key3 key4), $code_ref ], # copy_keys, code_ref to rename keys
907             {
908             source_key1 => 'target_key', # map_keys from source to target hash
909             source_key2 => $code_ref, # modify values in target hash
910             },
911             );
912              
913             =head2 subroutine hashref_map
914              
915             Similar, only the subroutine name and the return value has chenged.
916              
917             $target_hashref = hashref_map(
918             $source_hashref,
919             ...
920             );
921              
922             =head1 DIAGNOSTICS
923              
924             nothing
925              
926             =head1 CONFIGURATION AND ENVIRONMENT
927              
928             nothing
929              
930             =head1 DEPENDENCIES
931              
932             L<Carp|Carp>
933              
934             L<Clone|Clone>
935              
936             L<Scalar::Util|Scalar::Util>
937              
938             L<Try::Tiny|Try::Tiny>
939              
940             L<parent|parent>
941              
942             L<Exporter::Tiny|Exporter::Tiny>
943              
944             =head1 INCOMPATIBILITIES
945              
946             none
947              
948             =head1 BUGS AND LIMITATIONS
949              
950             none
951              
952             =head1 SEE ALSO
953              
954             L<map|http://perldoc.perl.org/functions/map.html>
955              
956             L<Data::Visitor|Data::Visitor>
957              
958             L<Hash::Map::Tutorial|Hash::Map::Tutorial>
959              
960             =head1 AUTHOR
961              
962             Steffen Winkler
963              
964             inspired by: Andreas Specht C<< <ACID at cpan.org> >>
965              
966             =head1 LICENSE AND COPYRIGHT
967              
968             Copyright (c) 2012 - 2016,
969             Steffen Winkler
970             C<< <steffenw at cpan.org> >>.
971             All rights reserved.
972              
973             This module is free software;
974             you can redistribute it and/or modify it
975             under the same terms as Perl itself.