100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
Programming

Scalars, Arrays, and Hashes

A guide to Perl's three core data types, how their sigils work, and the everyday operations for each one.

FoundationsBeginner10 min readJul 10, 2026
Analogies

Scalars, Arrays, and Hashes

Perl has exactly three built-in data structure types, and it tells them apart with a sigil, a leading punctuation character on every variable name: a dollar sign $ marks a scalar, which holds a single value such as a number, string, or reference; an at sign @ marks an array, an ordered, indexed list of scalars; and a percent sign % marks a hash, an unordered collection of key-value pairs. Crucially, the sigil describes how many values you are accessing right now rather than the variable's declared type, so @fruits refers to the whole array but $fruits[0] refers to a single scalar element pulled out of that same array, and this consistent rule is one of the first things that trips up newcomers coming from languages with a single, uniform indexing syntax.

🏏

Cricket analogy: Similar to how a scoreboard shows a single current total (a scalar) alongside the full over-by-over list of runs (an array), Perl's $ and @ sigils tell you whether you're looking at one value or the whole list.

Scalars

A scalar variable, declared with my $name = 'Alice';, holds exactly one piece of data at a time, and Perl does not require you to declare whether that data is a number or a string; the same scalar can hold 42, 'hello', a floating-point number like 3.14, or even a reference to an array or hash. Perl automatically converts between numbers and strings depending on context, so my $count = '5' + 3; yields 8 because the + operator forces numeric context, while my $greeting = 'Item ' . 5; yields the string 'Item 5' because the . concatenation operator forces string context; this implicit conversion is powerful but is also why use warnings; is valuable, since it will flag things like adding a non-numeric string to a number.

🏏

Cricket analogy: Similar to how a single stat, a batter's current strike rate, can be read either as a plain number for a ranking table or embedded into a sentence for commentary, a Perl scalar like $runs shifts between numeric and string context automatically.

Arrays

An array, declared as my @colors = ('red', 'green', 'blue');, is a zero-indexed ordered list, so $colors[0] is 'red' and $colors[-1] conveniently returns the last element, 'blue', without needing to know the array's length. Arrays grow and shrink dynamically: push @colors, 'yellow'; appends an element, pop @colors; removes and returns the last one, and scalar @colors (or simply using @colors in a place that expects a number) tells you how many elements it holds. A common beginner mistake is writing $colors instead of $colors[0] when trying to grab the first element, since Perl will not automatically assume you meant the first element; $colors alone actually refers to a completely separate, unrelated scalar variable in Perl's namespace.

🏏

Cricket analogy: Similar to a batting order being a numbered list where slot 0 is the opener and the last slot is the number 11 batter, a Perl array is zero-indexed so $order[0] is the opener and $order[-1] is the last batter without counting manually.

Hashes

A hash, declared as my %ages = (Alice => 30, Bob => 25);, stores unordered key-value pairs where every key is a unique string and every value is a scalar, so $ages{Alice} retrieves 30 using curly braces rather than the square brackets used for arrays. The keys %ages function returns a list of all the keys, values %ages returns a list of all the values in the same corresponding order, and exists $ages{Carol} lets you safely check whether a key is present before accessing it, which avoids the subtle bug of auto-vivifying a new key with an undef value just by testing if ($ages{Carol}). Because hashes have no guaranteed order, code that needs a predictable iteration order should explicitly sort the keys, for example for my $name (sort keys %ages) { ... }, rather than relying on the order keys happen to come back in.

🏏

Cricket analogy: Similar to a scorecard mapping each player's name to their runs scored, where you look up 'Kohli' directly rather than searching a numbered list, a Perl hash $scores{Kohli} retrieves a value by name key instead of by position.

perl
use strict;
use warnings;

# Scalar
my $name = 'Alice';

# Array
my @colors = ('red', 'green', 'blue');
push @colors, 'yellow';
print "First: $colors[0], Last: $colors[-1], Count: " . scalar(@colors) . "\n";

# Hash
my %ages = (Alice => 30, Bob => 25);
$ages{Carol} = 28;

for my $person (sort keys %ages) {
    print "$person is $ages{$person} years old\n";
}

A handy mnemonic: the sigil always matches what you're pulling OUT, not what you started with. @colors is a whole array, but $colors[0] (one element) and $#colors (the last index number) both use $ because each expression yields a single scalar value.

  • Perl has three core data types, distinguished by sigil: scalar ($), array (@), and hash (%).
  • A scalar holds one value at a time and Perl converts freely between numeric and string context based on the operator used.
  • Arrays are zero-indexed ordered lists; $array[-1] conveniently accesses the last element without checking the length first.
  • push, pop, shift, and unshift are the standard functions for adding and removing elements from either end of an array.
  • Hashes store unordered key-value pairs, accessed with curly braces like $hash{key}, unlike the square brackets used for arrays.
  • keys %hash and values %hash return corresponding lists; exists safely checks for a key without creating it.
  • Since hash order is not guaranteed, use sort keys %hash when you need predictable iteration order.

Practice what you learned

Was this page helpful?

Topics covered

#Programming#PerlStudyNotes#ScalarsArraysAndHashes#Scalars#Arrays#Hashes#DataStructures#StudyNotes#SkillVeris#ExamPrep