Recommended idiom for collecting narrowest type

How to collect an iterator, X, into an instance of Array, Y, such that eltype(Y) is based on the typejoin of the type of each value of X:

  • Using Collects.jl, which improves upon the interface and implementation of collect:

    using Collects: collect_as
    collect_as(Array, X)
    
  • Using collect, if you want to avoid depending on Collects.jl for some reason:

    • Using collect directly:

      collect(Iterators.map(identity, X))
      
    • Using map, which is implemented using collect:

      map(identity, X)
      

The documentation says:

The element type of the returned array is based on the types of the values collected. However, if the iterator is empty then the element type of the returned (empty) array is determined by type inference.

So the docs do not specify whether types are combined with typejoin or with promotion.

In my opinion:

  • It would be breaking for Base to change this behavior of collect regarding returned eltype.

  • However, a package adding a method to collect could do this. IMO that would be a bad practice, but allowed according to the contract as specified in the docs.

In any case, there is Collects.jl, which:

  • Generalizes the collect interface.

  • Documents the behavior in detail.

In summary: just use Collects.jl if you are worried about collect for any reason. Its topic here on Discourse:

That is just typejoin promote_typejoin.

While the syntax is similar, there are multiple distinct things colloquially referred to as “comprehension”. The form you refer to ([1, 2.0]) does promotion, while the topic here, as defined in the OP, is the form that does typejoin.

@Deduction42 @mbauman creating an issue on the Collects.jl repo:

Feel free to provide more specific suggestions.