Somehow, I just never ended up investigating use of local() with Perl. I've been using lexical scope ever since I learned it existed, and before that I (very briefly) didn't use strict, so no explicit declarations were needed. Good ol' local() just never figured into it.
I've been investigating the differences between local() and my() recently, because a friend asked me some questions about lexical scope and how exactly my() differs from local(). Somewhere along the way in the last few years, I'd picked up the textbook definition of local(), but that didn't tell me much about it — though I did get enough from my hazy memory and a quick refresher on how dynamic and lexical scoping each affect language implementation to be able to offer somewhat useful answers to my friend. The clearest usage advice I've seen about local(), in several venues, is "Don't."
I was reading a quick Perl I/O howto someone I know wrote about slurping file contents into a scalar variable, newlines and all, today. It suggested a methodology something like the following:
my $foo = $/; undef $/; my $bar = <>; $/ = $foo;
This is probably the knee-jerk, simple method of accomplishing that feat that comes immediately to mind for most when not really thinking about the fact that TIMTOWTDI. I thought there should be a better way, though, and the second option that came to mind was something like this:
my $foo; $foo .= $_ while <>;
Another that came to mind immediately looks something like this (though I don't like it much):
my $foo; my @bar = <>; $foo .= $_ foreach @bar;
What wouldn't have occurred to me at all if I hadn't been thinking about local() a lot recently is this one:
my $foo; { local $/; $foo = <>; }
. . . which strikes me as a surprisingly elegant rewrite of the file-slurping methodology in the howto.
I decided to kick around in PerlMonks and see what I could find that might address using local() for scalar context file content assignment to a variable, and came across Slurp a file, wherein Merlyn whipped out this gem (slightly modified to fit my foregoing example style):
my $foo = do { local $/; <> };
Edit: It has been pointed out in the ensuing discussion that this code essentially loads two copies of the contents of <> into memory for a brief moment, and preceding example where $foo is declared on its own line, then assigned explicitly in the unnamed block without the use of do, uses less system resources.
There was discussion of using join(), with or without local $/, for various levels of safety and performance (complete with benchmarks), and of using sysread(), which is of course problematic on some OSes but blazing fast (as system calls often are, all else being equal).
. . . but I really rather like Merlyn's version of what I came up with while contemplating the problem on my own. Here's the question that comes to mind:
How did I never read anything about the usefulness of local() for such purposes before this? Am I living under a rock?
|
- apotheon
CopyWrite Chad Perrin |
|
---|
Replies are listed 'Best First'. | |
---|---|
Re: local() for scalar file slurping
by ikegami (Patriarch) on Jul 28, 2006 at 21:19 UTC | |
by apotheon (Deacon) on Jul 28, 2006 at 22:57 UTC | |
by ikegami (Patriarch) on Jul 28, 2006 at 23:30 UTC | |
by apotheon (Deacon) on Jul 29, 2006 at 00:09 UTC | |
by rodion (Chaplain) on Jul 29, 2006 at 17:35 UTC | |
| |
Re: local() for scalar file slurping
by holli (Abbot) on Jul 28, 2006 at 20:35 UTC | |
by apotheon (Deacon) on Jul 28, 2006 at 22:54 UTC | |
Re: local() for scalar file slurping
by bobf (Monsignor) on Jul 30, 2006 at 05:23 UTC | |
by apotheon (Deacon) on Jul 30, 2006 at 05:48 UTC | |
by planetscape (Chancellor) on Jul 31, 2006 at 15:46 UTC | |
Re: local() for scalar file slurping
by revdiablo (Prior) on Jul 29, 2006 at 15:44 UTC | |
Re: local() for scalar file slurping
by sh1tn (Priest) on Aug 09, 2006 at 10:10 UTC |