Abigail said:
Brian McCauley (
[email protected]) wrote on MMMDCLXI September MCMXCIII in
<URL:&&
&& > my $elem = do {local $" = "]["; eval "\$AoA [@ind]"};
&&
&& [...] looks amazingly elegant at one level
&& but is actually aborrently ugly to an experienced programmer.
I guess I'm not an experienced programmer then.
"When I was a child I spoke as a child I understood as a child I
thought as a child; but when I became a man I put away childish
things." I Cor. xiii. 11.
20 years ago I was a child and I was an inexperienced programmer (~5y)
and my language of choice was "Beeb BASIC"[1].
It happens that Beeb BASIC has an EVAL() function very similar to
Perl's eval().
It was also worth noting that the Beeb had only 7K of user RAM in it's
highest resolution/depth graphics modes so anything that saved a byte
was good.
I used to delight in things like this.
Now I program for a living.
Now I maintain code written by others.
Now I code libraries that are reused.
Now I code that others maintain.
Now I don't do things like that execpt under very special
circumstances (like scripts that I know are to be used once and thown
away).
&& I trust you _were_ joking.
I wasn't.
Oh dear.
Being able to do stuff like this is what makes Perl Perl.
Agreed.
I really hate dogma's like "you can't use string eval".
Me too.
Restricting
yourself to part of the language is something for the FWP mailinglist,
but a serious programmer should use the full power of the language.
Using the full power of the language does not mean that when there is
a choice of tools you use a technique just because you haven't used it
for while.
And the whining "but if @ind comes from the outside, it's dangerous"
gets old fast.
Using eval here is not ugly because it is insecure. It's very hard to
explain the real reason. Which is why people usually end up saying
"it's dangerous". But that's not the real reason.
It's not really a security problem since if you've got tainting on
@ind can't come from an external source unless it's been laundered, in
which case it's probably been laundered with /^(\d+)$/ so that's OK.
It is ugly because it blurs the code/data divide for no beniefit.
The eval approach is not really any shorter (if you reduce the refs
approach to it's minimum inlined form too), and the eval approach is
certainly slower.
timethese 100000 => {
eval => sub {
my $elem = do {
local $" = "][";
eval "\$AoA [@ind]";
};
},
refs => sub {
my $elem = \@AoA;
$elem = $elem->[$_] for @ind;
},
}
Benchmark: timing 100000 iterations of eval, refs...
eval: 6 wallclock secs ( 5.84 usr + 0.06 sys = 5.90 CPU)
@ 16949.15/s (n=100000)
refs: 1 wallclock secs ( 0.59 usr + 0.00 sys = 0.59 CPU)
@ 169491.53/s (n=100000)
Blurring the code/data line is a very powerfull tool and I think many
people are undely scared of using it when it is sensible to do so.
Indeed that is to be topic of my talk in Belfast.
But I don't think this is a case when it is sensible. One of my major
tasks over the next few months is to pin down exactly why I think
that.
'unlink $file' is dangerous if $foo comes from the outside
as well, but that's no reason to not use unlink. I'm fully aware that if
you run on behalve of some other user (suid, CGI, etc) there are issues -
issues that go much further than string eval. But the vast majority of
the programs I write runs under the same UID as the user invoking it. If
the user wants to screw himself, he doesn't need my programs to do so.
If you take a look at Message-ID: <
[email protected]>
http://groups.google.com/[email protected]
and the thread containing it you will see that I'm usually on your
side of this argument.
[1]
http://www.bbcbasic.com/