SCALARs and strings · Lists

reverse#

Reverse a list — or, in scalar context, reverse the characters of a string.

reverse is two operators wearing the same name. Context decides which one you get. In list context it returns LIST with its elements in the opposite order; element values are untouched. In scalar context it concatenates LIST into a single string and returns that string with its characters reversed. The common mistake of writing my $s = reverse $str and expecting a reversed list (or writing print reverse $str and expecting a reversed string) is the single biggest trap this function has — see Edge cases.

Synopsis#

my @r    = reverse @arr          # list context: elements reversed
my $s    = reverse $str          # scalar context: characters reversed
my %inv  = reverse %h            # hash invert (value → key)
reverse                          # in scalar context, reverses $_

What you get back#

Context-dependent. The operator inspects the context of its caller and branches:

  • List context → a new list with the elements of LIST in reverse order. Element values are not stringified, not modified, not copied at the character level. A list of refs stays a list of the same refs.

  • Scalar context → a single string: the concatenation of the stringified elements of LIST, with all characters in reverse order. Under use utf8 / wide strings, reversal is character-wise, not byte-wise.

This means the same call site returns radically different shapes depending on how you use it:

my @back  = reverse "abc", "def";    # ("def", "abc")
my $back  = reverse "abc", "def";    # "fedcba"

Used with no arguments in scalar context, reverse reverses $_. Used with no arguments in list context, reverse returns the empty list — not a reversed $_. print reverse; produces no output.

Global state it touches#

Reads $_ when called with no arguments in scalar context. That is the only global it touches. It does not modify $_; it returns the reversed string.

Examples#

Reverse a list. The elements themselves are unchanged:

my @a = (1, 2, 3, 4, 5);
my @r = reverse @a;              # (5, 4, 3, 2, 1)

Reverse a string. Force scalar context with scalar when the surrounding expression would otherwise be list:

my $s = reverse "Hello, world";  # "dlrow ,olleH"
print scalar reverse "Hello";    # "olleH"

Iterate an array backward without building a second array. reverse in the loop header is a list-context call; Perl consumes the reversed list lazily from the loop machinery:

my @stack = ("first", "second", "third");
for my $elem (reverse @stack) {
    print "$elem\n";             # third / second / first
}

Descending sort. reverse sort is the idiom when your comparison is ascending and you want the opposite. For anything more complex than default string compare, swap the operands in the comparator instead:

my @asc  = sort { $a <=> $b } @nums;
my @desc = reverse sort { $a <=> $b } @nums;     # works
my @desc2 = sort { $b <=> $a } @nums;            # preferred

Invert a hash. Values become keys, keys become values:

my %by_name    = (alice => 1, bob => 2, carol => 3);
my %by_id      = reverse %by_name;               # (1 => "alice", ...)
print $by_id{2};                                 # "bob"

The "dlrow ,olleH" trick — using reverse in scalar context as a one-shot character flip on a string variable:

my $word = "stressed";
my $rev  = scalar reverse $word;                  # "desserts"

Edge cases#

  • The #1 trap: context. my $s = reverse @arr does not give you a reversed array; it gives you the reversed string formed by concatenating the array’s elements and flipping every character. If you want a reversed array stored via a scalar, use a reference: my $ref = [ reverse @arr ].

  • Single scalar, wrong context. my @r = reverse $str returns ($str) — a one-element list containing $str unchanged. There is nothing to reorder. To reverse the characters, force scalar context: my $r = reverse $str or my @r = (scalar reverse $str).

  • Hash invert loses data on duplicate values. reverse %h walks the key/value pairs as a flat list and rebuilds a hash. If two keys share a value, one of them wins and the other is silently dropped; which one wins is not defined. Check for uniqueness first if it matters:

    my %seen;
    $seen{$_}++ for values %h;
    die "non-unique values" if grep { $_ > 1 } values %seen;
    my %inv = reverse %h;
    
  • No arguments in list context does nothing useful. reverse with no args returns () in list context. $_ is only consulted in scalar context. print reverse; prints nothing; print scalar reverse; prints the reverse of $_.

  • Character-wise, not byte-wise. For wide-character strings, reverse reverses characters, not bytes. A :utf8 string of three code points stays three code points after reversal, regardless of their byte widths. Reversing a raw byte string with multi-byte characters you never decoded will corrupt it — decode first.

  • Self-assignment preserves holes. @a = reverse @a on a non-magical or well-behaved tied array preserves non-existent elements in their reversed positions; a sparse array stays sparse.

  • reverse sort is not the same as sort { $b cmp $a }. Both give descending order for a stable default compare, but reverse sort does two passes over the data and is measurably slower on large lists. Prefer swapping the comparator operands.

Differences from upstream#

Fully compatible with upstream Perl 5.42.

See also#

  • sort — pair with reverse for descending order, or swap $a/$b in the comparator to avoid the second pass

  • pop — remove from the end of an array when you just want the last element, not the whole list reversed

  • shift — remove from the front; combined with a reversed copy you get stack-like access to the original tail

  • split — produce a list of characters (with //) or fields that you can then reverse

  • join — the natural partner when you reverse a list of strings and want a single string back

  • $_ — the default target when reverse is called with no arguments in scalar context