Search code examples
arraysunixstackdc

dc unix : preserving initial value even after storing new value at the same array index


I'm unable to understand this example given in manpage of dc:

$ dc  
 1 0:a 0Sa 2 0:a La 0;ap  
 1  

To me answer should be 2 because:

  1. 1 0:a
    Here we store 1 at 0th position of array a.

  2. 0Sa
    Now we push 0 to the stack of register a.

  3. 2 0:a Now here again we store 2 at 0th position of array a thereby overwriting the previous 1 stored at that location.

  4. La
    Now we pop the 0 stored on stack of register a and push it to main stack.

  5. 0;a
    Now we again push 0 to the main stack and then pop it to use as array index and so push the 2 stored at 0th location of array a to main stack.

  6. p
    Now we print the top of main stack which is 2. So answer should be 2.

What am I missing?

Edit :

$ dc -V
dc (GNU bc 1.06.95) 1.3.95

Solution

  • The explanation given before the example in the man page:

    Note that each stacked instance of a register has its own array associated with it.

    In other words, when you use array commands and stack commands on the same register, you create a 2-dimensional structure. The array commands operate on entries within the top row, and the stack commands operate on whole rows.

    Also, the "scalar" value of a stack entry retrieved with the l and L commands is completely separate from the array, not just an alias for the 0th element. (I didn't get that from the man page, but it seems to be true in my experiments.)

    Here are the commands in the example with the resulting values of a expanded into a verbose format. The outermost structure is the stack, with the top listed first.

    Initial value of all registers:

    [
      { scalar: undefined, array: [] }
    ]
    

    1 0:a

    [
      { scalar: undefined, array: [1] }
    ]
    

    0 Sa

    [
      { scalar: 0, array: [] },
      { scalar: undefined, array: [1] }
    ]
    

    2 0:a

    [
      { scalar: 0, array: [2] },
      { scalar: undefined, array: [1] }
    ]
    

    La

    [
      { scalar: undefined, array: [1] }
    ]
    

    (The top entry has been popped. Its scalar value, 0, has been pushed to the main stack, and its array value, [2], has been discarded.)

    0;a

    [
      { scalar: undefined, array: [1] }
    ]
    

    (The ; command doesn't modify the register, just copies the 0th array entry onto the main stack. Since the array is [1], this puts a 1 on top of the main stack.)