Beefy Boxes and Bandwidth Generously Provided by pair Networks
Problems? Is your data what you think it is?

Anti-snippet (or, "local" considered dangerous to fools")

by Mur (Pilgrim)
on Aug 05, 2003 at 20:00 UTC ( #281143=snippet: print w/replies, xml ) Need Help??
Description: Don't do this. It makes for long, painful debugging sessions.
Instead of:
local($object1->{field}) = $val;
local($object2->{field}) = $val;
local($object3->{field}) = $val;
That's too much typing! Instead,
for ($object1,$object2,$object3) {
  local($_->{field}) = $val;
So much nicer to look at, but completely, utterly wrong.
Replies are listed 'Best First'.
Re: Anti-snippet (or, "local" considered dangerous to fools")
by jeffa (Bishop) on Aug 06, 2003 at 17:23 UTC
    Indeed. Reserve the use of local for Perl built-in vars, for example:
    my $file_contents_as_scalar = do{local $/;<FILEHANDLE>};
    This "temporarily" undefines $/ so that the entire file handle is read into a scalar without resorting to appending inside a while loop.

    Using local on lexical or package variables can be dangerous. For your example, surely the better way to assign that variable to multiple classes is:

    $_->{field} = $var for @object;
    You did store your objects in a container didn't you? ;)


    (the triplet paradiddle with high-hat)

      Using local on lexical or package variables can be dangerous.

      You can reduce that to:
      "Using local can be dangerous."

      See also Coping with Scoping. In short: don't use local on variables not mentioned in perlvar. Do use local on variables mentioned in perlvar.

      Juerd # { site => '', plp_site => '', do_not_use => 'spamtrap' }

      Well, I would agree that local is to be avoided where possible, but it's rather hard in this case:
      sub main_loop { local($dbh->{AutoCommit}) = 0; ... lots of code here, with multiple returns }
      To avoid a problem with DBD::Pg, I have all my database connection handles set to "AutoCommit" (otherwise, they start a new transaction after every COMMIT; daemons thus hold open transactions for hours at a time, waiting for the next request). I turn the AutoCommit setting off just before starting to process something. I could turn it back on, but I'd have to put that before each and every return statement. Making a lexical copy of the object doesn't help:
      my $tmp_dbh = $dbh; $tmp_dbh->{AutoCommit} = 0; #BZZT!
      because they're handles, what you do to one affects all the copies. What I really need is a continue block for subroutines ...
      # Wishful thinking sub main_loop { ... stuff happens ... } continue { ... oops! I must have returned! }
      Perhaps I could do this with a naked block?
      sub main_loop { { ... stuff happens ... ... use 'last' instead of 'return'? } ... restore settings here }
      but local for all its shortcomings, is much easier to understand by the next guy (or is it?). As to the idea of a container: no, but not applicable in this case. One object is the return value of a subroutine (and is a package variable from elsewhere), the other is a package variable in the current package.
      Jeff Boes
      Database Engineer
      Nexcerpt, Inc.
      vox 269.226.9550 ext 24
      fax 269.349.9076
      ...Nexcerpt...Connecting People With Expertise
Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: snippet [id://281143]
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others musing on the Monastery: (5)
As of 2017-05-27 16:04 GMT
Find Nodes?
    Voting Booth?