Skip to content
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

A function to resize vectors in front? #26326

Open
oschulz opened this issue Mar 5, 2018 · 12 comments
Open

A function to resize vectors in front? #26326

oschulz opened this issue Mar 5, 2018 · 12 comments
Labels
domain:arrays [a, r, r, a, y, s]

Comments

@oschulz
Copy link
Contributor

oschulz commented Mar 5, 2018

AFAIK we're currently lacking a function to resize a vector in front (well, except for the internals like Base._growbeg!).

  • At the back of a vector, we have: push!, pop! and resize!.
  • At the front of a vector, we have: pushfirst! and popfirst!.

This is lacking in symmetry. :-) Could we add Base.resizefirst!?

Symmetry aside, it may also come in quite handy in some applications - I ran into this when I wanted to implement resizing in front for ElasticArray (some use cases will need it): I really don't want to use ccall(:jl_array_grow_beg, ...), if avoidable, and there's no generic name in Base to overload for the resulting function. Or maybe I just missed it?

@JeffBezanson JeffBezanson added the domain:arrays [a, r, r, a, y, s] label Mar 5, 2018
@mbauman
Copy link
Sponsor Member

mbauman commented Mar 5, 2018

We do have append! and prepend!… both of which require values but could be used for this purpose. You can also resize! and then circshift!. But I agree it would be nice to have a bit more of a first-class way of doing this.

@nalimilan
Copy link
Member

That would also allow providing AbstractArray fallback definitions for pushfirst! and popfirst! in terms of resize! and setindex!.

Though rather than resizefirst!, it would make sense to add an argument to resize!.

@oschulz
Copy link
Contributor Author

oschulz commented Mar 5, 2018

@mbauman : Right - but to "append!", you first need an array to append, you can't create uninitialized space that way. And resize! plus circshift! will be a lot more expensive than necessary, if there's still a space reserve in front. Now that I think about it, a version of "sizehint!" that reserves space in front might also be useful.

Also, there's currently no way to shorten the array in front - except for popfirst! in a loop, which is clearly not a nice solution. :-)

@oschulz
Copy link
Contributor Author

oschulz commented Mar 5, 2018

Though rather than resizefirst!, it would make sense to add an argument to resize!

I thought about that, initially - but then pushfirst! and popfirst! came along, so now i believe resizefirst! would be very natural, and obvious to users.

@StefanKarpinski
Copy link
Sponsor Member

StefanKarpinski commented Mar 5, 2018

resize!(v::Vector, n::Integer, offset::Integer=length(a)) could be made to insert n uninitialized slots at a given offset (i.e. spot between elements). To grow the front you would write resize!(v, n, 0). EDIT: I realized after posting that this does not help since the n in resize! doesn't indicate the number of elements to add but the total size the final collection should have.

resizefirst! is a really bad name – it suggests that it would resize the first element.

@mbauman
Copy link
Sponsor Member

mbauman commented Mar 5, 2018

See also #26201. Edit: Nevermind, ignore me. I thought we had a PR for sizehint at the front, but I was mistaken. Sorry for the noise.

@JeffBezanson
Copy link
Sponsor Member

Also, there's currently no way to shorten the array in front

splice! can do that. It's true that its name is not entirely obvious though.

@oschulz
Copy link
Contributor Author

oschulz commented Mar 5, 2018

splice! can do that. It's true that its name is not entirely obvious though.

But splice just removes a single element (in an arbitrary location) right?

@oschulz
Copy link
Contributor Author

oschulz commented Mar 5, 2018

resizefirst! is a really bad name – it suggests that it would resize the first element.

True - then maybe resizefront! or resizebeg! or so?

@JeffBezanson
Copy link
Sponsor Member

You can pass a range to splice!, in which case it removes multiple elements. But it returns the removed items as a new array, which requires allocation. deleteat! can do the same thing without allocation; I should have remembered that function first.

@oschulz
Copy link
Contributor Author

oschulz commented Mar 6, 2018

Thanks, @JeffBezanson , I should have read the help of splice! all the way through. :-)

@oschulz
Copy link
Contributor Author

oschulz commented Mar 6, 2018

@mbauman, thanks for pointing out that we have prepend! to complement append!. So resize! is really the only thing that lacks an "in-front" equivalent.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
domain:arrays [a, r, r, a, y, s]
Projects
None yet
Development

No branches or pull requests

5 participants