Softpanorama

May the source be with you, but remember the KISS principle ;-)
Home Switchboard Unix Administration Red Hat TCP/IP Networks Neoliberalism Toxic Managers
(slightly skeptical) Educational society promoting "Back to basics" movement against IT overcomplexity and  bastardization of classic Unix

Introduction to Perl 5.10 for Unix System Administrators

(Perl 5.10 without excessive complexity)

by Dr Nikolai Bezroukov

Contents : Foreword : Ch01 : Ch02 : Ch03 : Ch04 : Ch05 : Ch06 : Ch07 : Ch08 :


Prev | Up | Contents | Down | Next

Scope of Variables


Scope refers to the visibility of variables. In other words, which parts of your program can see or use it.

By default in Perl every variable has a global scope. That means that once defined, every part of your program can access a variable. This arrangement is not very suitable for functions and subroutines. It is much more useful to be able to limit a variable's scope to a single function. In other words, the variable will have a scope of function. This way, changes inside the function's variables can't affect the main program in unexpected ways.

There are thee types of variables in Perl that can create some level of isolation of subroutine namespace from the rest of the program:

Having just variables that are created on entry to subroutine and destroyed on exit is not a very good to encapsulate subroutine. So Perl was rather weak in this respect until recently (2007 or Perl 5.10). The situation improved in 2007 with the introduction of state variables. This is a valuable alternative to "my" variables. Unlike them  state variables keeps the value between invocations which often is needed to preserve that state of the subroutine. They more or less correspond to static variables in C and PL/1 and it was a blunder not to include them into the language earlier as there is nothing new in the concept. Still this was an the most important addition to the language in version 5.10 that we are studying as it rectified serious deficiency of previous version in subroutines local variables implementation.

Strange properties of elements of @_ array

The @_ variable is local to the current subroutine, but its elements  $_[0], $_[1], $_[2] are not. Jumping ahead to the topic of references (see Chapter 7) you can think about them as references to the actual variables that are automatically dereferenced.

If you change any of them you change the variable that was passed to subroutine. In order to avoid the problems you can use temporary variable, but by default they will be global.

Qualifier my

The scope of the variable declared with qualifier my is the block of code to which it belongs and all inner blocks.  If you declare it at the beginning of the subroutine that will be the whole subroutine. Typically my is used for variable inside subroutine to protect them from being over-written in main program and vise versa. 

$var=1;
broken();
print "$var in main\n";

sub broken {
  $var=2; # overwrites the value of var in main script
  print "$var in sub\n"; 
}

You can fix this using qualifier my in subroutine:

$var=1;
broken();
print "$var in main\n";

sub broken {
my $var=2; # overwrits the value of var in main script
  print "$var in sub\n";
}
qualifier my is not applicable to the special variables.  As we have seen, they change the workings of Perl functions and operators. (For example, "$/" changes the way "<STDIN>" breaks "lines".) This is an expected and desired side effect.

But when we start using functions (other than those built into the language), we may run into situations where one part of the code doesn't anticipate the fact that another part of the code changed a global variable. Here is an example:

   # Declare function "home_dir". Takes a
   # username and returns its home directory.
   sub home_dir {
     open PASSWD, '< /etc/passwd' or die "Uh oh: $!";
     $/ = ':';               # Records separated by colons.
     # ...
     close PASSWD;
     return $home;
   }

   # Main body.
   # Read usernames (one per line).
   open FILE, '< somefile.txt' or die "NO!!!";
   while ( my $username = <FILE> ) {
     chomp($username);
     my $home = home_dir($username);
     print "$username: $home\n";
   }
   close FILE;
Because "$/" is global, the "$/" in the function is the same as the "$/" in the main body. So setting $/ in the function changes the way "<FILE>" operates in the main body. This type of bug is difficult to track down.

We cannot solve the problem by declaring $/ with "my" because we want it to have some side effects (besides, Perl will yell at you if you try). So we declare it as "local". Variables declared with "local" can be accessed by functions called within the code block, but after the code block is closed (with a "}") the change ceases to take effect. You should usually use "local" when you change a special Perl variable:

   # Declare function "home_dir".
   sub home_dir {
     open PASSWD, '< /etc/passwd' or die "Uh oh: $!";
     local $/ = ':';       # Declare variable and set value.
     # ...
     close PASSWD;
   }
But there's an even more subtle trap here. If we had changed the variable in the main body and not the function, the change would have been reflected in the function even if it was declared as local in the main body:
   # Stupid function; just for demonstration.
   sub read_line {
     return <STDIN>;
   }

   # Main body.
   local $/ = ',';
   # ...
   print read_line() . "\n";
In this example, setting $/ has an effect on "read_line" even though "$/" was declared as "local". It's important that you understand the difference between this example and the previous one. One way to guard against this later problem is to enclose the changed variable in a code block:
   # Main body.
   {   # Introduce code block; scope is reduced to this block.
     local $/ = ',';
     # ...
   }   # End of block. Local $/ goes out of scope.
   print read_line() . "\n";
