Замкнення (closure) - це анонімна підпограма, згенерована під час виконання, що пам'ятає про лексичний контекст, в якому вона була задана. Це визначення може видатися дещо незрозумілим, тому для початку розгляньмо простенький приклад, де показано, як приватні змінні можуть зберігати свої значення при виході з контексту, де вони були задані:

my $scalarref;
{
    my $private = 33;
    $scalarref = \$private;
}
print $$scalarref; # 33

Виконання цього коду виведе "33". Що ж тут відбувається? Змінна $private задана всередині анонімного блоку. Звичайно при виході з блоку, що визначає лексичний контекст певної змінної, вона відразу ж потрапляє до смітника. Якщо ж створити посилання на цю змінну, то її величину можна отримати і змінити у зовнішньому контексті завдяки посиланню на неї.

Посилатися на приватні змінні можливо і за допомогою підпрограм:

my $count; # глобальна змінна
{
    my $count = 0; # змінна, видима всередині блоку
    sub counter { ++$count }
}
print &counter, "\n" for (1..3); # 1, 2, 3
$count = 10;
print &counter, "\n"; # 4

З цього прикладу видно, що підпрограма counter утримує інформацію про свій початковий контекст: вона використовує приватну змінну $count, недоступну в глобальному контексті, створюючи ефект "статичної" змінної (за термінологією C/C++). Такі змінні можуть поділятися і між кількома функціями одночасно:

{
    my $count = 0;
    sub increment { ++$count }
    sub decrement { --$count }
    sub reset { $count = 0 }
}

Тепер ми підійшли впритул до замкнень:

sub foo {
    my $x = shift;
    return sub {
        my $y = shift;
        return $x * $y;
    }
}
my $closure = &foo(10);
print $closure->(3); # 30

Підпрограма foo отримує один аргумент і повертає аномімну функцію, яка має доступ до приватних змінних підпрограми, що її згенерувала (foo). Посилання на новоутворене замкнення зберігається в змінній $closure, а виконання самого замкнення викликається за допомогою реферативного оператора ->, за яким розташовуються дужки.

Замкнення можуть також вкладатися одне в одне:

sub foo {
   my $x1 = shift;
   return sub {
       my $x2 = shift;
       return sub {
           my $x3 = shift;
           return $x1 * $x2 * $x3;
       }
   }
}

my $cl1 = foo(10);
my $cl2 = $cl1->(2);
print $cl2->(3); # 60

Тут виклик функції foo повертає замкнення, а виклик цього замкнення у свою чергу повертає інше.

Коли ж потрібні замкнення? Насамперед тоді, коли треба створити функцію, що пам'ятає про свій початковий стан, але вам не хочеться створювати новий об'єкт (адже задання замкнення є більш компактним). Особливо ж вони корисні тоді, коли вам потрібно задати кілька подібних функцій з різним початковим станом:

# масив кольорів:
my @colors = qw(red blue navy purple pink);

# функція, що отримує назву кольору як арґумент
# і повертає замкнення,
# котре генерує відповідну html-мітку:
sub colorize {
    my $color = shift;
    return sub {
        my $text = shift;
        return qq|<span style="color: $color">$text</span>|;
    }
}

# задаємо асоціативний масив, ключами якого є 
# назви кольорів, а величинами відповідні замкнення:
my %colors = map { $_ => &colorize($_) } @colors;

# випадковий колір:
my $color = $colors[rand(@colors)];

# виведення повідомлення:
print "Today my world is ", $colors{$color}->($color);

Можливий вивід:

Today my world is <span style="color: blue">blue</span>