perlsOfLondon

 

Variables, Scope, and Autovivification

Page history last edited by dmlond 2 yrs ago

  • Perl Variables: Things that you assign other things to (eg, scalars, arrays, hashes, references; We will discuss these DataTypes next). There are not alot of naming conventions in perl, and only a few reserved words. Variables start with either $ (scalar), @ (array), or % (hash) (or nothing, but only in the case of filehandles and some other things which you probably wont use). Case is significant - FOO, Foo and foo are all different names. Names that start with a letter or underscore may be of any length (well, 255 characters, at least) and may contain letters, digits, and underscores. Names that start with a digit may only contain more digits. Names that start with anything else are limited to that one character (like $? or $$), and generally have a predefined significance to Perl. For example, just as in the Bourne shell, $$ is the current process ID and $? the exit status of your last child process (You will probably never want to name variables with anything but letters, digits, and underscores). Each variable of a different type has a different underlying namespace. %foo, $foo, and @foo are different objects (note, all of this is quoted from Programming Perl, 3rd Edition by Larry Wall, et. al).
  • $_: Perl provides some special variables that you will make use of. One of these is $_. This variable always contains the current item available when iterating over a list without specifically assigning that variable a name. Most of perls internal commands use it as the default, when not specified, so you will often see it being used even if it isnt actually being 'used'.

    my @array = qw(a b c d e);
    foreach (@array) { print; }

    #is the same as
    foreach (@array) { print "$_"; }

    #you must use the variable to format it in some way
    foreach (@array) { print "\n"; } # only prints a newline
    foreach (@array) { print "$_\n"; } # prints the item followed by a newline
    foreach (@array) { print "WE GOT ITEM $_\n"; }

  • Scope: Unless otherwise specified, perl variables default to global scope, meaning they are available to the entire application in some way. Variables can (and should) be scoped using the 'my' keyword. I highly recommend using the 'strict' pragma, which forces you to scope your variables with my or our (rarely needed). My variables are always scoped to the block where they are created, and all blocks 'below' this block, unless overridden with a newly scoped variable of the same name within a particular block. Perl also allows the 'our' keyword, but because I have never used it (and rarely see it used in all the CPAN modules I have looked at), I cant really tell you much about it.

    use strict;

    my $stuff = "hello";
    print "$stuff\n"; # prints hello

    {
      print "$stuff\n"; # prints hello
      $stuff = "goodbye"; # changes main::$stuff, may or may not be what you want to do.
      my $stuff = "goodbye"; # creates local $stuff, can be manipulated without affecting main::$stuff
      print "$stuff\n"; # prints goodbye
    }

    print "$stuff\n"; # prints hello, unless modified by lower block

    Note that this also applies to eval blocks, and subroutine blocks (we will learn more about eval and subroutines later), but perl does impose a linear scoping mechanism which makes the order of subroutine/main code important (yes, perl does have a 'main' section, and this can be specified, but usually isnt necessary. Anything not within a subroutine is in main).

    sub broken {
      print "$stuff\n";
    }

    sub not_broken {
      my $stuff = "goodbye";
      print "$stuff\n"; # prints goodbye
    }

    my $stuff = "hello";
    print "$stuff\n"; # prints hello

    &not_broken_but_may_not_be_what_you_want(); # prints hello, but CHANGES main::$stuff!!!
    print "$stuff\n"; # prints goodbye, wait a minute, where did that happen??

    sub not_broken_but_may_not_be_what_you_want {
      # this is main::$stuff
      print "$stuff\n"; # prints hello
      $stuff = "goodbye"; # changes main::$stuff so be careful anytime this sub is called (not good practice)
    }

    sub not_broken_two {
      my $stuff = "goodbye"; # local $stuff, does not affect main::$stuff
      print "$stuff\n"; # prints goodbye
    }

  • Autovivification: Everything in perl can and will be created when it is used. This is extremely useful with array and hash elements, but is usually dangerous with variables. Using the strict pragma prevents autovivification of named variables (though not array and hash elements).

    $stuff = "hello";
    print "$stuf"; # prints undefined, because misspelled $stuf is autovivified to undef

    my $stuff = &some_subroutine($somedata);
    if ($stuf) {
      # this will never get run, because the misspelled $stuf will autovivify to undef, which is false in perl
      &dosomethingwith($stuff);
    }

    use strict;
    my $stuff = &some_subroutine($somedata);
    if ($stuf) {
      # this will throw a runtime exception under strict
      &dosomethingwith($stuff);
    }

    use strict;
    $array[5] = "something"; # throws runtime exception because @array has not been declared as a my variable

    use strict;
    my @array;
      $array[5] = "something"; # does what you think, it autovivifies the 6th item in the array, even if the first five elements are undef

    my %seen = ();
    foreach (@item) {
      &do_something_with($_) unless ($seen{$_}++); # this will autovivify the element in seen if $_ doesnt exist as a key, AND it will increment it as an integer this and each subsequent time it is seen
    }

Comments (0)

You don't have permission to comment on this page.