Lesson 2

No-one likes being type-cast

Some technicalities. Perl is often termed a weakly typed language. For those of you coming from bondage and discipline languages like C or Java, this means no floats, doubles, integers, characters, booleans, strings and suchlike. For those of you who are learning programming here, this means you don't have to worry about what you put into a variable like $name, especially, you don't need to worry if its a little integral number like 3, a big fat floating point number like 12.045e+89, a single character k, a string (like "Aisha likes beans"), or anything else.

Perl does have data types though. However, what Perl worries about is not the distinctions a computer would like to make (in terms of how big a chunk of data is in memory), but the distinction between singular and plural, much like many human languages. In perl, singular data is called scalar data, and comes in variables starting with a $. Plural data is called array (or list) data, and is stored in variables starting with a @.

(For the über-anal amongst you, Perl is in fact very strongly typed, it's just that the completely uncastable things are arrays, hashes and scalars, rather than integers, floats and doubles. Despite their reputations, C is much more weakly typed than Perl, it's just that neither language likes to admit it).

Scalar data, as you've already seen, is $ingular data. Scalar variables always start with a $ for $calar, and can contain one of pretty much anything. $name could contain an integer (2), a floating point number (2.345453e-65), a character ("P") or a string ("Or Pretty much @nything el$e"). They can even contain pointers to other sorts of data (which are called references, but we're getting ahead of ourselves). To create a scalar variable, just write:

$string = "Some string or other";
$number = 12453;

You don't need to quote numbers, and in fact shouldn't, for reasons that will become clear when we discuss comparing bits of data to each other later.

In contrast to scalar data, array data is plur@l data. Array variables start with an @ for @rray, and store a list of the same things valid as scalar variables. So creating an array could look like any of the following:

@numbers = ( 1, 3.05, 4, 2e-10, 23 );
@strings = ( "hello", 'everybody', "I'm Dr. Nick Riviera\n", $number );
@allsorts = ( 12.5, 'plop', "some tabs\t\t\t\t", $chocolate, 56, "C" );

When you create an array, you need to put the (suitably quoted, scalar) values in a list between ( ) parentheses, separated by commas, i.e. arrays are created like this:

@array = ( $scalar1, $scalar2, $scalar3 );

Note you can dump the values of scalar variables into arrays (like $number), as well as [suitably quoted] strings, and [preferably unquoted] numbers.

Now, let's see how to access the individual members of an array, imaginatively called @array. To access the members of an array, we need to use [ ] brackets. The syntax is:

#!/usr/bin/perl
use warnings;
@array = ( 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22 );
$the_9th_member_of_the_array = $array[8];
print $the_9th_member_of_the_array;

And $the_9th_member_of_the_array will print out '16'. There are two gotchas here. Firstly, what has happened to the @ of @array? And secondly, why 8, not 9? Well, firstly, the $ and @ 'sigils' aren't really part of the name of the variable. They are more a way of telling perl whether the thing you're talking about is a single thing or a list of things. When you create an array, you use a @ sign, because you want perl to put a list into it. However, when you want to access an individual member of an array, you're trying to get a $ingular piece of data, a $calar, so this gets an $. This syntax is a little weird, and is due to change in Perl 6, but for the moment, you're stuck with it: when you're talking about a list of data, you need a @, as in @array = ( blah... ); but to access a single bit of array data, you need to use a $, as in $array[index-number]; Which brings me to the second point. Why 8? In Perl, arrays index from the number 0, so the 9th element in an array is $array[8]. If you just put your brain into perl/C gear and think of the 1st element of an array as being the 'zeroeth', 0th, member, you may find this easier. So:

#!/usr/bin/perl
use warnings;
@beans = ( "adzuki", "haricot", "mung" );
    # anything following a '#' is a comment and perl will ignore it
    # perl will ignore stuff from a '#' to the end of the line
print "$beans[0]\n"; # this is adzuki,
print "$beans[1]\n"; # this is haricot,
print "$beans[2]\n"; # this is mung.
print "$beans[-1]\n"; # this is also mung.
adzuki
haricot
mung
mung

