-
-
Notifications
You must be signed in to change notification settings - Fork 5.6k
Return Any[] from broadcast() for empty input when no method applies #20049
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
Conversation
This is consistent with map().
@@ -280,7 +280,10 @@ end | |||
eltypestuple(a) = (Base.@_pure_meta; Tuple{eltype(a)}) | |||
eltypestuple(T::Type) = (Base.@_pure_meta; Tuple{Type{T}}) | |||
eltypestuple(a, b...) = (Base.@_pure_meta; Tuple{eltypestuple(a).types..., eltypestuple(b...).types...}) | |||
_broadcast_eltype(f, A, Bs...) = Base._return_type(f, eltypestuple(A, Bs...)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd leave this as is, and make the change here to return similar(Array{T === Union{} ? Any : T}, shape)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess I could do that, but that would mean _broadcast_eltype
doesn't actually return the type used by broadcast
. This can be confusing, and possibly slightly annoying for packages which call this function for their broadcast
implementation. What's the advantage of doing that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
_broadcast_eltype
does not return broadcast
's return eltype, only a guess; in general determining broadcast
's return eltype requires performing work equivalent to the broadcast
operation itself. Please find additional discussion in #19937 (comment). Best!
While being consistent with I've briefly considered whether just err::Nullable{String}
error.(err) to |
But the main issue with returning |
With that argument, |
That's true, though that doesn't mean we should create even more problematic cases if we can avoid it. I don't really have an opinion on this matter, I'm just trying to measure the consequences. Would there be any drawback in returning Cc: @JeffBezanson |
If I recall correctly, the idea was to use the result of inference if the type was concrete or if the array/iterator was empty even if things are not optimal or predictable in this case. This is what Jeff has called the StevenGJ compromise. I guess we could add the additional rule of being able to push things to empty arrays, which means replacing |
Yes, that was the discussion in #7258. But at the time it seems that |
Speaking of consistency: julia> map((x) -> error(x), 1:0)
0-element Array{Union{},1}
julia> map((x) -> error(x), [])
0-element Array{Any,1} |
Please add it to the list at #20033. |
More opinions? I've added the 0.6 milestone since the existing code on master is a behavior change from 0.5, so we should be sure we want to make it, and if so do it for both |
Sounds like we should go forward with making them consistent. |
decision is whether |
The |
Looks like the special casing is not only for empty arrays, though: julia> map(identity, Integer[1])
1-element Array{Int64,1}:
1
julia> map(identity, Any[1])
1-element Array{Any,1}:
1 FWIW, deleting that line does not break any tests, but I do wonder whether any packages depend on that. |
It seems that the line is not actually needed for bootstrap, so it should be removed. |
I've had a look at changing julia> h3(x::Float64...) = prod(x)
h3 (generic function with 1 method)
julia> itr=(h3(x) for x in Int[])
Base.Generator{Array{Int64,1},#h3}(h3, Int64[])
julia> Core.Inference.return_type(first, Tuple{typeof(itr)})
Any The problem is that So we may have to find another way of computing _default_eltype{T, F}(::Base.Generator{T, F}) = Core.Inference.return_type(F.instance, T) Of course |
Why wouldn't using a similar strategy to |
This has been lingering for a rather long time. Can we make forward progress here? |
I think the consensus has changed to change |
The correct behavior here should be to return |
#20866 is orthogonal to this. Whether inference returns |
The way forward here is to make both map and broadcast return arrays with element type |
Ah, the difference seems to be due to calling |
Could we change one of |
I can try to do this for |
Alternatively, would it make sense to never return an abstractly typed empty array, and always simply return |
This is consistent with map().
This is one way of fixing #20033.