7

I have read many posts in Stackoverflow and in Google which tell that local does not create a variable, instead it works on the existing ones.

I have a small piece of code below and I wonder how local is working when there is no such variable already created.

#use strict;
#use warnings;

&func;

sub func{
    local $temp = 20;
    print $temp;        
}

This I wrote just to understand the concept and I am relatively new to Perl.

Sinan Ünür
  • 116,958
  • 15
  • 196
  • 339
suhel
  • 321
  • 3
  • 12
  • 1
    Unless you have a good reason (and as newbie you seldom do), you should be using `my()` for local variables instead of `local()`. – Dov Grobgeld Jul 05 '15 at 07:54
  • 1
    @DovGrobgeld, Thanks for comment. I know i should use my. In this case, i only want to know where is the variable $temp created. Because when i run this code, i see no issues. And local cannot create a variable. – suhel Jul 05 '15 at 08:01
  • 5
    You forgot to use `use strict`. If you do not `use strict` the global package variable `$temp` will be used.. See http://perlmaven.com/global-symbol-requires-explicit-package-name – Håkon Hægland Jul 05 '15 at 08:36
  • @HåkonHægland, Thanks for the comment. This is the answer i was looking for. – suhel Jul 05 '15 at 08:40
  • 5
    ***Never*** use an ampersand `&` when calling a Perl subroutine. It does something very specific that you don't want. Just `func()` is correct and has been so since Perl version 5.8 twenty years ago. And ***Never*** comment out `use strict` and `use warnings` -- they are life savers – Borodin Jul 05 '15 at 13:33
  • 5
    An ampersand on a subroutine can do a couple of things, some of which you probably aren't thinking about. "Never" is too strong here, even for your other statements. – brian d foy Jul 06 '15 at 00:15

5 Answers5

8

Unless you declare a variable with my, variables without a full package specification go into the current package. Here's how you might see variables used for the first time and what they would be:

my $temp;       # a scoped, lexical variable that does not live in any package
state $temp;    # a persistent lexical variable
our $temp;      # a package variable in the current package, declared
$temp;          # a package variable in the current package
$main::temp     # a package variable in main
$Foo::Bar::temp # a package variable in Foo::Bar
local $temp     # a package variable in the current package, with a dynamically-scoped (temporary) value

The local sets the scope of a package variable. When you declare this "dynamic" scope, Perl uses the temporary value you set until the end of the scope. As with other package variables, Perl creates them when you first use them. That you might use it first with local in front doesn't affect that.

Many people who tried to answer your question immediately nagged you about strict. This is a programming aid that helps you not mistype a variable name by forcing you to declare all variables you intend to use. When you use a variable name you haven't declared, it stops the compilation of your program. You can do that with the vars pragma, my, state, or our:

use vars qw($temp);
our $temp;
my $temp;
state $temp;

local isn't part of that, as you've seen. Why? Because that's just how it is. I'd like it more if it were different.

strict won't complain if you use the full package specification, such as $Foo::Bar::temp. You can mistype all of those without ever noticing.

I mostly reserve my use of local for Perl's special variables, which you don't have to declare. If I want to use $_ in a subroutine, perhaps to use the operators that use $_ by default, I'll probably start that with local $_:

 sub something {
     local $_ = shift @_;
     s/.../.../;
     tr/.../.../;
     ...;
     }

I probably use local more often with the input record separator so I can use different line endings without affecting might have come before:

 my $data = do { local $/; <FILE> };

Those work because there's an implicit first use of those variables that you haven't seen.

Otherwise, I probably want to make variables private to its subroutine so nothing outside the subroutine can see it. In that case, I don't want a package variable that the rest of the program can read or write. That's the job for my variables:

sub something {
    my $temp = ...;

    }

The trick of programming is to limit what can happen to exactly what you want. If the rest of your program shouldn't be able to see or change the variable, my is the way to go.

I explain this is Learning Perl and write about the details of the package variables in Mastering Perl.

brian d foy
  • 129,424
  • 31
  • 207
  • 592
5

local does not create a variable instead works on the existing ones. but i have a small piece of code below and i wonder how local is working when there is no such variable already created.

Lets make a few steps, and let the perl do some diagnostics,

perl -wE 'local $temp =3'
Name "main::temp" used only once: possible typo at -e line 1.

So local $temp alters $main::temp which is package variable and

perl -wE 'local $main::temp =3'
Name "main::temp" used only once: possible typo at -e line 1.

gives the same warning. So we created a new package variable which is localized.

What does this mean? It means that unlike our $temp it keeps the value of package ('global') variable $temp until it exits enclosing block at which point it restores value to previous value.

A few more tests,

perl -MData::Dumper -E 'say Dumper [exists $main::{t}, ${$main::{t}}]'
$VAR1 = [
      '',     # `$main::t` is NOT created in main package
      undef   # retrieving value of `$main::t` thus returns undef
    ];

perl -MData::Dumper -E '{our $t=7} say Dumper [exists $main::{t}, ${$main::{t}}]'
$VAR1 = [
      1,      # `$main::t` is created in main package
      7       # value of `$main::t`
    ];

and finally,

