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

pop/enqueue/shift multiple items #1854

Closed
mlubin opened this issue Dec 30, 2012 · 16 comments
Closed

pop/enqueue/shift multiple items #1854

mlubin opened this issue Dec 30, 2012 · 16 comments

Comments

@mlubin
Copy link
Member

mlubin commented Dec 30, 2012

It would be convenient syntactically in some cases to be able to pop/enqueue/shift multiple items. It looks like the necessary low-level functionality is already there with jl_array_del_end/jl_array_grow_beg/jl_array_del_beg (respectively) taking a number of elements parameter, but this isn't currently exposed.

Additional methods for pop and shift could be added which take a number of elements parameter. There's a subtlety with enqueue in that the syntax should be consistent with the push/append! pair.

@StefanKarpinski
Copy link
Sponsor Member

Good ideas. While we're at it, there are a few naming issues here:

  1. I would like all of these to have ! on them.
  2. I really hate the name enqueue; I know that shift and unshift are not the best names, but it's what dynamic programming languages have been calling these operations for a very long time now.

@mlubin
Copy link
Member Author

mlubin commented Dec 31, 2012

How about pushbeg, popbeg, and prepend? I would keep push and pop short because they're probably used much more frequently.

@StefanKarpinski
Copy link
Sponsor Member

My point was not to make up new names but use shift and unshift because that's what other languages (Perl, Python, Ruby) already call these operations.

@JeffBezanson
Copy link
Sponsor Member

Ok, I give in and we can get rid of enqueue. I assumed we would have it if
there were an actual queue type, and therefore vectors might as well
support it too. I was not aware that queues are now called unshifts :)
On Dec 31, 2012 10:51 AM, "Stefan Karpinski" [email protected]
wrote:

My point was not to make up new names but use shift and unshift because
that's what other languages (Perl, Python, Ruby) already call these
operations.


Reply to this email directly or view it on GitHubhttps://github.com//issues/1854#issuecomment-11779248.

@mlubin
Copy link
Member Author

mlubin commented Dec 31, 2012

I'll yield to you guys here. What about the syntax for prepending a bunch of elements?

@StefanKarpinski
Copy link
Sponsor Member

I think vararg push(a,x...) and unshift(a,x...) make sense. For push the order is obvious, but for unshift it's a little less obvious. Likewise, we can have two-argument pop and shift functions where the second argument determines how many items to pop or shift.

@JeffBezanson
Copy link
Sponsor Member

That's ok syntactically and name-wise, but it will require some very serious work to avoid copying collections to and from the stack all the time. The problems are:

  • A vararg object (currently a tuple) is indexable, but not every collection is, so we might have to change this
  • If I call f(x, y, z...) as f(xs...) I need to take two items off xs, but (1) not every collection efficiently supports tail (all-but-first), and (2) the number of items to take is not known until the middle of the dispatch process, so in the worst case we need to make generic next calls as part of dispatch. Same problem the other way when f(xs...) is called as f(a, b, zs...).

We could fix the second thing by requiring anything passed as xs... to exactly match a ... formal argument. The signature f(x, y, z...) would mean you must pass 2 explicit arguments, followed by c... where c is iterable, or else a series of ordinary arguments.

@toivoh
Copy link
Contributor

toivoh commented Dec 31, 2012

We could fix the second thing by requiring anything passed as xs... to exactly match a ... formal argument. The signature f(x, y, z...) would mean you must pass 2 explicit arguments, followed by c... where c is iterable, or else a series of ordinary arguments.

That would kind of kill f(args...) as being the ultimate format to specify any function invocation, from a pair f, args. I'm ok with if it's not always efficient, but please don't take it away!

@JeffBezanson
Copy link
Sponsor Member

I agree, so we are left with picking out the cases we can optimize, and may have to relax the promise that a vararg object is a tuple, or maybe even indexable. I'm not totally comfortable relying on this optimization to a large extent, as the worst case is quite bad: copying a whole collection, and possibly inspecting the type of every element. That would argue for a push_all, or append/prepend.

@mlubin
Copy link
Member Author

mlubin commented Jan 1, 2013

Sounds to me like append/prepend is the much simpler route.

@johnmyleswhite
Copy link
Member

+1 for getting rid of enqueue.

@simonster
Copy link
Member

My point was not to make up new names but use shift and unshift because that's what other languages (Perl, Python, Ruby) already call these operations.

Python doesn't have shift or unshift for lists at all. You have to pop(0) and insert(0, x). Deques have popleft and appendleft.

@StefanKarpinski
Copy link
Sponsor Member

Python doesn't have shift or unshift for lists at all. You have to pop(0) and insert(0, x). Deques have popleft and appendleft.

My mistake. I could have sworn I looked this up in Python when we were first bikeshedding this and found that it had unshift also.

@JeffBezanson
Copy link
Sponsor Member

pop(array, count) is ok in itself, but I think it conflicts too flagrantly with python, where the second argument is an index instead of a count.

@StefanKarpinski
Copy link
Sponsor Member

The python version seems pretty weird to me, but there is the issue of the type signature. Do you return an array of the popped elements or a tuple? There's also the matter of their order, of course.

@JeffBezanson
Copy link
Sponsor Member

Now we have push! / append! and unshift! / prepend!. delete! can delete any range of elements. We might want a non-allocating version of delete that doesn't return anything; maybe empty!(a, a:b).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants