julia icon indicating copy to clipboard operation
julia copied to clipboard

Add `empty` for `AbstractArray`s and their types

Open janEbert opened this issue 6 years ago • 13 comments

empty now works on all AbstractArrays and the corresponding call using Type{<:AbstractArray}. The method specialized on AbstractVector remains for inlining purposes. I'm not sure whether that is actually necessary but I'm sure you can tell. (And maybe also explain how to test for that myself. That would be amazing!)

janEbert avatar Oct 06 '19 14:10 janEbert

The motivation to make empty work on types (instead of instances) is not clear here. Also, empty is defined for other kind of containers, so the same would have to be done for those too.

rfourquet avatar Oct 06 '19 14:10 rfourquet

Assume you have a Vector{Vector{Int}} of sequence data. You cannot construct an empty element for it using eltype. Sorry, not looking for other methods of empty was a silly oversight of me. I will fix it.

janEbert avatar Oct 06 '19 17:10 janEbert

You cannot construct an empty element for it using eltype.

At least In this particular case you can do eltype(Vector{Vector{Int}})()

Sorry, not looking for other methods of empty was a silly oversight of me. I will fix it.

It's a good starting point, and I would wait for more feedback before spending time on updating this PR to other methods.

rfourquet avatar Oct 06 '19 17:10 rfourquet

Hehe, you are right. I was just confused when it didn't work and wanted to patch the hole since most methods usually take types rather than instances (or both).

It's a good starting point, and I would wait for more feedback before spending time on updating this PR to other methods.

Thanks for saying that, I will not continue for now, then. However, I had already started and found that writing every method for instances and types was not good design.

If this seems worthwhile, maybe having a generic

#= @inline ? =# empty(a, types...) = empty(typeof(a), types...)

just like for eltype would be a good idea.

janEbert avatar Oct 06 '19 17:10 janEbert

I also encountered another use case. Pre-allocating a Vector of Arrays of high dimensionality requires you to write an array comprehension with the awkward Array{Int, 25}(undef, Tuple(Iterators.repeated(0, 25))) constructor. Even for saner dimensionalities, this quickly leads to unreadable code where empty(Array{Int, 25}) is much quicker to process.

janEbert avatar Oct 13 '19 10:10 janEbert

I have a few questions for which I don't have solid answers:

  • Does it make sense for the other methods of empty (the non-array ones) to allow types, too?
  • Should we have a fallback for empty(x) = empty(typeof(x)) a la eltype? What would the default empty(::Type) be? Maybe just have this fallback for ::AbstractArray?
  • Are there any cases where you need the object itself to determine what its empty looks like (and the type doesn't have enough information)?

mbauman avatar Oct 15 '19 16:10 mbauman

* Does it make sense for the other methods of `empty` (the non-array ones) to allow types, too?

I'd say yes.

* Should we have a fallback for `empty(x) = empty(typeof(x))` a la `eltype`?  What would the default `empty(::Type)` be?  Maybe just have this fallback for `::AbstractArray`?

Yes, makes sense.

* Are there any cases where you need the object itself to determine what its `empty` looks like (and the type doesn't have enough information)?

Hopefully not. Actually that's a question we should also try to address for similar, as having a version of it taking a type rather than an instance would be useful in other situations (https://github.com/JuliaLang/julia/pull/20815).

nalimilan avatar Oct 18 '19 10:10 nalimilan

It's usually quite a bad idea to introduce methods that work on both types and instances of types since types are values in Julia so this tends to produce an inherent ambiguity. However, in this case the empty function only makes sense for collections and types are not collections, so it seems safe and unambiguous to me:

  • if the argument is a type, try to create an empty instance of that type
  • if the argument is not a type, type to create an empty instance of the value's type

StefanKarpinski avatar Oct 28 '19 14:10 StefanKarpinski

Hey Stefan, so you are in favour of something like empty(a, types...) = empty(typeof(a), types...)? I'm sorry this hasn't moved along at all, I'm a bit busy this month but once I find the time, I'll get back to this taking all the feedback into account! Thank you all.

janEbert avatar Nov 01 '19 12:11 janEbert

Sure, I think that would be fine.

StefanKarpinski avatar Nov 27 '19 16:11 StefanKarpinski

@janEbert Sorry for neglecting this PR for 4 years. It now has conflicts. If you are still interested and would be willing to update it, I think it could be merged soon?

fingolfin avatar Feb 15 '24 09:02 fingolfin

Hi Max, sorry from my side; after all I promised to add stuff to the PR but never did. I haven't used Julia deeply in a while but if you are fine with waiting a bit more for me to catch up again, I'll gladly update the PR according to all the 4 amazing years of development. ;)

janEbert avatar Feb 15 '24 09:02 janEbert

@janEbert not your fault. thank you for being willing to pick this up again -- and sure, take your time

fingolfin avatar Feb 15 '24 22:02 fingolfin