Ask HN: Mnemonic for shift() and unshift()?

JavaScript push() and pop() are intuitive method-names because they come from the context of using an array as a "stack". You can "push" things to a stack meaning a new item is added as the new last element of the array. push() pushes a new element into the array. Pop() pops one off it.

shift() and unshift() on the other hand I always had trouble with. One of them adds a new element to the front of the array and the other removes and returns the 1st element. But which is which? I can google the answer but would be nice if I didn't have to google. And worse, sometimes I got confused between the two and used shift() where unshift() should have been used => Error,, stack overflow!

So I googled for "Mnemonics for shift() and unshift()", and found an entry on Stack Overflow. But that question was "Closed because the answers are opinion-based". I looked at the answers available but none of them struck me as particularly memorable.

Now after years of struggling with this confusion I think I've come up with a mnemonic I can live with:

Word "shift" is shorter than the word "unshift". Therefore shift() makes the array shorter.

Word "unshift" is longer than the word "shift". Therefore unshift() makes the array longer.

I know it doesn't really explain it, but it is a rule I can remember. I would appreciate hearing how anybody else remembers when to use shift() and when to use unshift().

13 points | by galaxyLogic 31 days ago

12 comments

  • Someone 30 days ago
    Learn shell programming (https://tldp.org/LDP/Bash-Beginners-Guide/html/sect_09_07.ht...) or MS-DOS (https://learn.microsoft.com/en-us/windows-server/administrat...), and it won’t be a problem remembering what shift does.

    Neither of those has unshift, but you can infer its meaning from knowing about shift.

    I also think push and pop aren’t good names. append, respectively removelast are way better.

    • galaxyLogic 30 days ago
      I agree that append() and removeLast() would be better names. But they don't exist as built-in functions in JavaScript. Therefore I need a mnemonic that makes it easy for me to remember what shift() and unshift() do.
      • gabrielsroka 29 days ago
        Try

          Array.prototype.append = Array.prototype.push;
        
        Etc
        • galaxyLogic 26 days ago
          That is tempting, and I've dome similar things earlier.

          But I don't want to do that. Why because: It is not a good practice to modify JavaScript built-in prototypes. If that was the recommended practice then someone else's code might do a similar thing, but assign some other function to it. Whoever writes it last overrides any previous definition.

          • gabrielsroka 25 days ago
            > someone else's code

            I don't use someone else's code. I use my code. But I may be the minority.

            Use a namespace, then.

              Array.prototype.glAppend = Array.prototype.push;
    • sargstuff 30 days ago
      lifo: last in, first out (cafeteria food line) -- taking from front/top, adding to back/bottom -- enought shifts will push element out of array queue without need to 'unshift'

      fifo : first in, first out (stack of plates) -- taking from front/top, adding to front/top. -- shift on "1"/push; unshift off "0"/pop. start with at least one shift/push. ideally equal number of unshifts/pops by end of task to clear the stack array.

      • wrboyce 26 days ago
        You have these the wrong way around. LIFO is a stack, FIFO is a queue.
    • brudgers 30 days ago
      "append" means adding something to the back end, e.g. appendices in a book are encountered later when sequentially processing the book's pages.

      "prepend" is used to describe adding something at the beginning of a sequence.

      Good old "cons" has the specific technical meaning of placing data at the lowest address of a sequential memory structure...and it is shorter than "append" and "prepend."

      • galaxyLogic 30 days ago
        Yes append() and prepend() would be much better names than push() and unshift().

        IF JavaScript had them as built-ins it would be great, then I wouldn't need to look for mnemonics for shift() and unshift() :-)

        But, I googled "prepend" and guess what: google replied

        "Although it sounds correct, prepend is not an English word. It was created to sound like the opposite of "append," which means to add to the end. The correct English word is "prefix".

        A slight problem with that is that "prefix" is more often used as a noun than as a verb, I think.

        • brudgers 29 days ago
          "Prepend" might not be queen's English. I'm American so so what.

          Anyway, "cons" is a better term in technical contexts.

      • sargstuff 30 days ago
        'idice' is the specific location context to put at end.
  • layer8 30 days ago
    Are you familiar with bit shifts? When you shift a 32-bit integer by one, for example, one bit will get shifted “off” the integer. In other words, the integer will have lost that bit.

    Shift on an array similarly shifts an element off the array. Unshift puts an element back on the array.

    Maybe more graphically: I you shift books on a shelf, the outermost book may fall off the shelf. To put it back on, you first need to “unshift” the books.

    How I actually remember it is from Perl, where shift is commonly used to process the next argument from the argument array. And you rarely unshift.

    • galaxyLogic 30 days ago
      The problem with a word like "shift" is that it doesn't say anything about which direction you are "shifting" the books on your shelf (or bits in your byte.) Same is true for4 unshift.

      Also "unshift" does not imply in any way that you are adding a new book to your shelf, and to which side of it.

      • layer8 29 days ago
        I'm not sure if you just want to complain about the naming, or are still genuinely looking for mnemonics. They may not be perfect, but that doesn’t mean they aren't helpful.

        The direction is simple to remember: It’s the opposite from push/pop. I thought this wasn’t your issue. But there is another way to remember, in case you forget what direction push/pop is: Removing an item from the end of an array doesn’t require shifting (moving) the remaining elements (their indices remain the same). Removing an element from the front, however, requires shifting the elements (their indices do change). Therefore shift/unshift are the operations at the front of the array, and push/pop are the ones at the back.

        The bookshelf analogy relies on "shift" being more common than "unshift" (otherwise the operations would have been named the other way around), and that shifting your books on a shelf is more common than the case where one book falls off the shelf and you have to put it back up ("unshift").

        The reason using both shift and unshift is less common, as opposed to push and pop, is again due to efficiency considerations, since the latter don’t require shifting all elements. If you want to use the array as a LIFO stack, you use push and pop. If you want to use it as a FIFO queue, you use push and shift. Unshift is usually only used in more exceptional cases.

        • paholg 29 days ago
          But you can do left shifts and right shifts. Your analogy works in comparison to right shifts, but it's backwards if compared to left shifts.
          • layer8 29 days ago
            For the question of whether “shift” removes and “unshift” adds or vice versa, it doesn’t matter if it’s left or right shift. Yes, the bookshelf analogy doesn’t tell you at which end the removal or addition occurs. But as I said, I didn’t think this was the question being asked, and if it is being asked, then it can be answered with the index shifting and the comparison to push/pop.
  • mayoff 30 days ago
    Unshift, like push, adds an element to the array.

    “Unshift”, like “push”, contains the letter “u”.

    • gregors 29 days ago
      I've never had a good one to tell my jr devs. Thank you for this!!!!
    • galaxyLogic 30 days ago
      That's a great mnemonic, I'll "push" it to my brain :-)
  • gregjor 31 days ago
    Certainly you will remember the difference now, after writing this.

    I remember the same way I remember anything else — by memorizing.

    In British English “shift” means “move,” so shifting something off an array means moving it (into a variable). Un- as a prefix indicates negation or reversing in English. So you just need to remember what shift does, and unshift does the opposite, as indicated by the word.

    • weare138 30 days ago
      I think that might be the cause of some of the confusion around these terms. They're terms that use a context of those words only native English speakers would be familiar with. If you're not a native English speaker or even maybe just younger and not familiar that specific context of those terms I can see how the terminology may be confusing and counterintuitive at first.
    • galaxyLogic 30 days ago
      > Certainly you will remember the difference now, after writing this.

      Indeed, part of my motivation for writing this was to remember it. I have spent too much time thinking about what shift() vs. unshift() do.

      The other part was that I wanted to know how others figure out when to use shift() and when to use unshift(). Thanks for everybody for your suggestions.

  • rrishi 26 days ago
    > Word "shift" is shorter than the word "unshift". Therefore shift() makes the array shorter.

    > Word "unshift" is longer than the word "shift". Therefore unshift() makes the array longer.

    This is quite useful as I too couldn't remember which is which. Thanks for sharing!

  • gqcwwjtg 30 days ago
    Unshift is a weird word for the weird method of the four. You’ve got a list. To use it as a stack you push and pop. To use it as a queue you push and shift. Unshift is the weird one.
  • sargstuff 30 days ago
    Mix html with bit twiddle logic!

    html < is open block, html > is close block.

    < and << are logical shift left for array of bits.

    > and >> are logical shift right for array of bits.

    Looking at only 'logical value of 1'. Have to open/shift left before unopen/shift right to make thing correct. aka init variable to 0; shift left/push gives 1; shift right/removes aka pops the 1.

    html < pushes/shifts all the commands onto stack.

    html > pops all the commands todo off of the stack until reach < aka end of stack marker.

  • dataflow 30 days ago
    The easiest way is learning what shift does in Bash, like another comment said, but if you're not going to do that:

    - C also has functions called getc() and ungetc(), and they're analogous.

    - "Doing" and "undoing" are actually the same in some sense: doing causes information loss, undoing causes information gain.

  • joshxyz 28 days ago
    as a 6y js/ts dev i never really bothered, i just end up coming back to mdn docs whenever im about to use those.

    especially the internals of array sort method.

  • kondrei 29 days ago
    I have this problem with splice and slice too
    • galaxyLogic 28 days ago
      I try to get by with slice() since it is simpler to understand. Semantics is "taking a slice". splice() has a meaning of not only splitting but also putting slices back together, and is used less often. I too always have to look up its definitions from docs, partly because I use it so infrequently.
    • saaliklok 28 days ago
      Oof same, I'm always going back to the docs for these
    • big_paps 27 days ago
      I somehow remembered that with : splice is more „evil“ because it changes the original. I know, it makes no sense ..
  • parentheses 29 days ago
    bash is how i remember. shift consumes an argument starting at $1.

    this is how it works in all languages

    same concept as << (bit wise left shift)