in reply to Pass By Reference Inner Workings - Magic scalar operator
This entire thread never even mentioned @_ once! It mentioned $_[0] exactly once but never used it in code.
So I'll be the first to mention:
my %h= %{ shift @_ };
Leaving the target of operations implied is fine for quick hacks, one-liners, and golf. But I usually stress writing code that is easy to maintain so I usually avoid such implied targets. And this means I don't get bit by shift or pop being treated as a string.
It also means that you can easily find where I deal with function arguments. As opposed to this code from a core module. Quick, what arguments does it take?
sub ... { my ($pkg,$file,$line) = caller($TestLevel); my $repetition = ++$history{"$file:$line"}; my $context = ("$file at line $line". ($repetition > 1 ? " fail \#$repetition" : '')); my $ok=0; my $result = to_value(shift); my ($expected,$diag); if (@_ == 0) { $ok = $result; } else { $expected = to_value(shift); my ($regex,$ignore); if (!defined $expected) { $ok = !defined $result; } elsif (!defined $result) { $ok = 0; } elsif ((ref($expected)||'') eq 'Regexp') { $ok = $result =~ /$expected/; } elsif (($regex) = ($expected =~ m,^ / (.+) / $,sx) or ($ignore, $regex) = ($expected =~ m,^ m([^\w\s]) (.+) \1 $ +,sx)) { $ok = $result =~ /$regex/; } else { $ok = $result eq $expected; } } my $todo = $todo{$ntest}; if ($todo and $ok) { $context .= ' TODO?!' if $todo; print $TESTOUT "ok $ntest # ($context)\n"; } else { print $TESTOUT "not " if !$ok; print $TESTOUT "ok $ntest\n"; if (!$ok) { my $detail = { 'repetition' => $repetition, 'package' => $ +pkg, 'result' => $result, 'todo' => $todo }; $$detail{expected} = $expected if defined $expected; $diag = $$detail{diagnostic} = to_value(shift) if @_; $context .= ' *TODO*' if $todo; if (!defined $expected) { if (!$diag) { print $TESTOUT "# Failed test $ntest in $context\n +"; } else { print $TESTOUT "# Failed test $ntest in $context: +$diag\n"; } } else { my $prefix = "Test $ntest"; print $TESTOUT "# $prefix got: ". (defined $result? "'$result'":'')." ($context)\n"; $prefix = ' ' x (length($prefix) - 5); if ((ref($expected)||'') eq 'Regexp') { $expected = 'qr/'.$expected.'/' } else { $expected = "'$expected'"; } if (!$diag) { print $TESTOUT "# $prefix Expected: $expected\n"; } else { print $TESTOUT "# $prefix Expected: $expected ($di +ag)\n"; } } push @FAILDETAIL, $detail; } } ++ $ntest; $ok; }
At least the suggested %{shift()} makes the code somewhat clearer. But both %{+shift} and %{(shift)} are, if anything, somewhat obfuscatory, which isn't an awful thing, but since there are such clearer alternatives I don't consider them good options.
- tye
|
|---|