-
-
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
fix non numeric accumulate(op, v0, x) (#25506) #25515
Conversation
@simonbyrne You said in the issue #25506:
Can you explain whats wrong with the fix in this PR and provide an example that fails? |
I don't think this will fix
|
@simonbyrne I think the
|
Can somebody review this? |
I would like to change that to be consistent |
Its was a conscious design decision, that |
I'm actually trying to find that discussion at the moment: do you have a link? I would like to change |
FWIW I am also in favor of making this consistent with |
Thanks for the links, I'll leave that to a separate issue. Even if we don't widen, I would still prefer to use |
base/multidimensional.jl
Outdated
n == 1 && return result | ||
_accumulate_pairwise!(op, result, v, v1, i1+1, n-1) | ||
return result | ||
end | ||
|
||
function accumulate_pairwise(op, v::AbstractVector{T}) where T | ||
out = similar(v, rcum_promote_type(op, T)) | ||
out = similar(v, promote_op(op, T)) |
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.
This (and others) should probably be promote_op(op, T, T)
: though built-in operators provide unary versions, anonymous functions typically won't.
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.
Oh thanks! I somehow assumed promote_op(op,T) = promote_op(op,T,T)
without checking. Documenting it is a good idea!
Can someone rerun CI? |
The correct thing to do would be to do the same as |
@martinholters What do you mean by empty case? Are you talking about |
The situation where the output is empty, so where
Conceptually, it works as follows:
If the code is type stable, inference can figure out that the type check in 2) can be optimized away. So a sufficiently tweaked implementation can be quite efficient. However, julia> accumulate(*, ['a', 'b'])
2-element Array{Any,1}:
'a'
"ab" may not be what you want in the end. (But then again, |
To save you some time hunting around (the broadcast code is a bit confusing): |
Mhhh, seeing julia> accumulate(*, ['a', 'b'])
2-element Array{Any,1}:
'a'
"ab" hurts my eyes. Getting |
I think we should still be able to use |
@simonbyrne okay you are right, we could still use |
Maybe we have different opinions of what "right" is here? To me, julia> accumulate(*, [1m, 1m]) # using Unitful (result faked)
2-element Array{Unitful.Quantity{Int64,D,U} where U where D,1}:
1 m
1 m^2 which is basically the same situation. Would we want to enforce some other element type (and likely cause a failure by doing so)? |
To me the difference between Base.promote_rule(::Type{Char}, ::Type{S}) where S<:AbstractString = S
Base.convert(::Type{String}, c::Char) = string(c) allowing this to work: julia> promote('a', "ab")
("a", "ab") That would, I believe, naturally make the |
Okay maybe the issue is indeed more with general |
Ultimately the reason you want |
@jekbradbury There isn't always such an identity element, e.g. |
Given that |
I agree, which is why I defined a |
Assuming #25728 lands, could this serve as a prototype implementation? function accumulate(f, x)
res = Vector{Any}(uninitialized, length(x))
res[1] = x[1]
for i in 2:length(x)
res[i] = f(res[i-1], x[i])
end
restype = mapreduce(typeof, promote_type, res)
return convert(Vector{restype}, res)
end Obviously, this is not the most efficient way to go about it and is restricted to non-empty |
I've created a WIP fix in #25766, which I think might be a more general solution. |
I close this in favor of #25766. |
Fix #25506