But this implies knowing that "read_line" would be affected by your changed variable. Are you supposed to check the implementation of every function you call to see if it uses any built-in Perl variables? Of course not! Instead, the rule is: as much as possible, you should not call ANY function when you have changed a special variable, unless you intended the change to affect that function. The corollary to that rule is: make the code block containing the changed variable as small as possible.

It's especially important to declare "$_" as local in functions, to avoid this problem:

   # Change employee list to keep up with people quitting.
   while ( <IN_FILE> ) {
     my $quit_person = GetPersonWhoQuit();   # Did this change "$_"?
     s/$quit_person//g;        # Uh oh: where did the line of input go?
     print OUT_FILE;           # I wonder what we just output!
   }
Of course, you should use your common sense here. For example, when you change "$<" (user ID), you probably want the change to be permanent and global. Likewise, functions should definitely declare "$_" as local, but declaring "$!" (last error) as local is probably less important because that variable is expected to change - indeed, the caller might use "$!" to understand why the function failed. Think carefully about the expected behavior, but when in doubt, avoid side effects.

Qualifier State

The main difference is that there is no automatic reallocation and re-initialization (to undef or specified value) like happens with my variables. Moreover if the variable is initialized in declaration, then it will never be reinitialized, contrary to my variables that are reinitialized each time their enclosing block is entered. In other words static variables behavior is imitated with the variables allocated in the heap. 

The value of state variable is preserved between calls. Consider the following example:

  1 use feature qw( :5.10 );
  2 sub counter {
  3    state $number_of_invocations=1; # will never be reinitialised after the first invocation
  4   
  5    print "number of invocations=$number_of_invocations\n";
  6    $number_of_invocations++;
  7 }
  8
  9    for $i (1..10) {
 10        counter();
 11    }
Result of execution:
perl test_state_attr.pl
number of invocations=1
number of invocations=2
number of invocations=3
number of invocations=4
number of invocations=5
number of invocations=6
number of invocations=7
number of invocations=8
number of invocations=9
number of invocations=10

Qualifier local

This feature came from Perl 4 and used rarely in Perl 5. For some cases where it makes sense see Seven Useful Uses of Local

To make them local one needs to use local (better for debugging) or my (better for production, but not visible in the debugger) keyword. Local keyword actually define a global variable but previous value is pushed at the beginning of the block and popped at the end. Both represent rudimentary means of declaring variables in Perl.

Let's discuss a simple example.  The following subroutine tests to see if one string is substring of the another much like index, but case insensitive.

$a="Hello world";
$b="hello";
if ($k=inside($a,$b)+1) {
   print qq(The substring "$b" was found in the string "$a" from the position $k);
} else  { 
   print qq(The substring "$b" was not found in the string "$a");
}
sub inside # case insensitive index function
{
	my ($a, $b);			# change to local for debugging
	($a, $b) = ($_[0], $_[1]);	# Assign values
	$i=index(uc($a),uc($b));
	return $i;	
}

You can combine declaration and assignment of initial values to the local variables in PL/! (or C) style:

my ($a, $b) = ($_[0], $_[1]);

Another example shows that the fact that operations define the type of operand is detrimental to the programming generic subroutines. The problem is that there is no generic way to make this subroutine work both on numeric and string arrays.

print max(9,0..5,7) . "\n"; # no the the method of generation of the input data
print max(5..7, 3..11) . "\n";

# find the maximum element of a numeric array
sub max { 
    my($max) = shift(@_); # get the first element and assign it to $max
    foreach $t (@_) {
        if ($t > $max) {$max = $t;} # check each element and replace if nessesary
    }
    return($max); # return what we got
}

Recommended Links

Seven Useful Uses of Local



Etc

Society

Groupthink : Two Party System as Polyarchy : Corruption of Regulators : Bureaucracies : Understanding Micromanagers and Control Freaks : Toxic Managers :   Harvard Mafia : Diplomatic Communication : Surviving a Bad Performance Review : Insufficient Retirement Funds as Immanent Problem of Neoliberal Regime : PseudoScience : Who Rules America : Neoliberalism  : The Iron Law of Oligarchy : Libertarian Philosophy

Quotes

War and Peace : Skeptical Finance : John Kenneth Galbraith :Talleyrand : Oscar Wilde : Otto Von Bismarck : Keynes : George Carlin : Skeptics : Propaganda  : SE quotes : Language Design and Programming Quotes : Random IT-related quotesSomerset Maugham : Marcus Aurelius : Kurt Vonnegut : Eric Hoffer : Winston Churchill : Napoleon Bonaparte : Ambrose BierceBernard Shaw : Mark Twain Quotes

Bulletin:

