Seems like you are doing it the hard way, but my way might be harder
in a different way.
I'd first write something to enumerate the different possibilities.
(method varies, but like a "pick (3,5)" -- a random example I wrote in
my perlish shell style):
#!/bin/bash -u
include stdalias
sub errmsg () {
my code=1
if (($#>1)) ; then
code=$2
fi
echo "Error: $1"
exit $code
}
# call with "parmnum <wanted>" - checks wanted against actual
alias parmnum='_parmnum $# '
sub _parmnum () {
int expected=${1:-0-1} actual=$2
if ((expected!=actual)) ; then
echo "Incorrect param count($actual). Expected $expected."
exit 1
fi
return 0
}
sub permute () { # ( inArName outArName) #: randomly permute in->out
+)
parmnum 2
my snam="$1" dnam="$2"
readarray -t "$dnam"< <(printf "%s\n" $(
eval "echo \${$snam[@]}") | sort --random-sort
+)
}
sub pick () { #(parms: #params inArray_name outArray_name)
parmnum 3
int savecnt=$1 cnt=$1
my snam="$2" dnam="$3"
set "" $(eval echo '${'$snam'[@]}' )
shift
if (($#<cnt)); then
printf "Cannot pick %s from list of len %s\n" "$cnt" "$#"
exit 1
fi
eval "$dnam=()"
while ((0 < cnt--));do
eval "$dnam+=( \"$1\" )"
shift || return 1
done
eval "$snam=( $(echo \"$@\") )"
if (($(eval "echo \${#$dnam[@]}")<$savecnt)); then
return 1
fi
return 0
}
sub dropcaches () {
echo -n "3"|sudo dd of=/proc/sys/vm/drop_caches
}
# runall |& tee -a /tmp/ndd.log
if [[ $# -ge 2 ]]; then
array in=( $(echo "$@") )
array out
array mypick
permute in out
else
array in=( $(echo {1..8} ) )
array out
array mypick
permute in out
fi
readarray -t ops< <(printf "%s\n" ''{,--nmmap} )
int dflt=8
int apt=2 #args/test
int args=$#
int nargs=$[args?args:dflt]
int nops=${#ops[@]}
if ((nops*apt>nargs)) ; then
{
printf "%s: Too few args for %s tests @ %s/test\n" \
"$nargs" "$nops" "$apt"
exit 1
} >&2
fi
if [[ ! $0 =~ bash ]]; then
echo Drop Caches...
dropcaches
echo Start tests
for op in "${ops[@]}"; do
pick 2 out mypick
cmd=$(echo "ndedup $op ${mypick[@]}" )
echo "$cmd"
time $cmd || exit $?
done
fi
I didn't want the caches used in the same order
each time to prevent disk locality from coming into
play.... So basically permute & pick # vals from list.
then for each test (this one tried 2 "ops" with and without "--nmmap")
For more perlish work, I'd rewrite those in perl -- should be trivial.
Then for execution, I would use either a hash or look through an array of cases, depending on howmuch control I needed over ordering. The thing is, the hash or array can be created on the fly, so you don't need to do the coding of the if/else cases... They can be run automatically after you put in the
cases to test.
Example of the ARRAY case to choose a format, with tests in order:
my $fmt; # prototypes are documentary (rt#89053)
my $given = [ sub ($$) { $_[0] =~ /^[-+]?[0-9]+\.?\z/ && q{%
+s} },
sub ($$) { $_[1] && qq{
+%s}},
sub ($$) { 1 == length($_[0]) && q{'
+%s'}},
sub ($$) { $_[0] =~ m{^(?:[+-]?(?:\.[0-9]+)
| (?:[0-9]+\.[0-9]+))\z}x && q{
+%.2f}},
sub ($$) { substr($_[0],0,5) eq 'HASH(' &&
'{'.sw(ellipsis).'}'
+},
sub ($$) { substr($_[0],0,6) eq 'ARRAY(' &&
'['.sw(ellipsis).']'
+},
# sub ($$) { $mxstr && length ($_[0])>$mxstr
# && qq("%.${mxstr}s")},
sub ($$) { 1 && q{"
+%s"}} ];
do { $fmt = $_->($v, $ro) and last } for @$given;
return sprintf $fmt, $v;
And a hash case, (this time creating a format for refs):
no strict 'refs';
my %actions = (
GLOB => ($p->{implicit_io}? *IO_glob: *NIO_glob),
IO => ($p->{implicit_io}? *IO_io : *NIO_io),
REF => sub(){ "\\" . $p->Px($$_, $lvl-1) . ' '},
SCALAR=> sub(){ $pkg.'\\' . $p->Px($$_, $lvl).' ' },
ARRAY => sub(){ $pkg."[".
(join ', ', map{ $p->Px($_, $lvl) } @$v ) ."]"
+ },
HASH => sub(){ $pkg.'{' . ( join ', ', @{[
map {$p->Px($_, $lvl, 1) . '=>'. $p->Px($v->{$_},
+$lvl,0)}
sort nonrefs_b4_refs keys %$v]} ) . '}' },);
if (my $act=$actions{$ref}) { &$act }
else { return "$v" }
You start using tables for decision trees, and it can simplify things.
A third case... is using a sub or RE to match on, and calling the action
based on that. With results from the first sub or RE being used
as params in the action...
I've been trying to eliminate all the features that are experimental from all my code since 5.18 . What a pointless exercise to have used them in the first
place -- but I thought that they were only experimental for the 1st main
release they were in, not "forever"...geez.
|