-
-
Notifications
You must be signed in to change notification settings - Fork 5.6k
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
give sum(T::Type, xs) = zero(T)
when xs is empy
#20561
Conversation
We allow users to call `sum(T::Type, xs)`. Currently, e.g. `sum(Float64, [])` gives an error because the `eltype` of `[]` is `Any` and so inference fails. But the fact that the user supplied a type means that we know the intended `eltype`, so we can use it to set e.g. `sum(Float64, []) = zero(Float64)`.
I don't think the behavior |
Also, if you're going to write |
The place where this is better is stuff like |
@ararslan The caller of @pabloferz Agreed, of course. And someone who was going to write @oscardssmith I'm not familiar with that, please could you explain? @tkelman will add tests if some consensus on usefulness emerges 👍 |
That can't be assumed in general, especially when writing generic code. As careful as people try to be with types, type inference can still give you an element type of
I don't think that's true at all? This PR concerns only the empty case, plus I'd actually argue that this behavior results in more magic. |
Which I wish we didn't do! But since we have that behavior, we need to mitigate it by reducing the impact of getting a wider-typed array: So I'd be fine with this, except I believe it makes some cases of |
This behavior makes sense to me too. The fact that the input can contain elements of an incorrect type is irrelevant: |
@JeffBezanson That's interesting, I hadn't thought of that. Where does the Of course this type-instability can be avoided by writing I agree, the error message is less appropriate when someone writes
|
This needs to be considered together with #20560, as presently e.g. |
just wondering -- does this suggest |
Yup! |
It would be great to revive this PR, or find a solution of some form. I understand that writing type inferrable code is ideal, but sometimes it is not possible or worth it, then one has to special-case robustzero(_) = 0.0
robustzero(::Type{T}) where {T <: Real} = zero(T)
isempty(v) ? robustzero(eltype(T)) : sum(v) or similar, eg with nested AD applications where getting inference to work can be tricky. |
maybe
|
Possibly, but I would prefer to go to the fallback only when sum(Int, Float64[]) === 0.0
sum(Int, Any[]) === 0 |
|
Neat. Now if only we could replace |
Does this approach meet the desired outcomes mentioned early in this thread?
|
Now that we have |
closed since we now have #36188 |
From #5311, we allow notation like
sum(T::Type, xs)
to cast the return type of the sum. CurrentlyWith this PR:
This lets you avoid writing boilerplate
if isempty(xs) ... else ...
code around what should be a simplesum(T, xs)
, by handling the case whenxs
is empty in the natural way.This is achieved by extending
mr_empty
, which dispatches onf::Callable, op, T::Type
. HereCallable = Union{Type, Function}
. Whenf::Function
, there is currently nothing we can say in general (some special cases are defined, likeidentity
andabs2
). Whenf::Type
, however, the user has indicated what resulting type he would like: therefore, whenop = +
, returnzero(f)
, and whenop = *
, returnone(f)
. This also enhances the behaviour ofsum(T::Type, xs)
andprod(T::Type, xs)
.Note this introduces a new error possibility:
but I feel like anyone who tries to sum strings or any type
T
without azero(T)
has only himself to blame. And of course