use strict; use warnings; use Data::Dump qw/pp dd/; use Scalar::Util qw/reftype/; use autovivification; use Test::More; use constant DBG => 0; my @rules; sub parse_arr (\@$) { my ( $arr, $path ) = @_; for ( my $i=0; $i <= @$arr; $i++ ) { my $item = $arr->[$i]; parse( $item, "${path}[$i]"); } } sub parse_hsh (\%$) { my ( $hsh, $path ) = @_; while ( my ($key,$val) = each %$hsh ) { parse( $val, "${path}{$key}"); } } sub parse { my ( $item, $path ) = @_; $path //= ''; my $type = ref $item; return unless $type; if ( $type eq "GRAB") { push @rules, [ $item->{ref} , $path ]; } elsif ( $type eq "ARRAY" ) { parse_arr( @$item, $path ) } elsif ( $type eq "HASH" ) { parse_hsh( %$item, $path ) } else { warn "Unknown $type"; } } sub assign (++){ my ($pattern,$in) =@_; @rules = (); parse($pattern); warn pp @rules if DBG; no autovivification; for my $rule (@rules) { my ($ref,$path) = @$rule; my $code = "\$in->$path"; $$ref = eval($code); } } sub set (\[@$%]) { bless {ref => $_[0]}, "GRAB"; } my @pattern = ( 1,2,3, set my $y , [ 5,6, set my $z ] ); my $src = [ 1,2,3, 42 , [5,6, 666] ]; assign @pattern => $src; is_deeply ( [$z,$y], [666, 42], "AoA grabbing different levels" ); assign { u => [undef, set( my $u )], v => set my $v } => { u => [1,123] , v => "VVV"} ; is_deeply ( [$u,$v], [123,"VVV"], "HoA grabbing different levels" ); done_testing;