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.
#!/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:
- Create an array containing the names of common operating systems. Prompt the user for the name of their OS. Print out "You have a blah, but I know about all these operating systems", and list the OSes. Print out "I can also write the first ten terms of the seventeen times table". Do this.
#!/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";
}