perl -MData::Dumper -E '{local $t=7} say Dumper [exists $main::{t}, ${$main::{t}}]'
$VAR1 = [
      1,      # `$main::t` is *CREATED* in main package
      undef   # value of `$main::t` reverts to undef at exit of enclosing block
    ];
mpapec
  • 50,217
  • 8
  • 67
  • 127
3

local does not create a variable. Simply mentioning $temp is creating the variable. It is created when as soon as it is first encountered, whether at compile-time or at run-time.

$ perl -E'
   $foo;
   ${"bar"};
   BEGIN { say $::{foo} && *{ $::{foo} }{SCALAR} ? "exists" : "doesn'\''t exist"; }
   BEGIN { say $::{bar} && *{ $::{bar} }{SCALAR} ? "exists" : "doesn'\''t exist"; }
   BEGIN { say $::{baz} && *{ $::{baz} }{SCALAR} ? "exists" : "doesn'\''t exist"; }
   say $::{foo} && *{ $::{foo} }{SCALAR} ? "exists" : "doesn'\''t exist";
   say $::{bar} && *{ $::{bar} }{SCALAR} ? "exists" : "doesn'\''t exist";
   say $::{baz} && *{ $::{baz} }{SCALAR} ? "exists" : "doesn'\''t exist";
'
exists               # $foo exists at compile-time
doesn't exist        # $bar doesn't exist at compile-time
doesn't exist        # $baz doesn't exist at compile-time
exists               # $foo exists at run-time
exists               # $bar exists at run-time
doesn't exist        # $baz doesn't exist at run-time

Having variables created simply by naming them makes it hard to spot typos. We use use strict; because it prevents that.

local only has a run-time effect. local temporarily backs up the value of $temp in a way that causes Perl to restore it when the lexical scope is exited.

$ perl -E'
   sub f { say $temp; }

   $temp = 123;
   f();

   {
      local $temp = 456;
      f();
   }

   f();
'
123
456
123
Community
  • 1
  • 1
ikegami
  • 367,544
  • 15
  • 269
  • 518
  • What is the difference between `$foo`, `${foo}` and `${"foo"}`? – Håkon Hægland Jul 06 '15 at 09:43
  • @Håkon Hægland, `${foo}` is identical to `$foo`. Useful in string literal `"${foo}bar"` – ikegami Jul 06 '15 at 14:22
  • 1
    @Håkon Hægland, The only difference I can think of between `${"foo"}` and `$foo` is the one I already mentioned. In the former ("symbolic reference"), the name is generated a run-time, while the name is known at compile-time. – ikegami Jul 06 '15 at 14:23
  • Ok, so `${"foo"}` is not known at compile time, while `$foo` is known at compile time.. That is weired. It would be interesting to know the logic behind this.. – Håkon Hægland Jul 06 '15 at 14:34
  • 1
    @Håkon Hægland, There are uses to generating variable names. You do it every time you import a symbol. But it's generally not something you want to do, which is why you use `use strict 'refs';` to forbid it. – ikegami Jul 06 '15 at 14:36
0

You forgot to use use strict. If you do not use strict the global package variable $temp will be used.. See http://perlmaven.com/global-symbol-requires-explicit-package-name.

Package variables are always global. They have a name and a package qualifier. You can omit the package qualifier, in which case Perl uses a default, which you can set with the package declaration. To avoid using global variables by accident, add use strict 'vars' to your program. From the documentation:

use strict vars: This generates a compile-time error if you access a variable that was neither explicitly declared (using any of my, our, state, or use vars ) nor fully qualified. (Because this is to avoid variable suicide problems and subtle dynamic scoping issues, a merely local variable isn't good enough.)

Håkon Hægland
  • 39,012
  • 21
  • 81
  • 174
  • `use strict 'vars'` is one of the strictures that are enabled by `use strict`. Your answer could imply that you need to enable it separately – Borodin Jul 05 '15 at 13:05
  • 2
    This doesn't answer the question and contains the annoying nag that doesn't help solve this problem. – brian d foy Jul 05 '15 at 22:29
0

Without use strict -- specifically use strict 'vars', which is a subset -- just mentioning a variable creates it in the current package. There is no need even for local, and your code can be written like this

sub func{
    $temp = 20;
    print $temp;
}

func();

output

20

That is one reason why use strict is so important, and it is dangerous to omit it. Without it you have no protection against misspelling variables and silently breaking your program

Borodin
  • 126,100
  • 9
  • 70
  • 144
  • 2
    Dangerous? That's a pretty strong statement. – brian d foy Jul 05 '15 at 22:30
  • 1
    @briandfoy: A lot of the danger comes from my reaction to seeing another question on SO that could be solved by enabling strictures – Borodin Jul 05 '15 at 22:33
  • 2
    strict wouldn't solve a question that's not related to a concrete programming problem. This is a question asking how things works and a bunch of people who don't want to explain it pull out this nag about strict. It's not at all helpful and certainly not welcoming. – brian d foy Jul 05 '15 at 22:40
  • 1
    @briandfoy: I'm not claiming that `use strict` would help to answer this question; I'm just using it as an example of what mistakes can go uncaught in its absence – Borodin Jul 06 '15 at 06:56