Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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
Implement accumulate and friends #702
Implement accumulate and friends #702
Changes from all commits
3a26ce9
801d95c
4985bcf
4ca0144
df1caa8
df87a52
b665233
3db20ef
6bf5e05
5a7963d
8db9ad6
File filter
Filter by extension
Conversations
Jump to
There are no files selected for viewing
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.
One thing I noticed here is that for length-0 input, the result has eltype of
Union{}
. I can see why, but in other cases we do try to to have a "sensible" output eltype for convenience, egSA{Int}[] .+ SA{Int}[]
preserves the Int eltype via some hopefully-not-dubious trickery (#664). Is it possible to do something similar here?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 don't think it's possible to solve this in general as the output value depends on the function
op
. I think another (somewhat) sensible output is to use theeltype
of input array. But this is not always the valid answer; e.g.,accumulate(//, [1, 2])
(note thatBase
'saccumulate(//, Int[])
magically returnsRational{Int64}[]
as it usespromote_op
).As all static arrays (including
MArray
) are shape-immutable, I don't think it is so harmful to returnUnion{}
element type.My preference is:
Union{}
promote_op(op, eltype(input), eltype(input))
eltype(input)
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 don't think it's possible to solve this in general as the output value depends on the function
op
.This is what #664 hacks around for
map
by usingreturn_type
😬 (but it's no worse than Base which does the same thing forbroadcast
andcollect
on empty containers). I've never been quite sure that's the right choice, but if it can't be made to work or is otherwise terrible I'm ok withUnion{}
:-) Prior to #664 we usedUnion{}
formap
and people mostly seemed ok with it.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.
Ah, I see. I misread the last half of your first comment.
But I think one difficulty of
accumulate
compared tomap
is that output "eltype
" is kind of ill-defined (or maybe it's better to say length-dependent). It's conceivable to have "type sequence" like thisBut, even though
B
,C
,D
are all different types,promote_type(B, C, D)
may return typeE
that is a concrete type. It is also easy to have "oscillatory" output:So, maybe we should use something like this?
Impressively,
julia
can figure out some non-trivial examples likeBase._return_type(f, Tuple{typeof(+), Int, Union{Int,Missing}})
andBase._return_type(f, Tuple{typeof(osc_op), Missing, Int})
.I'm not sure if we need to go this far, though.
Base
is not doing this foraccumulate
.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.
You're right, it's confusing to know what the empty case should do here and it's worse than map. With your fix we have
It seems like we must make a somewhat arbitrary choice for the length-0 case with
init
. You've gotOverall do you feel like this is an improvement on using
Union
? I do like thatcumsum
now preserves numeric eltypes and I feel like that could be helpful for users for the same reason that "fixing" map was.We do have oddities like
I think that inconsistency between here and Base might be harmless though, and it's certainly not clear how to "fix" it.
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.
That's a tough question... 😅 Personally, I think we should be using
Union{}
eltype everywhere when it's not possible to figure outeltype
without relying on the compiler. However, we don't have a good toolset and coding convention for dealing withUnion{}
eltype ("mutate-or-widen" style, even at the surface API level).But I think the consistency of the API within a package and with respect to
Base
matters. Asmap
is already usingreturn_type
, overall, I think usingreturn_type
seems to be a decent solution here.