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

Prev | Up | Contents | Down | Next

2.3. Perl Variables

Second look on scalar variables

Second Look on Arrays

Second look on hashes (Associative arrays)

Implementing read-only variables in Perl

Typical errors


Note to whose who previously programmed in C:

In interpretive language that table of variables that interpret created during parsing of the source code is present during execution. that creates several unique possibilities.

First of all in this table you can store a special bit which that determines if the variable was initialized or not. If a variable is not initialized you can also assume that it has a special "red-only" value undef. Perl has access to this field via build-in function defined. Using it you can check if variable was initialized or not.

You can also provide the operation of restoring uninitialized status of the  variable by resetting this bit feels . In Perl this is accomplished by assigning to the variable the value of undef.  

For complex structure like dictionaries (hashes) it is also possible to determine is particular key exists (built-in function exists, see below).

Previously complied languages have great difficulties with determining if the variable exists. For example PL/1 debugging complier pre-initialize all variable with a special rearely occurring bit string and if the value of the variable was this bit string it viewed it as uninitialized.  Not with interpretive language this operation became trivial.

Another option that arise due to existence of the symbol table at run time  is that type of the variable can be dynamic. It is just a special field in the symbol table and when you assign to the variable a constant of a different type you just correct this field. Perl went too far in the freedom of changing type. You can convert any variable to numeric field (zero if you can't convert) or string. That create possibility of difficult to find run time bugs.  As of  Perl 5/10 there is no possibility to declare type of the variable in Perl. While such possibility already exists in bash 5. 

Scalar variable are prefixes with  sigil $ which you can interpret as dereferencing operation: "take value of the memory location" So the variable $line  can be interpreted as the value stored at location line. So this can be viewed as a neat trick not nuisance and it allow to interpret variable in double quoted string constants, the fit that Python did not do right until the introduction of f strings in Python 3.6...

Like C Perl variable names are case sensitive, so variables $a and $A are different.

Like C Perl is case sensitive, so variables $a and $A are different

Perl has just five  basic types of variables:

All Perl variables have special prefixes that act much like "on the fly" declarations of the type. You can also think about $ of a function that converts to string a variable that it prefixed.

The main achievement of Perl in this area is the introduction of the undef value. This is a very interesting and pretty innovative solution to the problem of uninitialized variables.

NOTE: By convention you can use a leading underscore on names to informally indicate that they are 'internal' and not for public use

The Second Look on Scalar variables

Let's reiterate what we already know about scalar variables from previous section. At this point I believe many suspect that scalar variables in Perl always start with $ and can hold both strings and numbers. This is true and a scalar variable always has a string value and a numeric value. Yes, any string in Perl has a numeric value, and in case of non-numeric strings this value is  zero. But there is one gotcha: is string starts with numbers its value will be the extracted as the value of this numeric prefix:

my $var1 = "123abc";
print($var1 + 0); # will print 123
But in general Perl treats the data based on the operators you use and the context in which you use them. Here are a couple of examples:
$price = 5.0; # this variable is assigned a numeric value
print "price=$price"; # will print 5 as $price is assumed by Perl to be a numeric variable. 

First Perl determines that left side of expression is well-formed numeric value. Then it will convert it to double-float (internal representation of numeric values in Perl). In the second statement Perl interpreter  will convert numeric value to string. So the value of the scalar printed will be 5 not 5.0.

$price = '5.0'; # this variable is assigned a numeric value
print "price=$price"; # will print 5.0 as $price is assumed by Perl to be a string variable. 

As you see, if you supply the number as a string literal than string value will be stored first. It will not be converted to numeric value.

In general variable names consists of numbers, letters and underscores, but they should not start with a number and the names like $_ and several others are special, as we'll see later.

Many Perl operations return undef to indicate unusual situations -- failure, end of file, system error, uninitialized variable, and other exceptional conditions. There is a defined() function than allows you to check whether a variable contains the undef value. A conditional expression will not distinguish among undef, zero, the empty string, and string "0", which are all considered to be false.

 A conditional expression will not distinguish among undef, zero, the empty string, and string "0", which are all considered to be false.

Note that since undef is a valid scalar, its presence doesn't necessarily indicate an exceptional condition: many built-in functions returns undef when there no output any more (but also in case when element happens to have the value undef.)

Note that since undef is a valid scalar, its presence doesn't necessarily indicate an exceptional condition: many built-in functions returns undef when there no output any more (but also in case when element happens to have the value undef.)

Use of built-in function defined() upon aggregates (hashes and arrays) is not guaranteed to produce intuitive results, and should probably be avoided. When used on the element of an associative array (hash -- see below), it tells you whether the value is defined, not whether the key exists in the hash. Use exists for the latter purpose.

Undef and scalar variables

One big advantage of interpreted languages is that they can check whether the variable was initialized or not. Here Perl provides a solution that is superior to any other I know of. It explicitly defines special undefined value and set of functions to check for this value.

You can check if the variable exists in the symbol table (was it initialized or not) by using special built-in function defined. All uninitialized variables are assumed to have a special value before they are assigned any explicitly -- this value is called undef. Paradoxically you can assign undef like any other value to variables. Logically this should mean that the variable is deleted from the symbol table, but I do not know whether this true in Perl or not. For example:

$arg1 = undef; # set to undef
undef($arg1); # same as above
In Perl all uninitialized scalar variables are assumed to have the value undef .

Please note that -w switch produce some partially useful warning about uninitialized variables and this is another case when it can be useful.

That leads to the major difference between Perl and most of compiled languages (C, Pascal, etc.) -- a scalar variable can be used without initial assignment a value to it (initializization). In this case it has a default value undef that can be converted to string (resulting in zero length string) or to numeric value (resulting in 0).

In numeric operations the undef value is converted to zero much like and string literal. So it is perfectly legal to write

$k=$i+0;

Let's assume that at in this expression the variable $i is undefined and uninitialized. It is first created with initial value undef. Then because operator "+" requires numeric value it is converted to a numeric value (zero). Uninitialized value can also be used for comparison -- they will be converted according to the operator either to text value (zero length string) or numeric value (zero).

For arithmetic operations undef behaves like 0, for sting operations like zero length string

If you need to test whether or not a scalar has initialized you can use defined function. For example, if argument was passed to a subroutine then the corresponding variable can be either defined or undefined. If it is not defined, then you need to assign default value to it providing Perl with the capability to set default variables to subroutine parameters. We will learn about them more later.

From logical standpoint you cannot use undef in comparison because the type of variable in Perl is determined by an operator and should be either numeric or string depending on context:

if ( $arg1 == undef ) {...} # undef will always be converted to zero first  

The undef value is often used in Perl instead of exceptions to signal end of the data stream (Perl 5 does not support the notion of exceptions). For example as we will see in Ch.4, when you read the file and reach the end, the value undef is returned to signal that there is no more records in the file. Similarly functions can signal that there is no more values by returning the undef value.

Here is how defined if described in Perl documentation (perlfun):

Returns a Boolean value telling whether EXPR has a value other than the undefined value undef. If EXPR is not present, $_ will be checked.

Many operations return undef to indicate failure, end of file, system error, uninitialized variable, and other exceptional conditions. This function allows you to distinguish undef from other values. (A simple Boolean test will not distinguish among undef, zero, the empty string, and "0", which are all equally false.) Note that since undef is a valid scalar, its presence doesn't necessarily indicate an exceptional condition: pop() returns undef when its argument is an empty array, or when the element to return happens to be undef.

You may also use defined() to check whether a subroutine exists, by saying defined &func without parentheses. On the other hand, use of defined() upon aggregates (hashes and arrays) is not guaranteed to produce intuitive results, and should probably be avoided.

When used on a hash element, it tells you whether the value is defined, not whether the key exists in the hash. Use exists for the latter purpose.

Operations of scalar variables

(to be written)

The Second Look on Arrays

Arrays allow to access to their elements by number. Array in Perl are quite different from arrays in C and are more like a buffer of a text editor with indexes as line numbers. There are two notation for arrays -- regular index notation and so called list notation. For example (1,2,3) is an array with three elements.

Like in C and unlike any text editor the first element of array has index zero. For example the first element of array @mybuffer is $mybuffer[0], the second element is $mybuffer[1], and so on.

One needs to use prefix @ for arrays and prefix $ for array elements.
Please remember that @x[1] is array with one element

You can initialize arrays using list notation:

@x=(1,2,3) # now 
	@x contains three elements $x[0], $x[1] and $x[2]

Negative indexes does not make sense in Perl arrays, but they are used to denote access to the end of the array, not from the start. The last element is $mybuffer[-1], the element before last is $mybuffer[-2], etc. This is quite convenient shortcut worth remembering.

Negative indexes are used to access elements from the end of the array, not from the start:
$mybuffer[-1]
# the last element
$mybuffer[-2] # the element before last.

Again, arrays in Perl are much more like lists (or buffers of text editors which are essentially lists) -- they have no lower or upper bound and can accept any type of variable (both numbers and strings). All array names are prefixed by an @ symbol, but elements are prefixed with $. For example:

@workweek  = ("Mn", "Ts", "Wn", "Th","Fr"); # initialization of array @workweek with 5 values
@weekend = ("St", "Sn");
These statements assigns a five element list to the array variable @workweek and a two element list to the array variable @weekend.

Like in C the array is accessed by using indices starting from 0, and square brackets are used to specify the index. For example:

print $workweek[4]; # will print Fr. Notice symbol $ instead of @

This substitution of @ with $ is a frequent source of errors for beginners. Be careful. In this particular case there is some logic in this convention (after all each element of array is a scalar) and you need to adapt to it.

If you want to access one element of array you need to use a scalar like in $week[0]. Usage of @week[0] is a frequent error (this is interpreted as a slice -- see below). Watch your steps !

If index is non-numeric that 0 will used. So the following two statements are equal:

$color["abba"]="blue";
$color[0]="blue";  # same as above

Slices

Unlike C it is possible to specify multiple indexes. This is called a array slice or simply slice. For example

@x[1,2]=(3,4) # slice of array 
@x with indexes 1 and 2 is assigned values 3 and 4 

Any slice in scalar context returns the last element of the slice, not the number of elements like an array. So

$s=@x[0]; # wrong way to assign 
	$x[0] to a veriable $s

Slices accept Pascal range notation (..). for example

@x[2..5]=(1,2,3,4);
@danger_levels[1..3]=('green','orange','red'); 

Arrays on the left side of assignment statement are evaluated before any operations on right side. That's mean that in Perl you can exchange two elements using:

($a,$b)=($b, $a);

Undef and arrays

Only uninitialized scalar variables in Perl have the undef value. Uninitialized arrays have the value of the empty list (). You can assign undef value to array and pretty logically it destroys the content of the array and free all the memory. The same effect can be achieved by assigning the array an empty list and this is a more common notation.

Unlike scalars the initial value of array is not undef value, but an empty list (). The built-in function undef converts any array to empty list.

You cannot shorten array or remove elements from array by assigning undef value to them. This not very logical but that's how it is. So here undef is a special value, not just the fact of absence of identifier in the symbol table like it the logical view on undef for scalars presuppose.

Operation on arrays

Arrays are classical data structure. So operations on arrays will be discussed in more details in the next chapter.

The Second Look on Hashes
(Associative Arrays
)

Associative arrays or hashes are a generalization of a regular arrays to a non numeric indexes. They provide a built in search capability . You put values into the hash by defining key-value pairs. Like Perl arrays, hashes grow and shrink automatically when you add or subtract elements. The main difference is that array indexes are converted to numeric before retrieving the value and in associative arrays they are converted to string and are usually arbitrary strings (for regular arrays all non-numeric indexes are equivalent to the index 0).

The second important difference is that associative array entries are not created on mere reference, like scalars.

To define an associative array we use the usual parenthesis notation, but the array itself is prefixed by a % sign. Suppose we want to create an array of url of sites and there IP addresses. It would look like this:

%ip =( "www.yahoo.com",          "204.71.200.68", # note brackets "(" and ")"      
       "www.google.com",         "209.185.108.220",
       "www.northenlight.com",   "128.11.1.1",
     );

As a cosmetic improvement we can replace ",' with "=>". this way it's easier to count pairs so it is a recommended notation in all cases where Perl script is written by human (in generated scripts notation above is simpler and can be preferable):

%ip = ( "www.yahoo.com"        => "204.71.200.68",
        "www.google.com"       => 209.185.108.220",
        "www.northenlight.com" => "128.11.1.1",
  );
Now we can find the IP addresses of sited with the following expressions (note curly brackets):
$ip{"www.yahoo.com"};		# Returns 204.71.200.68
$ip{"www.northenlight.com"};	# Returns 128.11.1.1
Notice that like in arrays to access elements of hash each % sign has been changed to a $ because that element is a scalar. Unlike list arrays, the index (in this case the person's name) is enclosed in curly braces.

An associative array can be converted back into a list array just by assigning it to a list array variable. Order of variable is underemined in this conversion. A list array can be converted into an associative array by assigning it to an associative array variable. each pair will be converted into one hash element. Logically the list array should have an even number of elements, but if not the value of the last will be undef.

@info = %ip;		# @info is a list array. It
# now has 6 elements, but the order of pairs may changed
%ip=@info; # Reverse operation

If you wish to access a value, you can say:

print $ip{'www.yahoo.com'}; # note curly brackets

Again note that one needs to use prefix $ instead of %. To change the value you can also say:

$ip{'www.yahoo.com'} = '204.71.200.67'; 

Hashes are not lists, so there is no previous and next element related operations defined on hashes. If you try to get all of them, then the order in which Perl will extract values is undetermined and can be different from the order in which you put elements into the hash.

You can delete a single element of hash with the operator delete, for example:

delete $ip{'www.yahoo.com'};

Undef and hashes

Like arrays the initial value of hash is an associative array with no elements. So if you convert such hash to an array you will receive an empty list. Built-in function undef is applicable to hashes and will convert any hash to an empty one. As you will see in the next chapter you need to apply a special built-in function delete to remove element from the hash.

Operation on Hashes

Hashes are non-traditional data structure and here Perl is a to certain extent a pioneer. We will discuss operations on hashes in more details in the next chapter.

Implementing read-only variables in Perl

Modern languages need to have the facility for creating non-modifiable variables. The first widely adopted language that provided this capability was probably Korn shell. Ability to use constants is very useful for configuration files, headers, etc. Catching updates to variables that should not be changed is a very useful debugging tool.

Perl does not provide explicit facility for creating constant values, but there are some way around via typeglobs construct and/or the "use constant" pragma. All of them are deficient in implementation and clumsy to use:

There is also Readonly.pm but it imposes a performance penalty. In other words it's pretty slow and pretty complex. Not recommended. I think that this feature should be implemented on the language level not via crutches.

Typical errors

The most typical error in Perl related to variables is a typo in the variable name, which automatically creates a new uninitialized variable.

The most typical error in Perl related to variables is a typo in the variable name, which automatically creates a new uninitialized variable.

There is a strict pragma that helps to avoid such errors, but you generally should use editor that suggest the names of the variables from after typing prefix such as free Comodo editor.

Another typical error is to use @ prefix where $ is required, For example @x[5] instead of $x[5].

Most modern versions of Perl interpreter (I think starting from 5.10) warn about such an error

Prev | Up | Contents | Down | Next



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: October 01, 2019