Wordsmyth's Corner

Perl Primer - Chapter 2 - Variables

by Linda Naughton

Topics
Previous Chapter Next Chapter


Variables

There are no ints/chars/floats like in C.
There are three variable types (identified by the symbol at the front):
Scalars ($)
    $returnValue;
Arrays (@)
    @linesArray;
Hashes (%)
    %reportHash;
%value is a different variable than @value (don't name them the same to avoid confusion)
Identifiers are case-sensitive.
Variables do not need to be declared ahead of time.
Why is that a problem?
$returnValue = 123;
return $returnvalue;  # Returns 0 because you typo'ed!

Variables: Strict

Use strict to enforce variable declarations.
use strict;

# Variable declaration.
my $returnValue;

# Proper use.
$returnValue = 123;

# This will be a compile error.
return $returnvalue;

Implicit Variables

$_ : "default input and pattern matching space" (most commonly used as an iterator)
    foreach (@array)
    { 
    print $_;   # $_ is set to each item in the array in turn
    }

Many functions operate implicitly on $_, but this is obscure and usually best avoided.
    foreach (@array)
    { 
    print;  # Implicitly operates on $_ 
    }
$! : Human-readable system error message (usually used with file operations)
    open(INFILE, "in.txt") or 
    die "Can't read infile: $!\n";
$a, $b : Used in sort functions (see section on sorting arrays) @_ : Stores subroutine parameters (see section on subroutines)

Variables: Context

Make sure that the type of variable is appropriate depending on what you're trying to do with it.
5 + something        # + expects a scalar
sort something       # sort expects an array
print something      # print handles anything (after a fashion)

Scalars: Numbers

Automatically interprets floats and integers (including hex/binary/octal)
$value = 27;
$value = 1.25;
$value = -6.5e24;
$value = 0xff;        # leading 0x for hex
$value = 0377;        # leading 0 for octal
$value = 0b11111111;  # leading 0b for binary
$value = 0x1234_5678; # use _ for long numbers

Scalars: Strings

Strings expand automatically as you add characters to them.
The NULL string terminator is not really visible to Perl.

Single quoted strings (backslash escapes only single-quotes; no variables)

    print Ôhello\nworld' --> hello\nworld
Double quoted strings (backslash escapes normally; variables interpolated)
    $value = 32;
    print "hello\nworld:$value"  -->     hello
                                         world:32
String concatenation
    $longString = "hello\n" . "world";
Strings spanning multiple lines
    $longString = "This is my very long string that ",
                   "spans across multiple lines.";

Scalars: Converting Strings to Numbers

Auto-conversion between numbers and strings:
    12 * 3 = "12" * "3" = "12fred" * "3b2"
Manual conversion between strings and numbers:
   $value = "0xff";
   print $value;          # Prints 0xff
   print hex($value);     # Prints 255

   $value = sprintf("%04x", 255);
   print $value;          # Prints 00ff
TRY IT: Printing Decimal and Hex.

Scalars: undef

Scalar variables initially are set to undef.
Check using the defined function.
my $value;       # Implicitly initialized to undef.
$value = undef;  # Redundant but acceptable.
if (!defined($value))
    { print "Value was not defined!\n"; }

Arrays: What are they?

Arrays are collections of scalars, indexed by number.
Arrays are 0-indexed like in C.
Arrays expand automatically as you add items to them.
Declare an array using the @ prefix:
   my @array;

Arrays: Accessing Elements

Each element in the array is a scalar, so the individual elements are accessed as scalar variables ($)
   my @array;
   $array[0] = undef;
   $array[1] = 123;
   $array[2] = "bye\n";
Arrays are auto-extended. Unassigned values are set to undef.
    $array[0]  = 123;
    $array[10] = 456;   # array items 1-9 automatically 
                         # created and set to undef

Arrays: Special Indices

Finding the number of elements:
    $endIndex = $#array;
    $count = $#array + 1;
Using the array name in a scalar context also gives the number of elements:
    $count = @array; 
-1 accesses the last element:
    $array[-1] = "The End";

Arrays: List Literals

Can be used in contexts that expect arrays. List of scalars.
   @array = (1, 2, 3);
Range operator.
   @array = (1..5);            # 1, 2, 3, 4, 5
   @array = (0, 2..4, 10)      # 0, 2, 3, 4, 10
List of words (qw = quoted words).
   @array = qw(starbuck apollo boomer helo)
It also works the other way.
    @array = (1, 2);
    ($var1, $var2) = @array;   # $var1 = 1, $var2 = 2
Be careful! If you leave off values they will be assigned to undef.
    @array = (1);
    ($var1, $var2) = @array;    # $var1 = 1, $var2 = undef

Arrays: Adding/Removing Items

Push and pop operate on the END of the array.
Shift and unshift operate on the BEGINNING of the array.
    push(@array, 0);
    push(@array, 1);       # Array: 0, 1

    unshift(@array, 0);
    unshift(@array, 1);    # Array: 1, 0

    @array = (0, 1);
    $var1 = pop(@array);   # $var1 = 1;

    @array = (0, 1);
    $var1 = shift(@array); # $var1 = 0;
TRY IT: Push vs Shift.

Arrays: Sorting

Use the sort operator. This DOES NOT modify the original array.
You must assign the result to an array variable if you want to use it.
    @array = (3, 4, 2);
    @array = sort(@array);    # Array contains: 2, 3, 4
The sort operator sorts "ASCIIbetically".
    @array = (32, 3, 4);
    @array = sort(@array);    # Array contains 3, 32, 4

Arrays: Custom Sorting

Specify a sort subroutine after the sort statement.
    @array = (33, 3, 2);
    @array = sort sortNumbers (@array);
The sort subroutine should compare two implicit variables ($a and $b) and return 0 if they are equal, -1 if A comes before B, and 1 if B comes before A (like strcmp).
    sub sortNumbers
    {
    if ( $a < $b ) { return Ð1;}
    elsif ($a > $b) { return 1;}
    else { return 0; }
    }
There's a shortcut for numeric comparison: $a <=> $b
If the sort routine is small enough, you can put it inline:
    @array = (33, 3, 2);
    @array = sort {$a <=> $b} (@array);
TRY IT: Custom Sort

Hashes: What are they?

Hashes are like arrays indexed by name. The name is called the key.
Hashes are not in any particular order.
Like arrays, hashes auto-expand as you add things to them. Declare a hash using the % prefix:
   my %array;

Hashes: Accessing Items

Each item is a scalar, so it is accessed like a scalar variable ($).
   $hash{$key}
Example: Storing name and address. Name is the key, address is the data.
    $hash{"fred"}   = "123 First Street";
    $hash{"barney"} = "789 Bedrock Lane";

    $address = $hash{"fred"}; # Gets Fred's address.
You can also initialize a hash using the => ("big arrow") operator:
%hash = ( "fred"   => "123 First Street",
          "barney" => "789 Bedrock Lane" );

Hashes: Keys

Each key must be unique:
    $hash{"fred"} = "123 First Street";

    # This overwrites Fred's address.
    $hash{"fred"} = "234 Second Street"  
You can get a list of keys using the "keys" operator.
    $hash{"fred"}   = "123 First Street";
    $hash{"barney"} = "789 Bedrock Lane";

    # @keys contains "fred" and "barney"
    @keys = keys(%hash);   
Since the list of keys is an array, it can be sorted. This is handy for iterating through hash elements.

There's also a values function for getting the values, but that's not commonly used.

TRY IT: Creating Hashes

Hashes: Checking for Elements

The exists function checks to see if a key exists.
    if (!exists($hash{"fred"})
    {
    print "Can't find Fred's address!\n";
    }
Exists will return true even if the actual data is undef.
    $hash{"fred"} = undef;   # Fred still exists!
The only way to remove a key is through the delete function.
    delete($hash{"fred"});   # Fred no longer exists.
Or to remove them all.
    undef(%hash);

Hashes: Nested Hashes

You can have "nested" hashes.
    KEY      =>  SUBKEY1  =>  DATA1
             =>  SUBKEY2  =>  DATA2
This is commonly used for simulating arrays of structures. For example, assume we want a "structure" containing name, address and phone number (with name being the key):
    $hash{"fred"}{"address"} = "123 First Street";
    $hash{"fred"}{"phone"} = "412-555-1234";
    $hash{"barney"}{"address"} = "789 Bedrock Lane";
    $hash{"barney"}{"phone"} = "412-555-2345";

    # This gets Fred's address
    $address = $hash{"fred"}{"address"};

    # This gets Barney's phone number
    $phone = $hash{"barney"}{"phone"};
Getting the keys for the nested hashes is a little more complicated.
    # Gives keys for the main hash (fred, barney)
    @keys = keys(%hash); 

    # Gives the sub-keys (address, phone) for fred
    # The %{} syntax is like a cast.
    @subkeys = keys(%{$hash{"fred"}})

Constants

Constants in Perl are wacky. They're defined almost like hashes with the "use constant" syntax.
   use constant LOG_FILE_NAME     => "log.txt";
   use constant MAX_STRING_LENGTH => 22;
Once they're defined, you can use them without a $ in statements.
    print LOG_FILE_NAME;
    if ($stringLength < MAX_STRING_LENGTH)
However, unlike variables, they are not interpolated in strings.
    print "Log File: LOG_FILE_NAME\n";    # Doesn't work.
To evaluate a constant inside a string requires special syntax.
    print "Log File: ${[LOG_FILE_NAME]}[0]\n";    # Works.
For that reason, I usually avoid the "use constant" syntax and just declare constants like normal variables, but in all uppercase:
    my $LOG_FILE_NAME = "log.txt";
Previous Chapter Next Chapter