# Note: Don't prototype () since that won't let you pass args sub builder { my $data = shift; # $i in your code I'm keeping in @_ my %hash = (); my $ptr = \%hash; # Set up a pointer to %hash for (my $cur = 0; $cur < $#_; $cur++) { $ptr->{$_[$cur]} = {}; # Manipulate using our pointer $ptr = $ptr->{$_[$cur]}; # and advance it as we go } $ptr->{$_[$#_]} = $data; # Do our last hash return %hash; # and do what you want with %hash } my %hash = builder('abcde', 'a', 'b', 3); print $hash{'a'}{'b'}{3}; # 'abcde'