--- name: sort signatures: - 'sort LIST' - 'sort BLOCK LIST' - 'sort SUBNAME LIST' since: 5.0 status: documented categories: ["Lists"] --- ```{index} single: sort; Perl built-in ``` *[Lists](../perlfunc-by-category)* # sort Sort a list, returning the sorted list. `sort` takes a list and returns a new list with the elements rearranged in order. With no comparator it uses standard string comparison. With a `BLOCK` or a `SUBNAME` you supply the comparison rule as a small function that is called for each pair of elements and must return a negative, zero, or positive value the way `cmp` and `<=>` do. Sorting is stable — elements that compare equal keep their original relative order. The algorithm is mergesort. ## Synopsis ```perl sort LIST sort BLOCK LIST sort SUBNAME LIST ``` Three idiomatic forms: ```perl my @out = sort @in; # default: string cmp, ascending my @out = sort { $a <=> $b } @in; # numeric, ascending my @out = sort by_name @in; # named comparator sub ``` ## What you get back A **new** sorted list. `sort` does **not** modify the input in place. To replace an array with its sorted version you assign back: ```perl @a = sort @a; ``` In list context the return is the sorted list. In scalar context the return value is undefined — do not use `scalar sort`. The returned list contains **aliases** into the original list, exactly like a `foreach` index variable. Modifying an element of the result inside a later `foreach`, [`map`](map), or [`grep`](grep) therefore modifies the original element too. This is almost never what you want; treat the result as read-only. ## Global state: `$a` and `$b` Inside the comparator `BLOCK` or `SUBNAME`, the two elements being compared are exposed as the package globals `$a` and `$b`. These are not parameters and they are not lexicals — they are real package variables that `sort` localises for you around the call. - `$a` and `$b` live in **the package that called `sort`**. In `main`, that is `$main::a` and `$main::b`; in `Foo`, `$Foo::a` and `$Foo::b`. - **Never declare `my $a` or `my $b`** anywhere the sort block can see. A lexical `$a` or `$b` shadows the package global; the block then compares two unrelated variables and the sort silently produces garbage. Under `use warnings` you get no warning for this. - If you genuinely need `$a` / `$b` as lexicals elsewhere, refer to the sort variables by full name inside the block: ```perl print sort { $::a cmp $::b } qw(A C E G B D F H); print sort { our $a cmp our $b } qw(A C E G B D F H); ``` - A comparator defined with the prototype `($$)` (or an equivalent signature attribute) receives the pair in `@_` instead of `$a` and `$b`. This is slower than the `$a`/`$b` convention but decouples the sub from the caller's package. Both elements are passed **by reference**; mutating `$a` or `$b` in the block mutates the original list. Don't. ## Examples Default string sort: ```perl my @sorted = sort qw(banana apple cherry); # ('apple', 'banana', 'cherry') ``` Numeric ascending — the default `sort @nums` would sort `"10"` before `"2"` because comparison is by string: ```perl my @nums = sort { $a <=> $b } (10, 2, 33, 4); # (2, 4, 10, 33) ``` Numeric descending — swap `$a` and `$b`: ```perl my @nums = sort { $b <=> $a } (10, 2, 33, 4); # (33, 10, 4, 2) ``` Multi-key sort with a tiebreaker. `||` runs the second comparator only when the first returns `0`: ```perl my @people = sort { $a->{last} cmp $b->{last} || $a->{first} cmp $b->{first} } @records; ``` Sort a hash's keys by the associated value: ```perl my %age = (alice => 30, bob => 25, carol => 40); my @by_age = sort { $age{$a} <=> $age{$b} } keys %age; # ('bob', 'alice', 'carol') ``` Schwartzian Transform — when the sort key is expensive to compute, precompute it once per element, sort the `[key, value]` pairs, then strip the keys. Three stages, read bottom-up: ```perl my @sorted = map { $_->[1] } # 3. strip key sort { $a->[0] <=> $b->[0] } # 2. sort by key map { [ expensive_key($_), $_ ] } # 1. attach key @input; ``` Named comparator sub. The sub reads `$a` and `$b` from the caller's package, so it must be in (or referenced from) that package: ```perl sub by_name { $a->{name} cmp $b->{name} } my @sorted = sort by_name @people; ``` Prototyped comparator — arguments arrive in `@_`, so it works from any package: ```perl sub numeric ($$) { $_[0] <=> $_[1] } my @sorted = sort numeric @nums; ``` ## Edge cases - **`$a` and `$b` are package globals, not lexicals.** A stray `my $a` in scope silently breaks every sort in that scope. If you must, use `our $a` or `$::a` inside the block. - **`<=>` is numeric, `cmp` is string.** Using the wrong one is the most common sort bug. `sort { $a cmp $b } (10, 2, 33)` yields `(10, 2, 33)` — lexicographic, `"10"` before `"2"`. Use `<=>` for numbers. - **Empty list returns an empty list.** `sort ()` is `()`. No error. - **Single element is returned unchanged.** No comparisons happen. - **Comparator must be consistent.** If it sometimes says `$x < $y` and sometimes says the opposite for the same pair, the result is undefined. The comparator must return a total ordering: negative, zero, or positive, stably, for every call. - **`NaN` poisons `<=>`.** `$a <=> $b` returns [`undef`](undef) if either operand is `NaN`, which `sort` then treats as `0` — equal — giving an arbitrary placement. Filter first: ```perl my @clean = sort { $a <=> $b } grep { $_ == $_ } @input; ``` - **Stable sort.** Equal elements keep their input order. Rely on this for multi-pass sorts (sort by secondary key first, then by primary key). `use sort 'stable'` is the default and a no-op; `use sort '_mergesort'` / `'_qsort'` pragmas are historical and have no effect on current Perl. - **`sort` is not in-place.** `sort @a` does not touch `@a`. Use `@a = sort @a` to replace it. Assigning to `sort`'s result list aliases back into the original, so `(sort @a)[0] = ...` modifies `@a`'s smallest element. - **No loop control out of the block.** [`last`](last), [`next`](next), [`redo`](redo), [`return`](return), and `goto LABEL` do not work inside a sort comparator — the block is not a loop body. - **Parser trap: sorting a function's return value.** `sort` takes a `LIST`, so a following bareword can be mistaken for a `SUBNAME`. To sort the result of `find_records(@key)`: ```perl my @out = sort { $a cmp $b } find_records @key; # OK my @out = sort +find_records(@key); # OK my @out = sort(find_records(@key)); # OK ``` To use `find_records` as the comparator over `@key` instead: ```perl my @out = sort find_records @key; # comparator form my @out = sort { find_records() } @key; # block form ``` - **Locale-aware sorting.** Under `use locale` (without `':not_characters'`) the default string comparison follows the current collation locale instead of codepoint order. - **XSUB comparators.** If the comparator is an XSUB, the pair is passed on the argument stack the way XS functions normally receive arguments; `$a` and `$b` are not set. ## Differences from upstream Fully compatible with upstream Perl 5.42. ## See also - [`reverse`](reverse) — reverses a list; combine with `sort` for descending sorts when the comparator is hard to invert by swapping `$a` and `$b` - [`map`](map) — the other half of the Schwartzian Transform; use to attach and strip sort keys around a `sort` - [`grep`](grep) — prefilter the list (e.g. remove `NaN` or [`undef`](undef)) before handing it to `sort` - [`$a`](../perlvar) — the first element in the comparison pair, aliased as a package global for the duration of the sort - [`$b`](../perlvar) — the second element in the comparison pair, same lifetime and scoping rules as `$a` - [`<=>`](../perlop) — numeric three-way comparison; the usual operator inside a numeric sort block - [`cmp`](../perlop) — string three-way comparison; the usual operator inside a string sort block