Type-hinting iterable is the right choice for anything that consumes a sequence, and it makes two promises the caller has to honour.
public function export(iterable $rows): void
{
foreach ($rows as $row) {
fputcsv($this->handle, $row);
}
}
$e->export([$a, $b]); // array
$e->export($this->stream()); // generator
// what the method may NOT do with an iterable:
// count() it, iterate it twice, or assume it is finite
Accepting iterable is a promise to consume it once, in order, without counting — and code that quietly calls count() works until somebody passes a generator. is_countable() is the guard, and needing it usually means the signature wanted array. The other half is that a generator may be infinite, so any method that reads all of it before doing anything has made a stronger assumption than its signature states.