I once wrote one of these before for @NegativeMjark but I think I lost it. So here's another.
All you need to know is:
-
$foo
is a scalar (i.e. a single dimensional variable) -
@foo
is an array.$foo[n]
is the element of an array. -
%foo
is a hash.$foo{'moo'}
aka$foo{moo}
is the value in the hash for key'foo'
. -
\
is the reference operator. it returns a scalar which points to the address of the variable (like&
in C). -
(1, 2, 3)
is a list. (an array is a variable which contains a list). -
[1, 2, 3]
(rarely:\(1,2,3)
) is a reference to a list - aka arrayref -
$foo->[n]
gives an element of an arrayref -
@$foo
aka@{$foo}
dereferences an arrayref back into an array -
(a=>1, b=>2) or ('a'=>1, 'b'=>2)
is a hash.
(technically, it's a list which you can assign to a hash to initialise it -=>
is a synonym for,
.%foo = ('a', 1, 'b', 2)
would do the same thing). -
{a=>1, b=>2} or {'a'=>1, 'b'=>2}
(rarely:\(a=>1, b=>2)
) is a reference to a hash - aka hashref. -
$foo->{'moo'}
aka$foo->{moo}
is an element of a hashref -
%$foo
aka%{$foo}
dereferences a hashref back into an hash -
$foo->{bar}->{quux}
or$foo->{bar}{quux}
lets you drill into a nested datastructure - likefoo.bar.quux
elsewhere. -
$foo->{bar}->[0]
or$foo->{$bar}[0]
also works. -
$foo->bar()
calls method bar on object$foo
. -
compare numbers with
<
,==
,>
,<=
.>=
,!=
,<=>
(lattermost is -1 if a<b, +1 if a>b, 0 if a==b) -
compare strings with
lt
,eq
,gt
,le
,ge
,ne
,cmp
-
you must always run with
use strict; use warnings;
. -
sub
declares a function. you typically don't declare a prototype of the arguments it takes, although you could specify a cryptic message signature made out of sigils, but nobody does. -
the arguments to the function are available in the
@_
array variable. -
so:
sub moo { my $bar = shift; }
is the equivalent tofunction moo(bar) {}
in JS. -
if you skip the argument for a given function, it typically operates on the 'topic' variable, which is
$_
or@_
. So in the example above,shift
is short forshift @_
. This is typically the default iterator variable if you don't specify one, e.g.foreach (@foo) { do something with $_ }
-
my
declares a local scope similar tolet
in JS. -
our
declares a global scope. -
every operand is evaluated in a context - typically either scalar or list. This lets functions behave differently when you assign to a list rather than a scalar; e.g.
my (@foo) = localtime
returns an array of the day, month, etc, whereasmy ($foo) = localtime
returns a unix epoch timestamp.- If it's ambiguous whether you wanted a list or a scalar, you use the
scalar
keyword to force it to be scalar, or, more rarely, assign through an empty list to force it to be a list (e.g.= () =
). - Usefully, the value of an array in a scalar context is its length. so:
@a = (1, 1, 1); $b = @a;
,$b
is 3 (as isscalar @a
).
- If it's ambiguous whether you wanted a list or a scalar, you use the
-
you can put conditionals after expressions as well as before them, in order to make the code read more like English:
if ($moo) { bar(); }
is often written asbar() if $moo;
.
-
unless
is a synonym forif not
, in order to make the code read more like English:foo() unless bar;
. -
hashes 'autovivify'. which means that
my $foo; $foo->{bar}{quux}{baz} = 1;
will do the right thing, rather than needing you to initialise each layer of the datastructure as an empty hash. It's great when it's what you wanted, but can blow your leg off. -
There are lots of archaic magic variables provided by the runtime, for getting at things like line separators, line buffering behaviour, unix user ID. Just use
perldoc perlvar
if you see something like$/
or$|
and have no idea what's going on. They all have sensible names too (like$INPUT_RECORD_SEPARATOR
and$OUTPUT_AUTOFLUSH
) if only people would ever use them. -
pretty much everything else you can find out via
perldoc -f whatever
.