use Carp; use vars qw(%data); my %comparison; sub init_comparison_for { local $_ = shift; my $op = /^string/ ? 'cmp' : /^num/ ? '<=> : croak "unknown comparison type $_"; @comparison{@_} = map { eval "sub { \$data{\$a}{$_} $op \$data{\$b}{$_} }" } @_; @comparison{map "r-$_", @_} = map { eval "sub { \$data{\$b}{$_} $op \$data{\$a}{$_} }" } @_; } sub sortedkeys (\%@) { my $hash; unless( ($hash = shift) and ('HASH' eq ref $hash) ) { croak "not a hashref: $hash"; } local *data = shift; my @funcs = @comparison{@_}; if(my @unknown = grep !defined $func[$_], 0 .. $#_) { croak "unknown field name(s): @unknown"; } sort { my $r = 0; ($r ||= &$_) && last for @funcs; $r } keys %data; }