Sorting
Two sorts in all five BEAM languages: the trivial [3, 1, 2] -> [1, 2, 3], then a list of {name, age} people sorted by age descending. Watch the two flavours of API - Erlang and LFE pass a comparator fun(A, B) -> A > B to lists:sort/2, Elixir and Gleam prefer a key function (Enum.sort_by / list.sort with a by: comparator) so you say what to sort on rather than how to compare, and Luerl falls back to Lua's in-place table.sort with a <-style comparator closure.
-module(sorting).
-export([run/0]).
run() ->
Sorted = lists:sort([3, 1, 2]),
%% => [1, 2, 3]
People = [{"Alice", 30}, {"Bob", 25}, {"Carol", 35}],
%% lists:sort/2 takes a comparator returning true when A should come first.
%% Sort by age descending: A precedes B when A's age is greater.
ByAgeDesc = lists:sort(
fun({_, AgeA}, {_, AgeB}) -> AgeA >= AgeB end,
People),
%% => [{"Carol",35}, {"Alice",30}, {"Bob",25}]
{Sorted, ByAgeDesc}.Erlang's lists:sort/1 handles the default ascending order, while lists:sort/2 takes a comparator fun that returns true when its first argument should sort before its second; the {_, AgeA} patterns pull the age straight out of each tuple.
people = [%{name: "Alice", age: 30}, %{name: "Bob", age: 25}, %{name: "Carol", age: 35}]
sorted = Enum.sort([3, 1, 2])
# => [1, 2, 3]
# Enum.sort_by takes a *key function*; :desc says biggest key first.
by_age_desc = Enum.sort_by(people, & &1.age, :desc)
# => [%{name: "Carol", age: 35},
# %{name: "Alice", age: 30},
# %{name: "Bob", age: 25}]
{sorted, by_age_desc}Elixir favours Enum.sort_by/3: you give a key function (& &1.age, the capture shorthand for fn p -> p.age end) and a direction atom like :desc, so you describe what to sort on instead of writing a comparator by hand.
import gleam/int
import gleam/io
import gleam/list
import gleam/order.{type Order}
import gleam/string
pub type Person {
Person(name: String, age: Int)
}
pub fn main() {
let sorted = list.sort([3, 1, 2], by: int.compare)
// => [1, 2, 3]
let people = [
Person("Alice", 30),
Person("Bob", 25),
Person("Carol", 35),
]
// list.sort takes a comparator returning an Order (Lt/Eq/Gt).
// Flip the arguments to int.compare to sort ages descending.
let by_age_desc =
list.sort(people, by: fn(a: Person, b: Person) -> Order {
int.compare(b.age, a.age)
})
// => [Person("Carol", 35), Person("Alice", 30), Person("Bob", 25)]
io.println(string.inspect(sorted))
io.println(string.inspect(by_age_desc))
}Gleam's list.sort takes a labelled by: comparator that must return an Order (Lt/Eq/Gt), and int.compare builds one for you; swapping its arguments (int.compare(b.age, a.age)) flips ascending into descending without any mutation.
(defmodule sorting
(export (run 0)))
(defun run ()
(let ((sorted (lists:sort '(3 1 2)))
;; => (1 2 3)
(people (list (tuple "Alice" 30)
(tuple "Bob" 25)
(tuple "Carol" 35))))
;; lists:sort/2 takes a comparator; return 'true when A sorts first.
;; Match the age out of each tuple and compare descending with >=.
(let ((by-age-desc
(lists:sort
(lambda (a b)
(>= (element 2 a) (element 2 b)))
people)))
;; => (#("Carol" 35) #("Alice" 30) #("Bob" 25))
(tuple sorted by-age-desc))))LFE calls the same Erlang lists:sort/1 and lists:sort/2, written as S-expressions: the comparator is a (lambda (a b) ...) that pulls each age with (element 2 a) and returns true for descending order via (>= ...).
local nums = {3, 1, 2}
-- table.sort mutates the table in place; no comparator = ascending.
table.sort(nums)
-- nums is now {1, 2, 3}
local people = {
{ name = "Alice", age = 30 },
{ name = "Bob", age = 25 },
{ name = "Carol", age = 35 },
}
-- The comparator returns true when a should come before b.
-- a.age > b.age gives descending order by age.
table.sort(people, function(a, b)
return a.age > b.age
end)
-- people is now ordered Carol (35), Alice (30), Bob (25)
for _, p in ipairs(people) do
print(p.name, p.age)
endStandard Lua (what Luerl runs) sorts a table in place with table.sort; the optional second argument is a comparator closure returning true when its first argument sorts first, so a.age > b.age yields a descending order.