Description
The doc string of first(::Any)
says:
Get the first element of an iterable collection.
For an unordered collection the concept of a "first element" is not defined. It's not defined in the docs, and, intuitively, I'd say it doesn't exist at all, so I sometimes expect first
and findfirst
to just throw when given an unordered collection. In the case of built-in unordered collections, like Dict
or Set
, instead an element is returned.
That said, collections are basically just iterators in Julia, and every nonempty iterator has a "first element", obtainable with (elem, _) = iterate(iterator)
. In that sense it might make some sense to identify "first element of the collection" as "first element in the iteration order". However, in that case the documentation should make clear the non-obvious lack of some nice properties: the iteration order is not necessarily constant for a single iterator. Indeed, last time I was interested in Golang, what they did is randomize the iteration order of the built-in unordered hash map collection. The implication is that first
may, for example, choose a return value randomly among the elements of the collection, shuffling before returning, something that may be surprising but seems legal on further thought.
This is not about Set
or Dict
, because changing their behavior would presumably be breaking. This is about the generic interface of first
. The docs should make clear:
- What can a user of generic collections expect when the collection is not ordered?
- What interfaces must an implementor of a new collection abide by.
Cross-reference: #38927. That issue is perhaps more specific to the search and find functionality around findfirst
and findlast
.