Skip to content

semantics of first for unordered iterators #58199

Open
@nsajko

Description

@nsajko

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    collectionsData structures holding multiple items, e.g. setsdesignDesign of APIs or of the language itselfiterationInvolves iteration or the iteration protocol

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions