std/collections/stack
std/collections/src/stack.trb
LIFO: Stack, with ArrayStack and the persistent ConsStack as its implementations.
push, pop and peek all work on the top. There is no index: the only way to see an item below the top is to pop
down to it or to iterate the whole stack.
Related
Queue- the FIFO sibling, withenqueue,dequeueandpeekat its two ends.
trait Stack
trait Stack<Item> with Iterate<Item>, Length
LIFO stack. Iterates from top to bottom, which is the order it hands items out in.
The words everybody knows for a stack: push puts an item on top, pop takes the top one off, and peek looks at it
without taking it.
Examples
var pending = Stack.of 1, 2, 3
pending.push 4
print pending.pop()
print pending.peek()
print pending.toList()
Related
fn of
static fn of(...items: Item): Self where Self: From<Iterate<Item>>
Builds a stack from its arguments. The last item ends up on top. Answers Self.
fn push
var fn push(value: Item)
Puts value on top, in place.
fn pop
var fn pop(): Item?
Takes the top item off and answers it, or None if the stack is empty.
fn clear
var fn clear()
Removes every item, in place.
fn compact
var fn compact()
Hands back storage held beyond the length. The default does nothing: a storage without spare room has none.
fn peek
fn peek(): Item?
The item pop would take, without taking it, or None if the stack is empty.
fn count
fn count(): Int
How many items there are. A stack knows its size, so counting it does not walk it.
extend Stack<Item> with From<Iterate<Item>>
extend<Item> Stack<Item> with From<Iterate<Item>>
The factory picks the default implementation: what Stack.of and a pipeline's to<Stack<Item>>() build.
fn from
static fn from(items: Iterate<Item>): Self
extend Stack<Item> with Equals
extend<Item: Equals> Stack<Item> with Equals
Equal when they hold the same items in the same order, which for a stack is from the top down - the order it iterates in, and the only order a reader of one can see.
A collection is Equals when its items are, exactly as a tuple is: values compare structurally, and which
implementation carries the items is nobody's business.
fn equals
fn equals(other: Self): Bool
extend Stack<Item> with Hash
extend<Item: Hash> Stack<Item> with Hash
Order-dependent, like List.hash and unlike Set.hash: two stacks with the same items in a different order are
not equal, so they need not hash alike.
Hash requires Equals, and the Equals implementation above satisfies that: Item: Hash implies Item: Equals.
fn hash
fn hash(): Int
type ArrayStack
type ArrayStack<Item> with Stack<Item>, From<Iterate<Item>>
The only implementation of Stack: a List used from the end. A value, because it consists of values - nothing
had to be done for that.
fn from
static fn from(items: Iterate<Item>): Self
Builds the stack from items, with the last one on top.
fn push
var fn push(value: Item)
Puts value on top, in place.
fn pop
var fn pop(): Item?
Takes the top item off and answers it, or None if empty.
fn peek
fn peek(): Item?
The top item, or None if empty: the end of the list underneath, without walking it.
fn clear
var fn clear()
Removes every item, in place.
fn compact
var fn compact()
Hands back what the list underneath holds beyond its length; see List.compact.
fn length
fn length(): Int
How many items there are.
fn iterate
fn iterate(): Iterator<Item>
A cursor from top to bottom: the reverse of insertion order.
type ConsStackIterator
type ConsStackIterator<Item> with Iterator<Item>
The cursor over a ConsStack: it holds the cell it stands on, which keeps that cell and everything below alive, so
a change to the stack while it is iterated is never seen here.
fn next
var fn next(): Item?
The item of the cell the cursor stands on, or None once it is past the bottom.
type ConsStack
type ConsStack<Item> with Stack<Item>, From<Iterate<Item>>
A persistent stack: a cons list of cells, each holding an item and the stack below it. A copy of a ConsStack is
the reference to its top cell and nothing else, so var rest = stack shares the whole tail, and pushing or popping
on either one builds or drops one cell without touching the other.
Cost
| Operation | Cost |
|---|---|
push, pop, peek, length, clear |
O(1), nothing is copied |
copy (var rest = stack) |
O(1), the tail is shared |
iterate, equals, hash |
O(n), top to bottom |
The price against ArrayStack is one allocation per push and no contiguous storage; the gain is keeping many
versions of one stack at the price of one cell each. It fits backtracking, undo and a parser's context.
Examples
var history = ConsStack.of 1, 2, 3
const saved = history
history.push 4
print history.toList()
print saved.toList()
fn from
static fn from(items: Iterate<Item>): Self
Builds the stack from items, with the last one on top.
fn push
var fn push(value: Item)
Puts value on top, in place: one new cell over the old top, which the stack below shares.
fn pop
var fn pop(): Item?
Takes the top item off and answers it, or None if empty. The cell is dropped; the tail stays where it is.
fn peek
fn peek(): Item?
The top item, or None if empty.
fn clear
var fn clear()
Removes every item, in place. Cells that another copy still holds stay alive for that copy.
fn length
fn length(): Int
How many items there are, without walking the cells.
fn iterate
fn iterate(): Iterator<Item>
A cursor from top to bottom.