D D Allen wrote:
I think what's going on is that for variations 1 and 3, Perl is "slurping" the input file into an array, performing the substitutions on the array elements, and then writing out the array elements.   For variation 2, there's no array involved.  It's simply "read a line, perform the substitution on that line, write a line".   And I think the explanation for the time differences between 1 and 3 is that there is a certain amount of overhead associated with the map function -- that's not present with the for loop.
Thanks for your informative test.  When we make decisions about how to code something, it is important to consider what factors are most important in our situation.  Sometimes, speed will be critical.  At other times, conceptual clarity of the code, for ease of maintenance, will be of highest concern.  Most of the time we choose a balance.  Personally, I find that if speed is not critical (and if it is, you should be using something faster than current Perl implementations), I want to emphasize conceptual clarity.

I feel that in the long run, it is best to write clearer code, unless the performance penalty is overwhelming.  Understand that future versions of Perl may be optimized to handle some things more efficiently, e.g. map.  If more people used it, there would be more incentive for Wall et al to optimize for it.

One issue that arises in designing for clarity in the code is that different developers are used to different idioms.  So, what is clear and simple to me may seem obtuse to a future maintainer, and vice-versa.  Many of the practices in the Best Practices book seem strange to many Perl developers, but Conway suggests that if we would all get used to them, we'd be happier in the long run.  It is in that spirit that I prefer the three-line map solution to the while loop:

my @lines = <$infile>;
map { s/$oldval/$newval/g; $_ } @lines;
print {$outfile} @lines;

It conceptually separates I/O from computations.  It is also more declarative - saying what you want rather than how to do it.  Some programmers may find it less familiar than while loops, but I think that is only because they have been taught to use while loops.  If you start a new programmer from scratch, my bet is they'll find the map solution conceptually simpler.  Granted, I have a functional programming background, so I'm apt to say such things.

Anyway, despite the fact that the map solution is simpler than the while loop, there is yet a simpler solution to this problem, which I mentioned earlier.  It involves sucking in the entire file and doing substitutions on it.  There is no need to impose the conceptual framework of line-based processing.  It might even be faster.  I'm eager to find out.

Here is the variant I suggest you test:

use File::Slurp;
...
my $text = read_file($input_file, binmode => ':raw');
$text =~ s/$oldval/$newval/g;
print {$outfile} $text;

(I know Conway suggests using Perl6::Slurp, but I couldn't find a PPM for it, so I used File::Slurp.  Admittedly, the binmode => ':raw' is a bit obtuse, and could be left out.  I do think it will boost performance slightly, which I am curious about in the context of this discussion.)
-- 
Lyle Kopnicky
Software Project Engineer
Veicon Technology, Inc.


_______________________________________________
Perl-Win32-Users mailing list
[email protected]
To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs

Reply via email to