patternMinor
Perl module to deal with numbered nested objects
Viewed 0 times
objectsperlwithmodulenestednumbereddeal
Problem
I wrote a small perl module that dealing with PHP-ish array structures, and I'm going to release it to CPAN.
I want it to be reviewed before the release about the module naming and the code itself.
Could you please give me improvements? Any suggestions are appreciated.
https://github.com/ernix/p5-Object-Squash
```
use strict;
use warnings;
package Object::Squash;
# ABSTRACT: Remove numbered keys from a nested object
use parent 'Exporter';
use List::Util qw/max/;
use version; our $VERSION = version->declare("v0.0.1");
our @EXPORT_OK = qw(squash);
sub squash {
my $obj = shift;
return $obj unless ref $obj;
$obj = _squash_hash($obj);
$obj = _squash_array($obj);
return $obj;
}
sub _squash_hash {
my $obj = shift;
return $obj unless ref $obj eq 'HASH';
my @keys = keys %{$obj};
if (grep {/\D/} @keys) {
return +{
map { $_ => squash($obj->{$_}) } @keys,
};
}
my $max = max(@keys) || 0;
my @ar;
for my $i (0 .. $max) {
push @ar, sub {
return (undef) unless exists $obj->{$i};
return squash($obj->{$i});
}->();
}
return \@ar;
}
sub _squash_array {
my $obj = shift;
return $obj unless ref $obj eq 'ARRAY';
return (undef) if @{$obj} == 0;
$obj = squash($obj->[0]) if @{$obj} == 1;
return $obj;
}
1;
__END__
=head1 NAME
Object::Squash - Remove numbered keys from a nested object
=head1 DESCRIPTION
This package provides B subroutine to simplify hash/array structures.
I sometimes want to walk through a data structure that consists only of a bunch
of nested hashes, even if some of them should be treated as arrays or single
values. This module removes numbered keys from a hash.
=head1 SYNOPSIS
=head2 C
use Object::Squash qw(squash);
my $hash = squash(+{
foo => +{
'0' => 'nested',
'1' => 'numbered',
'2' => 'hash',
'3' => 'structures',
},
bar
I want it to be reviewed before the release about the module naming and the code itself.
Could you please give me improvements? Any suggestions are appreciated.
https://github.com/ernix/p5-Object-Squash
```
use strict;
use warnings;
package Object::Squash;
# ABSTRACT: Remove numbered keys from a nested object
use parent 'Exporter';
use List::Util qw/max/;
use version; our $VERSION = version->declare("v0.0.1");
our @EXPORT_OK = qw(squash);
sub squash {
my $obj = shift;
return $obj unless ref $obj;
$obj = _squash_hash($obj);
$obj = _squash_array($obj);
return $obj;
}
sub _squash_hash {
my $obj = shift;
return $obj unless ref $obj eq 'HASH';
my @keys = keys %{$obj};
if (grep {/\D/} @keys) {
return +{
map { $_ => squash($obj->{$_}) } @keys,
};
}
my $max = max(@keys) || 0;
my @ar;
for my $i (0 .. $max) {
push @ar, sub {
return (undef) unless exists $obj->{$i};
return squash($obj->{$i});
}->();
}
return \@ar;
}
sub _squash_array {
my $obj = shift;
return $obj unless ref $obj eq 'ARRAY';
return (undef) if @{$obj} == 0;
$obj = squash($obj->[0]) if @{$obj} == 1;
return $obj;
}
1;
__END__
=head1 NAME
Object::Squash - Remove numbered keys from a nested object
=head1 DESCRIPTION
This package provides B subroutine to simplify hash/array structures.
I sometimes want to walk through a data structure that consists only of a bunch
of nested hashes, even if some of them should be treated as arrays or single
values. This module removes numbered keys from a hash.
=head1 SYNOPSIS
=head2 C
use Object::Squash qw(squash);
my $hash = squash(+{
foo => +{
'0' => 'nested',
'1' => 'numbered',
'2' => 'hash',
'3' => 'structures',
},
bar
Solution
Just a few remarks about parts which poke the eye,
introduces unnecessary subroutine call/overhead which can be replaced with
This one is only matter of taste, so
could also be written as
Usually you don't have to explicitly return
could be better as
or perhaps,
push @ar, sub {
return (undef) unless exists $obj->{$i};
return squash($obj->{$i});
}->();introduces unnecessary subroutine call/overhead which can be replaced with
do {} block, or even simpler,push @ar, exists $obj->{$i} ? squash($obj->{$i}) : undef;This one is only matter of taste, so
return $obj unless ref $obj eq 'HASH';could also be written as
return $obj if ref $obj ne 'HASH';Usually you don't have to explicitly return
undef, as in list context you may end up with list one element long, and that might not be what is intended. Instead just return; or return (); will produce empty list, or undef in scalar context. Soreturn (undef) if @{$obj} == 0;could be better as
return () if @{$obj} == 0;or perhaps,
@$obj or return;Code Snippets
push @ar, sub {
return (undef) unless exists $obj->{$i};
return squash($obj->{$i});
}->();push @ar, exists $obj->{$i} ? squash($obj->{$i}) : undef;return $obj unless ref $obj eq 'HASH';return $obj if ref $obj ne 'HASH';return (undef) if @{$obj} == 0;Context
StackExchange Code Review Q#60917, answer score: 2
Revisions (0)
No revisions yet.