Iter
The Iter component provides utility functions for inspecting and reducing iterables. Unlike Vec and Dict, which eagerly produce arrays, Iter functions work directly with any iterable -- arrays, generators, and iterators -- making them ideal for querying data without creating intermediate collections.
When to Use Iter vs Vec/Dict
Use Vec or Dict when you need a transformed array as output (mapping, filtering, sorting). Use Iter when you need to answer a question about an iterable (does it contain X? what is the first element? how many items?) or reduce it to a single value.
use Psl\Iter;
use Psl\Vec;
// Vec: "give me a new array with doubled values"
Vec\map([1, 2, 3], fn($n) => $n * 2); // [2, 4, 6]
// Iter: "what is the sum of these values?"
Iter\reduce([1, 2, 3], fn($sum, $n) => $sum + $n, 0); // 6
Querying
use Psl\Iter;
// First and last element (null if empty)
Iter\first([10, 20, 30]); // 10
Iter\last([10, 20, 30]); // 30
// Check for emptiness
Iter\is_empty([]); // true
Iter\is_empty([1]); // false
// Count elements
Iter\count([1, 2, 3]); // 3
// Contains: check if a value exists (strict equality)
Iter\contains([1, 2, 3], 2); // true
Iter\contains([1, 2, 3], '2'); // false (strict)
// Contains key: check if a key exists
Iter\contains_key(['a' => 1, 'b' => 2], 'a'); // true
// Random: get a random element
Iter\random([10, 20, 30, 40]); // e.g. 30
Predicates
use Psl\Iter;
// All: do all elements satisfy the predicate? (short-circuits on false)
Iter\all([2, 4, 6], fn(int $n) => ($n % 2) === 0); // true
Iter\all([2, 3, 6], fn(int $n) => ($n % 2) === 0); // false
// Any: does at least one element satisfy the predicate? (short-circuits on true)
Iter\any([1, 3, 5], fn(int $n) => $n > 4); // true
Iter\any([1, 3, 5], fn(int $n) => $n > 9); // false
Searching
use Psl\Iter;
use Psl\Str;
// Search: find the first value matching a predicate
Iter\search(['foo', 'bar', 'baz'], fn(string $v) => Str\starts_with($v, 'ba'));
// 'bar'
Iter\search([1, 2, 3], fn(int $v) => $v > 10);
// null (not found)
Reducing
use Psl\Iter;
// Reduce: fold an iterable into a single value
Iter\reduce([1, 2, 3, 4], fn(int $carry, int $v) => $carry + $v, 0);
// 10
// Reduce with keys: the callback also receives the key
$cart = ['apple' => 2, 'banana' => 3];
$prices = ['apple' => 1.50, 'banana' => 0.75];
Iter\reduce_with_keys($cart, fn(float $total, string $item, int $qty) => $total + ($prices[$item] * $qty), 0.0);
// 5.25
Side Effects
use Psl\Iter;
// Apply: execute a function on each element (returns void)
Iter\apply(['alice', 'bob'], fn(string $name) => print "Hello, {$name}!\n");
// Prints:
// Hello, alice!
// Hello, bob!
Rewindable Iterators
Generators in PHP can only be iterated once. The Iter\Iterator class wraps a generator so it can be rewound and iterated multiple times without re-executing the generator.
use Psl\Iter;
$gen = (function () {
yield 'a';
yield 'b';
yield 'c';
})();
$iterator = Iter\rewindable($gen);
Iter\count($iterator); // 3
$iterator->rewind();
Iter\first($iterator); // 'a' -- still accessible after counting
See src/Psl/Iter/ for the full API.