A closure is a function without a name that you write inline and hand to another function. Nowhere is this more useful than sorting: sorted(by:) doesn't guess how you want things ordered — it asks you. You pass a closure that receives two elements and returns true when the first one should come before the second:
let nums = [3, 1, 2]
let small = nums.sorted(by: { (a: Int, b: Int) -> Bool in
return a < b
})
// small is [1, 2, 3]
That works, but Swift lets you shrink it dramatically. The compiler already knows the closure's types, single-expression closures return implicitly, and $0, $1 are automatic names for the first and second parameter:
let small = nums.sorted(by: { $0 < $1 })
And when the closure is the last argument, you can drop it out of the parentheses entirely — trailing closure syntax:
let big = nums.sorted { $0 > $1 } // [3, 2, 1]
The closure doesn't have to compare the elements themselves — any rule works. { $0.count > $1.count } orders strings by their length, longest first.
The trap: sort() is not sorted()
Swift has two sorting methods and beginners mix them up constantly. sorted() returns a NEW array and leaves the original alone. sort() rearranges the array in place — so it needs a var. Call it on a let constant:
let names = ["Charlie", "Al"]
names.sort()
...and the compiler stops you cold:
trap.swift:2:7: error: cannot use mutating member on immutable value: 'names' is a 'let' constant
1 | let names = ["Charlie", "Al"]
| `- note: change 'let' to 'var' to make it mutable
2 | names.sort()
| `- error: cannot use mutating member on immutable value: 'names' is a 'let' constant
"Mutating member" means the method modifies the thing it's called on. When you see this error, either switch to sorted() (usually what you want) or declare the array with var.
Assignment
Follow the Coding Tutorial: create let names = ["Bo", "Alexandra", "Kim", "Charlie"], then
- sort it alphabetically into
ascendingusing the full formsorted(by: { $0 < $1 })and print it, - sort it by length, longest first, into
byLengthusing trailing closure syntaxsorted { $0.count > $1.count }and print it.
The exact expected output is:
ascending = ["Alexandra", "Bo", "Charlie", "Kim"]
byLength = ["Alexandra", "Charlie", "Kim", "Bo"]
Hint
sorted never changes names, so both sorts start from the same original array — and printing an array with \(...) shows it in brackets, exactly like the expected output.
Free plan: 30 tutor messages. Premium is unlimited.