RFC: into(T::Type, iterable) -> collection::T #36288
Labels
collections
Data structures holding multiple items, e.g. sets
design
Design of APIs or of the language itself
feature
Indicates new feature / enhancement requests
tl;dr Can we have an API (say)
into(T::Type, iterable) -> collection::T
for creating acollection
of typeT
from aniterable
?Problem
Given an arbitrary iterable and arbitrary container type, there is no consistent API to construct the container. The closest thing probably is to call the constructor. Indeed, that's what the documentation recommends
However, even things like
Vector(1 + x for x in 1:10)
orVector(Dict(:a => 1))
do not work (ref #16029). ForVector
, we can usecollect
but having arbitrary factory function for each custom container type is not great.Furthermore, this recommendation is not always reasonable. For example, if you want to implement own
vec
withyou'd want to
VectorView(array)
to not copy the inputarray
. It is reasonable to expect constructors to do only minimum amount of work, especially for "wrapper" types. For example,StructArray(a = vector)
doesn't copy the inputvector
(although it's not of the formT(x)
).Another problem is that constructors usually have a particular semantics. For example:
T(x)
whereT :< StaticArray
to treatx
as an element Inconsistencies with multi-argument constructors JuliaArrays/StaticArrays.jl#518, Fix method amguity in Scalar(::StaticArray) JuliaArrays/StaticArrays.jl#774.Adjoint
,Diagonal
,Hermitian
, ...); i.e., it is desirable if the data is not copied at all when calling these constructors.All of these points suggest that it would be nice to have an entry point for constructing a container given its type and the input iterable, separated from the constructor.
For example, StaticArrays has
sacollect(::Type{<:StaticArray}, itr)
JuliaArrays/StaticArrays.jl#792 for collecting an iterable as a given type. It'd be great to have a uniform interface so that it is possible to overload.Proposal
API
Construct a new
collection
of typeT
that contains the elements initerable
. Ifiterable
is also a container, it acts as a shallow-copy.If
T
haseltype
,keytype
, orvaltype
information, all elements incollection
areconvert
ed to the destination type. Otherwise, ifIteratorEltype(collection)
isHasEltype()
and typeT
can specify element type in the type domain,eltype(typeof(new)) == eltype(typeof(collection))
holds.If
T
has size or length information (e.g.,StaticArray
), providingcollection
with unmatched size or length throws an error.Default implementation
It is probably OK for many cases if we use the fallback implementation
Alternatively, a safer implementation is:
Naming bikeshedding
The name
into
is something I stole from Clojure https://clojure.github.io/clojure/clojure.core-api.html#clojure.core/intoIn Python, I see
$Class.from_$thing(thing)
classmethod pattern. Translating this to Julia,from(T, iterable)
can also be a reasonable choice?Some more random alternatives:
Related discussions
Merge collect() into Vector()? #16029: Merge collect() into Vector()
This would solve the problem for
Vector(iterable)
,Array(iterable)
, etc. However, we still need a dedicated generic factory function for the reasons listed above.design of array constructors #24595: design of array constructors
Most of the problems is solved for Julia 1.x?
Generic abstract array construction without instances #25107: Generic abstract array construction without instances
Since this is a discussion for common interface for creating uninitialized arrays, it's somewhat orthogonal to this issue. But
into(T, iterable)
withiterable::UndefArray
can be used for this.The text was updated successfully, but these errors were encountered: