sub traverse(&$) { my( $code, $ref ) = @_; my $d; $d = { SCALAR => sub{ my $code = shift; my $ref = shift; return $code->( @_, $$ref ); }, ARRAY => sub { my $code = shift; my $ref = shift; map $d->{ ref $ref->[ $_ ] }->( $code, $ref->[ $_ ], @_, $_ ), 0 .. $#$ref; }, HASH => sub { my $code = shift; my $ref = shift; map $d->{ ref $ref->{ $_ } }->( $code, $ref->{ $_ }, @_, $_ ), keys %$ref; }, REF => sub{ my $code = shift; my $ref = shift; return $d->{ ref $$ref }->( $code, $$ref, @_ ); }, CODE => sub{ my $code = shift; my $ref = shift; return $d->{ '' }->( $code, "$ref", @_ ); }, '' => sub{ my $code = shift; my $ref = shift; return $code->( @_, $ref ); }, }; return $d->{ ref $ref }->( $code, $ref ); } traverse { print join ',', @_ } \%hash;