[Note the comments: anything following a # character is ignored by perl as a helpful hint to the human reader]. Helpfully, negative indices are counted back from the end of the array. Another useful way to access pieces of arrays is to take slices of them:

#!/usr/bin/perl
use warnings;
    # Have you noticed the subtle change yet? 
    # use warnings; is much better than -w, so use it
@cake = ( "flour", "eggs", "milk", "sugar", "butter", "sultanas", "water" );
@slice_of_cake = @cake[ 3, 6 ];
print "@slice_of_cake\n";
sugar water

@slice_of_cake will contain the list ( "sugar", "water" ). Note that the slice syntax @slice_of_cake needs a @, because you are creating a list. Likewise, @cake also gets a @, because you're creating plur@l data, not a $ingle piece of data. Slices are useful for getting at multiple bits of data simultaneously, without tediously having to write single accesses for each bit. You can also assign things to a slice:

#!/usr/bin/perl
use warnings;
@array = ( "hello", "everybody", "I'm", "Dr.", "Nick", "Riviera" );
print "@array\n";
@array[ 3, 4, 5 ] = ( "a", "complete", "charlatan" );
print "@array\n";

You can see from the previous few scripts that, like scalar variables, arrays will also interpolate their values when put in between double quotes. Furthermore, perl will helpfully pad the items in the array with spaces too. By the way, if you think I'm being horribly inconsistent with capital letters here, Perl is the language, and perl is the interpreter, so I'm not ☺

OK, enough about simple arrays for the moment. Perl actually has two sorts of array. Simple arrays like those we've just discussed are simply called arrays. The second sort of array is called an associative array, or hash (they're very similar to dictionaries, if you're a Python programmer). Hashes are created with a % for %we_ran_out_of_sensible_symbols, and contain pairs of data (ah, maybe it was for the two blobs, in a % sign) called keys and values. Here are some typical hash creations:

%hash = ( key1 => 'value1', key2 => 'value2', key3 => 'value3' );
%dictionary =
(
    aardvark  => "first",
    name      => "Steve",
    age       => 25,
    zebedee   => "character in magic roundabout",
);

The syntax is nearly the same as for normal arrays: the only difference is the =>. => is just a posh sort of comma, sometimes called the fat comma, and in fact, if you replaced the => with a real comma, and put aardvark, Steve, age and zebedee in quotes, it would still work. Hashes are simply created from lists, and they're not fussy about their commas. However, => has two advantages: it makes the fact you're creating pairs of data more explicit, and it also means you don't have to quote the string that forms the key (perl will do this automagically for you): note it's aardvark, not 'aardvark'.

The first member of each pair in a hash is called the key, and the second is called the value. To access the individual members of a hash, you use a similar syntax to accessing array members, but rather than [INDEX] brackets, you use {KEY} braces:

$value = $hash{ 'key' };

So:

#!/usr/bin/perl
use warnings;
%fruit_trees = ( apple => "Malus", pear => "Pyrus", plum => "Prunus" );
$latin_name_of_apple = $fruit_trees{ 'apple' };
    # $latin_name_of_apple contains the value associated with
    # the key 'apple', i.e. 'Malus'
print $latin_name_of_apple;

Again, like the funny syntax for normal arrays, you need a $, because you're accessing $ingle bits of data from the hash. Hashes are stupendously useful, since it is far easier to use a hash than an array in a situation like:

$personal_details{ 'name' };

since if you used an array:

$personal_details[ 2 ];

you'd have to remember whatever arbitrary index you stored that the person's name at (2 here). Far easier to use a hash, and just ask for what you want with a key. As with arrays, you can also take slices of hashes, but the syntax may make you do a double take:

#!/usr/bin/perl
use warnings;
%trees =
(
    apple =>  "Malus",
    pear  =>  "Pyrus",
    plum  =>  "Prunus",
    oak   =>  "Quercus",
    ash   =>  "Fraxinus",
    yew   =>  "Taxus",
);
@latin_names_of_fruit_trees 
    = @trees{ 'apple', 'pear', 'plum' }; # hash slice
print "@latin_names_of_fruit_trees\n";

What's with the @ for the slice syntax??? Remember that $, @ and % aren't really part of the name of a variable, they are ways of accessing and creating data of a specific type. When we take a slice of a hash, we are accessing a list of values, just as when we are slicing an array, so we need a @. [If it's any consolation, I think this is bloody stupid too! It'll be fixed in Perl 6]. Note the pretty arrangement of the tree hash: Perl is largely whitespace-insensitive, so you can get away with writing your code in largely whatever creative way you want. (This useful ability is due in part to the compulsory, and to some annoying, semicolon at the end of statements: you pays your money, you takes your choice).

So, to summarise. Perl has three fundamental data types, scalars, arrays and hashes. When creating them, you'll need to use $, @ and % respectively. When accessing them, you'll need to use $ to access $ingle bits of data, and @ to access plur@l slices of data, with the appropriate parentheses: [INDEX] for arrays, {KEY} for hashes.

Loopy

Now, let's get into some proper Perl. This is a decent size lump of Perl, but may be less boring than reading through a thousand incremental programs showing you tiny bits at a time. Perl has a shallow learning curve, so I'll assume you're not stupid, and we'll launch straight into something slightly more juicy:

#!/usr/bin/perl
use warnings;
print "What is your name?\n";
$name = <STDIN>;
chomp $name;
@beans = ( "adzuki", "haricot", "mung" );
print( "\@beans contains ", scalar @beans, " members, @beans\n" );
for ( $i = 0; $i < scalar @beans; $i++ )
{
    print "$name likes $beans[$i] beans.\n";
}
@beans contains 3 members, adzuki haricot mung
Steve likes adzuki beans.
Steve likes haricot beans.
Steve likes mung beans.

Don't get scared by the line-noise (i.e. all the punctuation): if you do, regular expressions will likely be fatal. The very beginning should be quite obvious now:

print "What is your name?\n";
$name = <STDIN>;
chomp $name;

means something like, "read in someone's name from a prompt, get rid of the trailing newline from the input, and shove this in $name." Easy.

@beans = ( "adzuki", "haricot", "mung" );

means 'create a list of the strings adzuki, haricot and mung, and store it in array @beans'. Still easy. By the way, @beans and $beans would be completely different variables: mucking about with one would have no effect on the other. The next line prints out some stuff about the beans:

print( "\@beans contains ", scalar @beans, " members, @beans\n" );

You may have some difficulty with exactly what is going on here, but all we're doing is feeding print a list of three items:

print( "a string", something to do with @beans, "another string" );

Let's consider the three items in the list separately:

"\@beans contains "

is responsible for the bit of the output that looks like

@beans contains

You need to escape (use a \ on) the @ of @beans. As I said earlier, if you put a perl variable into a double-quoted string, perl will replace the variable name with the actual contents of that variable. So, if you don't escape the @, perl will interpolate the entire contents of @beans ('adzuki haricot mung') into what it's going to print, a fact that we'll take advantage of in a minute. With the \, perl just prints a literal @ symbol instead, followed by the word 'beans'. So, \$ and \@ are two more escape characters like \" and \n, which double quotes will interpolate for us.

Now, print is a list operator, that is, it will print out any stuff you put in a list after it. In just the same way as array variables, a list is some stuff between ( ) parentheses, separated by commas, so the stuff we're feeding print is a list (just look at the code), and the next item is:

scalar @beans

Now, perl is a helpfully (well, usually) context sensitive language. Unsurprisingly, the two main contexts perl recognises are scalar (singular) context, and list (plural) context, which you've already met in passing when we discussed array and hash access and slicing. print forces list context on the things you give it. So, if you simply put this:

@beans

you'd get a mess, because the usual behaviour of an array in list context is to interpolate all its members. perl would squadge the contents of @beans ("adzukiharicotmung") into the output, not even padding it with spaces like it does between double quotes. That's not what we're after here. What we actually want is the number of items in the array. In scalar context, an array will return the number of members it contains, which is just what we want. Scalar context can be forced using the scalar operator, hence the upshot of:

scalar @beans

is to give the size of the array, rather than its contents, to print, which it duly does:

3

List and scalar context is one of Perl's more esoteric, but more useful features, and we'll come across more as we go along. For now, remember that if you assign stuff to an array:

@things = ( "wobble", 2, "kaboom");

or use an operator that expects a list, like print...

print( "wobble", 2, "kaboom");

the arguments (wobble, and so on) will be interpreted in list context unless you explicitly use the scalar keyword. Many perl functions, and some sorts of variable, will return different values in scalar or list context. Most importantly for the present moment, an array will be interpreted as a list of its members in list context, but will be interpreted as the number of its members in scalar context.

Hence:

#!/usr/bin/perl
use warnings;
@things = ( "wobble", 2, "kaboom");
print @things, "\n";
    # print forces list context on what it's given
$number = @things;
    # $number forces scalar context so perl assigns the size of
    # array @things to $number
print $number;
print scalar @things;
    # scalar also forces scalar context, overriding print's
    # preference for lists
wobble2kaboom
3
3

Finally, the last item given to print in our original program is:

" members, @beans\n"

which is responsible for the output of

members, adzuki haricot mung

As I said earlier, if you put the name of an array into double quotes, perl will interpolate the contents of the array into the string. Even more than this, perl also helpfully pads the members with spaces, hence the output of:

adzuki haricot mung

rather than:

adzukiharicotmung

The very last bit of the code:

for ( $i = 0; $i < scalar @beans; $i++ )
{
    print "$name likes $beans[$i] beans.\n";
}

is a for loop. for loops take a bit of explanation, and mercifully, Perl has a cute shortcut for loops, which we'll investigate in a minute. But first, let's learn it the hard, C-style way, which is occasionally useful. A for loop, as you may know/have guessed, looks like:

for ( LOOP_VAR = START_VALUE; TEST_LOOP_VAR; INCREMENT_LOOP_VAR )
{
    DO_SOMETHING;
}

The ( ) and { } are required, but you can write this with K&R style bracing:

for ( LOOP_VAR = START_VALUE; TEST_LOOP_VAR; INCREMENT_LOOP_VAR ) {
    DO_SOMETHING;
}

or with hideous style bracing like this:

for 
( LOOP_VAR = START_VALUE; TEST_LOOP_VAR; INCREMENT_LOOP_VAR ) 
{ DO_SOMETHING; }

if you'd rather, whatever looks best to you: Perl is largely space and newline insensitive as mentioned above. It's fairly obvious from the output that the loop in the program prints:

Steve likes XXXXX beans.

for each member of @beans. How exactly does it do this? First it sets the loop variable, $i, to the start value of 0. Then it tests the variable to see if it's less than the scalar size of @beans (which is 3). On each passage of the loop, it does the INCREMENT_LOOP_VARIABLE thing: $i++ means 'add 1 to $i'. So the upshot of all this is that $i is just a counter that runs from 0 to 2 (it will actually get to 3, but the loop will immediately terminate at this point, as 3 is not < 3). Hopefully the for loop should now be crystal clear. Hence:

for ( $i = 0; $i < scalar @beans; $i++ )
{
    print "$name likes $beans[$i] beans.\n";
}

means:

for
(
    set $i to 0;
    keep looping while $i is less than 3;
    increment $i by 1 on each pass of the loop
)
{
    print out Steve likes the $i'th member of @beans
}

The increment operator, ++ , can be used in two ways: you can either write:

$i++

or

++$i

In this particular case, it doesn't matter which you use, but in fact $i++ increments $i after returning it (post-increment), whereas ++$i increments it before returning it (pre-increment). So:

#!/usr/bin/perl
use warnings;
$i = 1;
print "At the start, \$i is $i.\n";
print "\$i still returns ", $i++, 
    " when you post-increment it, but its value is now $i\n";
$i = 1;
print 
   "But if you pre-increment it, \$i's value will be immediately changed to ",
   ++$i,
   ".\n";
At the start, $i is 1
$i still returns 1 when you post-increment it, but its value is now 2.
But if you pre-increment it, $i's value will be immediately changed to 2.

Note the escaped (backslashed) $ on some of the $i's. You already know you need to escape a @ in a double-quoted string to print a literal @ character, or perl will try to interpolate the value(s) of a variable. The exact same thing applies to $. There's no reason why you shouldn't write

$i++;

as

$i = $i + 1;

but the former is much more concise. You'll never guess what --$i and $i-- do. You can't? Well, there is more than one way to decrement a variable (the perl motto is TIMTOWTDI: there is more than one way to do it):

--$i;

is shorthand for:

$i -= 1;

which itself is shorthand for:

$i = $i - 1;

The middle version is something which you may find useful. The -= subtraction assignment operator is one of a whole class of similar operators, like += (so $i++ is short for $i += 1 which is itself short for $i = $i + 1): Perl has all the usual mathematical operators, like +, -, *, /, % (modulus), and ** (raise-to-the-power-of), and any of these may be used like -= or += too, so:

$a = $a ** 2;
# square $a and bung the result back into $a

is the same as:

$a **= 2;

One operator lacking in just about every other language is the x operator (that's just a little x character). Perl, being a very string-happy language will 'multiply' strings:

#!/usr/bin/perl
use warnings;
$string = "hello";
$three_copies_of_string = $string x 3;
print $three_copies_of_string;
hellohellohello

You can of course also use the x in a x= construction too:

#!/usr/bin/perl
use warnings;
$string = "hello";
$string x= 3; # put "hellohellohello" into $string

One final useful operator is . which concatenates two strings together:

#!/usr/bin/perl
use warnings;
my $world = ", world\n";
my $cat   = "This is the concatenation operator in action.";
my $msg   = "hello" . $world . $cat . "\n";
print $msg;
hello, world
This is the concatenation operator in action.

Prettier Perl

Now, the original code we were studying is very ugly, and Perl makes writing short, saccharine code easy. It also makes writing shoddy, mucky code easy too, but we'll have none of that, thank you very much. A much more attractive way of writing ,the script above is:

#!/usr/bin/perl
use warnings;
print "What is your name?";
chomp( $name = <STDIN> );
@beans = qw( adzuki haricot mung );
print "\@beans contains ", scalar @beans, " members, @beans\n";
foreach ( @beans )
{
    print "$name likes $_ beans.\n";
}

Much tidier, and probably more readable even without explanation. There are a few new things though. The assignment of <STDIN> ("Steve\n" or whatever) to $name actually returns the variable $name, which is exactly what chomp needs to work on. So the two lines can be combined.

$name = <STDIN>;
chomp $name;

is exactly the same as:

chomp( $name = <STDIN> );

This is a typical bit of idiomatic perl.

The qw( ) is a simpler way of making a list of variables. It stands for 'quote words'. To save you the effort of all those:

('X', 'Y', 'Z');

quotes and commas, you can just write:

qw(X Y Z);

which is much easier on the eye, although of course, it's unsuitable if any of X, Y or Z contain spaces. You can mix and match quoting systems, so:

@bits = ( "hello, sailor", "1", "mung", "adzuki", "haricot", 
    "dal\n", "\t", $thing );

could also be written:

@bits = ( 'hello, sailor', 1, qw( mung adzuki haricot ), 
    "dal\n", "\t", $thing );

1 is a number, not a string, so it doesn't need quotes, and I've only used double quotes for things that really need them (strings with escapes like \t in them). Written like this, it's not really any more readable, but it gives you the idea. Incidentally, it doesn't matter which (non-alphanumeric) character you use around a qw list:

qw(X Y Z);
qw{X Y Z};
qw/X Y Z/;
qw[X Y Z];
qw^X Y Z^;

are all equivalent: as long as you use the same character, or pairs of naturally paired characters like ( ), [ ] and { }. (I'd avoid anything but parentheses and braces though, unless you're deliberately trying to make your code unreadable. Perl also has the quote operators qq( ) and q( ), which are equivalent to " " and ' ' ' respectively, but you get to chose your own quote characters, which can be useful if your string contains lots of some character you'd rather not have to keep escaping. Hence:

q(Exploding 'chocolate' cake and an awful 'lot' of 'quotes');

and..

'Exploding \'chocolate\' cake and an awful \'lot\' of '\quotes\'';

are equivalent, but the first doesn't make your eyes bleed. I'd avoid qq' ' and q" " if I were you though, or your brain will bleed. Also remember that if you need to include the quote character itself in a string, whether you use conventional double quotes, or the qq( ) or q( ) operators, you'll have to escape it, just as you did with single quotes in single quoted strings:

"This is "wrong" ";
# because of the embedded, unescaped " characters
"This is \"OK\" ";
# properly escaped
qq!This is overexcited! and wrong! not to mention unreadbly awful!;
# because the second and third !s are unescaped
qq!This is OK\! though!;
# properly escaped !

Please don't even think of using exclamation marks as delimiters: it's cute until the maintainer of your code has you killed.

qq{This uses a choice of "delimiter" that's (very) well chosen}; 

The next bit of the shortened code:

print "\@beans contains ", scalar @beans, " members, @beans\n";

is virtually the same as before, but you'll note that perl list operators like print don't really need the ( ) parentheses, although feel free to leave them in if it prevents ambiguity. Some languages distinguish between functions (which need parentheses) and operators, which don't. In Perl they're by and large the same thing, and parentheses are only required for creating lists, or for mathematical (precedence) reasons: 2+(8*3) is different to (2+8)*3.

The for loop is mercifully replaced with something much, much tidier:

foreach ( @beans )
{
    print "$name likes $_ beans.\n";
}

Which is hugely more intuitive than the ghastly C-style for(;;){} loop, and it runs quicker too. The only difficult thing here is the infamous perl $_ variable. $_ is the 'default' variable. It is automagically set, and automagically assumed by many Perl functions. A more explicit way of writing this loop is:

foreach $bean ( @beans ) { print "$name likes $bean beans.\n" }

The

foreach $bean ( @beans )

means 'set $bean to the value of each member of @beans in turn'. If you don't supply a loop variable (here, $bean), perl will conveniently assume $_ for you. So far so good I hope. Well be seeing a lot more of $_ as we go on.

You may be wondering what characters you can get away with in the name of a Perl variable: basically, they should start with a letter (either case), and thereafter can contain any of A to Z, a to z, 0 to 9 and the underscore _. However, Perl is also liberally sprinkled with 'punctuation variables', which you will learn as you go along. Rather than starting '$letter', they start '$punctuation', like $_ , $! , $@ and $/, to name four of the most useful ones (and probably the only ones you will actually ever need). These variables are special to Perl, and are often set or assumed by certain Perl functions. Earlier you learnt that chomp will remove newlines from Perl variables. This is actually a fib: it will remove whatever is in $/ from the end of the string if it's present, it just happens that $/ (the 'input record separator') is set to \n when perl starts:

#!/usr/bin/perl
use warnings;
$string = "hello:";
chomp $string;
print "$string\n";
    # chomp does nothing, as $/ is \n and $string doesn't end in \n
$/ = ":";
chomp $string;
print "$string\n";
    # chomp will now remove : from the end of strings, which it duly does
hello:
hello

Of these punctuation variables, $_ is particularly infamous: the following do the same thing:

foreach $bean ( @beans ) { print $bean; }
foreach ( @beans ) { print; }

perl assumes $_ as the loop variable in the foreach, and also assumes $_ if no other arguments are given to print. Some criticise Perl for having the 'invisible thread' of $_ running through them, but there's nothing to stop you being more explicit if you want.

Back to the program. There are a few more shortcuts that are instructive, if we ignore the middle bit:

#!/usr/bin/perl
use warnings;
print "What is your name?";
chomp( $name = <STDIN> );
@beans = qw( adzuki haricot mung );
foreach ( @beans )
{
    print "$name likes $_ beans.\n";
}

can also be written:

#!/usr/bin/perl
use warnings;
print "What is your name?";
chomp( $name = <STDIN> );
@beans = qw( adzuki haricot mung );
print "$name likes $_ beans.\n" foreach @beans;

For simple, single statements like the last one, you can append the loopy bit and avoid all those braces in this pleasantly readable style. Beware using this on long lines though, as the loop (statement modifier) at the end can get lost. You should always have a care for the future readers of your code: well written Perl can read like English if you're careful, which makes understanding it much easier (providing you're fluent in English). Perl gives you 'more than one way to do it'. That doesn't mean you should chose the first appaling way that comes into your head! However, if you want serious brevity:

#!/usr/bin/perl
use warnings;
print "What is your name?";
chomp( my $name = <STDIN> );
print "$name likes $_ beans.\n" foreach qw( adzuki haricot mung );

There is little distinction in Perl between a list and a bona fide array, so if you just put a list where perl expects a real array, it'll generally still do what you mean (DWIM, do what I mean).

Summary

So, to sum up (and there's quite a bit!). Perl has three types of data: scalars, arrays and hashes. To create them, use $, @ and %, and to access them use $ for single bits, @ for slices, and use the appropriate brackets: [INDEX] for arrays and {KEY} for hashes. Remember that arrays interpolate in double quotes (and are space padded), so to print a literal @, you'll need a \@ (the same applies to $).

Perl is a context sensitive language, and some functions and variables return different values in list and scalar context. In particular, arrays will interpolate their (unpadded) members in list context, or their size in scalar context. Some operators (like print) assume list context, and to force scalar context, you'll need to use the scalar function

Perl provides an infinitude of quoting mechanisms: qw(), qq(), q(), " " and ' ', the qq() and q() operators allow you to choose your own quotes to avoid escaping lots of " or '. qw() allows you to create a comma separated list of quoted variables without having to use quotes or commas!

To loop over an array, you can use a for loop (yuk), or a foreach loop, with or without an assumed $_ for the current item from the array. And finally, don't forget that all computer languages are glorified maths: Perl has all the usual maths operators, various shorthands like /= and ++, and its own weird little 'repetition' operator x.

Test yourself

See if you can write a script that does the following:

#!/usr/bin/perl
use warnings;
@os = qw{ Linux Windows MacOS MacOSX OS/2 DOS Irix Solaris BSD Amiga };
print "Which OS do you use?\n";
chomp( $user_os = <STDIN> );
print "You have a $user_os, but I know about all these operating systems...\n";
print "\t$_\n" for @os;
print "I can also write the first ten terms of the seventeen times table\n";
for ( $i = 1; $i <= 10; $i ++ ) # less than or equal to 10
{
    print "$i times 17 is ", $i * 17, "\n";
}

Next…