Vol 25, No.12 (December, 2013) Rational Fools vs. Efficient Crooks The efficient markets hypothesis : Political Skeptic Bulletin, 2013 : Unemployment Bulletin, 2010 :  Vol 23, No.10 (October, 2011) An observation about corporate security departments : Slightly Skeptical Euromaydan Chronicles, June 2014 : Greenspan legacy bulletin, 2008 : Vol 25, No.10 (October, 2013) Cryptolocker Trojan (Win32/Crilock.A) : Vol 25, No.08 (August, 2013) Cloud providers as intelligence collection hubs : Financial Humor Bulletin, 2010 : Inequality Bulletin, 2009 : Financial Humor Bulletin, 2008 : Copyleft Problems Bulletin, 2004 : Financial Humor Bulletin, 2011 : Energy Bulletin, 2010 : Malware Protection Bulletin, 2010 : Vol 26, No.1 (January, 2013) Object-Oriented Cult : Political Skeptic Bulletin, 2011 : Vol 23, No.11 (November, 2011) Softpanorama classification of sysadmin horror stories : Vol 25, No.05 (May, 2013) Corporate bullshit as a communication method  : Vol 25, No.06 (June, 2013) A Note on the Relationship of Brooks Law and Conway Law

History:

Fifty glorious years (1950-2000): the triumph of the US computer engineering : Donald Knuth : TAoCP and its Influence of Computer Science : Richard Stallman : Linus Torvalds  : Larry Wall  : John K. Ousterhout : CTSS : Multix OS Unix History : Unix shell history : VI editor : History of pipes concept : Solaris : MS DOSProgramming Languages History : PL/1 : Simula 67 : C : History of GCC developmentScripting Languages : Perl history   : OS History : Mail : DNS : SSH : CPU Instruction Sets : SPARC systems 1987-2006 : Norton Commander : Norton Utilities : Norton Ghost : Frontpage history : Malware Defense History : GNU Screen : OSS early history

Classic books:

The Peter Principle : Parkinson Law : 1984 : The Mythical Man-MonthHow to Solve It by George Polya : The Art of Computer Programming : The Elements of Programming Style : The Unix Hater’s Handbook : The Jargon file : The True Believer : Programming Pearls : The Good Soldier Svejk : The Power Elite

Most popular humor pages:

Manifest of the Softpanorama IT Slacker Society : Ten Commandments of the IT Slackers Society : Computer Humor Collection : BSD Logo Story : The Cuckoo's Egg : IT Slang : C++ Humor : ARE YOU A BBS ADDICT? : The Perl Purity Test : Object oriented programmers of all nations : Financial Humor : Financial Humor Bulletin, 2008 : Financial Humor Bulletin, 2010 : The Most Comprehensive Collection of Editor-related Humor : Programming Language Humor : Goldman Sachs related humor : Greenspan humor : C Humor : Scripting Humor : Real Programmers Humor : Web Humor : GPL-related Humor : OFM Humor : Politically Incorrect Humor : IDS Humor : "Linux Sucks" Humor : Russian Musical Humor : Best Russian Programmer Humor : Microsoft plans to buy Catholic Church : Richard Stallman Related Humor : Admin Humor : Perl-related Humor : Linus Torvalds Related humor : PseudoScience Related Humor : Networking Humor : Shell Humor : Financial Humor Bulletin, 2011 : Financial Humor Bulletin, 2012 : Financial Humor Bulletin, 2013 : Java Humor : Software Engineering Humor : Sun Solaris Related Humor : Education Humor : IBM Humor : Assembler-related Humor : VIM Humor : Computer Viruses Humor : Bright tomorrow is rescheduled to a day after tomorrow : Classic Computer Humor

The Last but not Least Technology is dominated by two types of people: those who understand what they do not manage and those who manage what they do not understand ~Archibald Putt. Ph.D


Copyright © 1996-2021 by Softpanorama Society. www.softpanorama.org was initially created as a service to the (now defunct) UN Sustainable Development Networking Programme (SDNP) without any remuneration. This document is an industrial compilation designed and created exclusively for educational use and is distributed under the Softpanorama Content License. Original materials copyright belong to respective owners. Quotes are made for educational purposes only in compliance with the fair use doctrine.

FAIR USE NOTICE This site contains copyrighted material the use of which has not always been specifically authorized by the copyright owner. We are making such material available to advance understanding of computer science, IT technology, economic, scientific, and social issues. We believe this constitutes a 'fair use' of any such copyrighted material as provided by section 107 of the US Copyright Law according to which such material can be distributed without profit exclusively for research and educational purposes.

This is a Spartan WHYFF (We Help You For Free) site written by people for whom English is not a native language. Grammar and spelling errors should be expected. The site contain some broken links as it develops like a living tree...

You can use PayPal to to buy a cup of coffee for authors of this site

Disclaimer:

The statements, views and opinions presented on this web page are those of the author (or referenced source) and are not endorsed by, nor do they necessarily reflect, the opinions of the Softpanorama society. We do not warrant the correctness of the information provided or its fitness for any purpose. The site uses AdSense so you need to be aware of Google privacy policy. You you do not want to be tracked by Google please disable Javascript for this site. This site is perfectly usable without Javascript.

Last modified: March, 12, 2019