-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Move to a factory pattern for array creation #22630
Comments
With regards to benefit 1: Currently there aren't any constructors on AbstractArray, so benefit 2 could be possible right now. It's just more of a mouthful than you probably want. If you're interested in that, I'd propose it separately. As a renaming, the major benefit is in changing how we talk about things. Sometimes that can be worth it. In this case, the manual makes careful distinction between vector, matrix, and array vs. |
If we did that, we would have to rename |
I'm not really sure such a large change is worth any of the benefits that follow. First, I'd say the I would like to see more constructors, but I guess we can add methods to If it were a clearer win-win, this might make sense to sneak in before 1.0, but I'd argue if we can't follow "if it ain't broke, don't fix it", then it might turn off potential users worried about ongoing language instability. |
I agree with both of these. I think people use |
You may be interested in this ancient series of commits: 38d8b8b6678d5a1ccca5d8aa45c8af19a99df6d6^...eafcbd8. We used to use the names |
The commit message of 26b8497 explained it fairly well, if somewhat simplistically:
It's kind of funny that I used the same "reach" metaphor back then to explain it. |
@StefanKarpinski I completely agree with your point if you look at only half of the proposal I made, namely the renaming part (and I also have to say that my original write-up was not very clear...). That, in isolation, makes clearly no sense. But if you look at the whole proposal and apply the criterion "the simplest name should do the right thing in most instances", my proposal fares well (I think), if not better, than what we have right now. Of course there might be other arguments against it. The core idea here is to move to a factory pattern for array creation, where the default method for creating an array would move from specifying the precise container (array) type, to a model where you say "give me an array that is really good for storing elements of type T". That factory method would be The other use case for the type name is in situations where one "consumes" an array, i.e. in dispatch and in field declarations in types. In my mind, in both cases, the most common correct thing in those situations is to use the abstract super type for arrays: in general a function that takes an array should work with any array, not just dense arrays, similar if I declare a type that holds an array, things are much more general if it can hold any array type, not just dense arrays. Currently, one has to use the longer name So I think just based on the criterion "the shortest name should do the right thing in most cases", my proposal is at least as good as what we have currently: array creation still would use What are the benefits of all this? I see these right now:
I've changed the title of this issue to something more descriptive. My original title was really lame, but the new name picked by @mbauman really only highlights one part of the overall proposal. |
You still seem tied to a rename as part of this proposal. That's not necessary to achieve the goals you want. In fact, a rename won't even achieve those goals — it seems like you just want all code using Like I said, there's definitely value in rethinking our abstract array constructors. The name itself is the most superficial part of this proposal; let's nail down the functionality. Currently Predicating this on an intensive renaming that'd require two-four major release cycles to deprecate is really a non-starter, IMO. |
I second what @mbauman said, and would add that the entire motivation for this seems to stem from wanting the ability to write |
I think we might want something like |
We can use whatever algorithm we want to determine the element type, though I concede that one could debate whether it is "sensible". promote_type could in fact return a union type, as could typejoin (which is already kind of an arbitrary join algorithm that just joins things however we feel like). |
Yes, I think |
OK, that actually does work surprisingly well. I was expecting to run into lots of issues trying to define that. julia> struct Null end
julia> Base.promote_rule(::Type{Null}, T::Type) = Union{Null, T}
julia> Base.promote_rule(::Type{Union{T, Null}}, S::Type) where {T} = Union{Null, Base.promote_type(T, S)}
julia> Base.convert(::Type{Union{T, Null}}, x) where {T} = convert(T, x)
julia> [1, Null()] |> typeof
Array{Union{Int64, Null},1}
julia> [1, 3.0, 4.0, Null()] |> typeof
Array{Union{Float64, Null},1}
julia> [Null(), 1, 3.0, 4.0] |> typeof
Array{Union{Float64, Null},1} Inference uses |
FWIW, that's exactly the approach taken in Nulls.jl and it's been working out quite well. |
Ah, good to know. Looks like you're missing the second rule I added (needed to give transitivity, such that |
Shouldn't the second example also become |
Yes, it does. (I fixed the text above when I noticed my copy-paste error, but I assume you noticed the error in the notification email?) |
No, I think the GitHub webpage became inconsistent. Odd - carry on. |
This might well be a terrible idea, but I can't figure out why, so here we go with an idea about a revamp of the array type hierarchy:
Rename
AbstractArray
-->Array
,DenseArray
-->AbstractDenseArray
andArray
-->DenseArray
. The new type hierarchy would look like this:The final piece is to keep the
Array
constructor methods around, but now they would be methods on the abstract typeArray
. The default methods would return aDenseArray
, but one could add methods in packages that return a different array type.There would be two benefits:
foo(a::Array{Int,1})
, but I'm pretty sure in almost all cases that should really have beenfoo(a::AbstractArray{<:Int,1})
(at least in julia 0.6+ with the new type system). With this new proposalfoo(a::Array{Int,1})
won't work at all, and maybe that would be a good thing.Array{T,N}(d::NTuple{N,Int}) where {T<:Foo,N}
(actually, a few more would be needed) that would return a custom array type instead ofDenseArray
if one creates an array ofFoo
s. In some sense this idea was inspired by Support isbits Union array elements and struct fields #22441, which would change how arrays of a certain element type are stored in memory. HavingArray
be a kind of factory method for custom array types would allow a similar design for other element types, i.e. any package could decide that one should get a custom array type if one creates an array of those elements via theArray
method. I'm currently playing with that kind of design in WIP DataValueArray queryverse/DataValues.jl#12 for a custom type, so that would be one use case.I haven't even started to think about how this could be phased in, and I can well imagine that the problems around that might be enough to make this a moot suggestion. I guess I'm not even sure enough whether this would be a good idea on its own (if we didn't have to worry about backwards compat), so I deferred thinking about a deprecation strategy for now :)
The text was updated successfully, but these errors were encountered: