M
Michael Press
Willem said:Keith Thompson wrote:
) Willem, you have a point. There is no One True Way to define the
) set of operations available for a stack.
Thank you, that was exactly the point I was trying to make.
) On the other hand, some operations make sense and some do not.
)
) I don't believe you've demonstrated that a push() operation that
) extends the stack without storing a value in the top element makes
) any sense.
I never tried to demonstrate it. I just got very annoyed by people
claiming that thier views on stacks are the One True Way, and using
bad logic to argue their points.
Nobody tried to argue *why* it maked sense to have the stack operations
work the way they say they should work. They just *asserted* it.
) Under what circumstances would you want to use such an operation?
) As far as I can see, extending the stack is *always* immediately
) followed by storing a value in the new top element. How would it
) be advantageous to separate those operations?
The most obvious one would be is your application needs a way to replace
or change the top value of a stack. Then a push() which sets the value
also would be redundant(*).
Another one would be if the 'value' on the stack is actually a large
entity, such as a struct, and passing the whole struct would be
a performance issue, especially if you're only using a part of it.
This is especially true if the stack is a way of being able to step
back to a previous saved state.
As a real-life example of that, look at a postscript interpreter, which
keeps a stack of graphics contexts. Or a chess playing program, which
needs to save the current state of the board to be able to try different
moves.
Another example would be when growing the stack would be a very costly
operation, and putting items in slots very cheap. In that case, it would
be very advantageous if you could grow the stack by a large step, and
then insert all the items one by one.
One could also imagine having a stack that stores char values, but using it
for different-sized objects/blobs.
Oh, and as a very real-life example, look at the way that a C compiler uses
stack frames: it allocates a whole frame in one go, and then uses the space
it created for different variables, objects, et cetera.
A stack frame is best conceptualized as a single push. The
details are not a stack operation at all. The details are
memory allocation and initialization. _In_ the stack frame is
data that tells the supervising process how to get the value of
the stack pointer after this stack frame is released---how to
pop the stack.