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?

print substr("Just another Perl hacker", 0, -2);
- apotheon
CopyWrite Chad Perrin


In reply to local() for scalar file slurping by apotheon

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.