de.caff.generics

## Interface FStack<T>

- Type Parameters:
    `T` - element type
  All Superinterfaces:
    java.lang.Iterable<T>
  All Known Implementing Classes:
    CopierFStackImpl, CopierFStackImpl.Empty, FStackImpl

      public interface FStack<T>
      extends java.lang.Iterable<T>

  A functional stack.

  This implements a functional stack which itself is immutable. Stack operations are defined in a way that most of the stack is reused in copies of it. That means that when you change ony element on the stack it will change in all copies of this stack and the stacks created from it via `pop()` and `push(Object)`. If you don't change the elements (preferable they are immutable, too) this stack is perfectly thread-safe.

  The only way to use this stack in multi-threaded environments for potentially changeable objects is by making copies of each element when it is pushed and when it is requested via `top()`. This stack can be used this way by providing a copier or using `copiable` elements. See item list below for how this is done.

  This stack also extends `Iterable`. The returned `Iterator` will traverse the stack from top to bottom.

  Creating a stack from scratch is done by

  - `empty()` which will return an empty stack with the required type. Internally this is always the same object, but the Java type system takes care of handling this correctly.
  - `empty(Copier)` which will return an empty copying stack with the required type. This is the only way to use a stack of mutable elements securely in multi-threaded environments.
  - `emptyCopyable()` which will return an empty copying stack with the required `copyable` type. This is the way to use copyable elements securely in multi-threaded environments.
  - `from(Iterable)` which will return a stack with the elements from the given iterable. Because of the lifo characteristics of stacks popping the elements one by one (or iterating over the stack) will present the elements in the reverse order compared to the iterable.
  - `from(Copier, Iterable)` which will return a stack with the copied elements from the given iterable. Because of the lifo characteristics of stacks popping the elements one by one (or iterating over the stack) will present the elements in the reverse order compared to the iterable. This is a way to use a preinitialized stack of mutable elements securely in multi-threaded environments.
  - `fromCopyable(Iterable)` which will return a stack with the copied elements from the given iterable. Because of the lifo characteristics of stacks popping the elements one by one (or iterating over the stack) will present the elements in the reverse order compared to the iterable. This is a way to use a preinitialized stack of `copyable` mutable elements securely in multi-threaded environments.
  - `reverseFrom(Iterable)` which will return a stack with the elements from the given iterable, but take care that they are pushed in reverse order. Therefore popping the elements one by one (or iterating over the stack) will present the same order of elements that the iterable provided.
  - `reverseFrom(Copier, Iterable)` which will return a stack with the copied elements from the given iterable but take care that they are pushed in reverse order. Therefore popping the elements one by one (or iterating over the stack) will present the same order of elements that the iterable provided. This is a way to use a preinitialized stack of mutable elements securely in multi-threaded environments.
  - `reverseFromCopyable(Iterable)` which will return a stack with the copied elements from the given iterable but take care that they are pushed in reverse order. Therefore popping the elements one by one (or iterating over the stack) will present the same order of elements that the iterable provided. This is a way to use a preinitialized stack of `copyable` mutable elements securely in multi-threaded environments.
  Since:
    September 22, 2020
  Author:
    Rammi

- - ### Method Summary

    All Methods Static Methods Instance Methods Abstract Methods Default Methods
    Modifier and Type | Method and Description
    --- | ---
    `static <E> FStack<E>` | `empty()` Get an empty stack.
    `static <E> FStack<E>` | `empty(Copier<E> copier)` Get an empty stack which uses a copier to allow using changeable elements securely in multi-threaded environments.
    `static <E extends Copyable<E>> FStack<E>` | `emptyCopyable()` Get an empty stack which can be used securely in multi-threaded environemnts because it copies it copyable elements.
    `static <E> FStack<E>` | `from(Copier<E> copier, java.lang.Iterable<E> iterable)` Create a stack from pushing copies of all elements of an iterable to this stack.
    `static <E> FStack<E>` | `from(java.lang.Iterable<E> iterable)` Create a stack from pushing all elements of an iterable to this stack.
    `static <E extends Copyable<E>> FStack<E>` | `fromCopyable(java.lang.Iterable<E> iterable)` Create a stack from pushing copies of all elements of an iterable to this stack.
    `boolean` | `isEmpty()` Is this stack empty?
    `default java.util.Iterator<T>` | `iterator()`
    `FStack<T>` | `pop()` Pop the stack.
    `FStack<T>` | `push(T elem)` Push an element to the top of the stack.
    `default FStack<T>` | `pushAll(java.lang.Iterable<? extends T> elements)` Get a stack which is the result of pushing all elements to the top of this stack.
    `static <E> FStack<E>` | `reverseFrom(Copier<E> copier, java.lang.Iterable<E> iterable)` Create a stack from pushing copies of all elements of an iterable to this stack.
    `static <E> FStack<E>` | `reverseFrom(java.lang.Iterable<E> iterable)` Create a stack from pushing all elements of an iterable to this stack.
    `static <E extends Copyable<E>> FStack<E>` | `reverseFromCopyable(java.lang.Iterable<E> iterable)` Create a stack from pushing copies of all elements of an iterable to this stack.
    `default FStack<T>` | `reversePushAll(java.lang.Iterable<? extends T> elements)` Get a stack which is the result of pushing all elements to the top of this stack.
    `int` | `size()` Get the size of this stack.
    `T` | `top()` Get the top element of the stack.

    - ### Methods inherited from interface java.lang.Iterable

      `forEach, spliterator`

- - ### Method Detail

    - #### top

          T top()

      Get the top element of the stack.
      Returns:
        top element
      Throws:
        `java.util.EmptyStackException` - if this stack is `empty`

    - #### push

          @NotNull
          FStack<T> push(T elem)

      Push an element to the top of the stack. This will not change this stack but return a new stack with the given element at the `top()`.
      Parameters:
        `elem` - element to push to the stack
      Returns:
        new stack with `elem` at the top and the same elements as this stack below it

    - #### pushAll

          @NotNull
          default FStack<T> pushAll(@NotNull
                                             java.lang.Iterable<? extends T> elements)

      Get a stack which is the result of pushing all elements to the top of this stack. This will not change this stack but return a new stack with the given elements at the `top()`.

      Because of the lifo characteristics of stacks the order of elements when popped from the returned stack is the reverse of the order of the iterable. If you prefer otherwise use `reversePushAll(Iterable)`.

      Parameters:
        `elements` - elements to push to this stack
      Returns:
        stack with the elements pushed to its top

    - #### reversePushAll

          @NotNull
          default FStack<T> reversePushAll(@NotNull
                                                    java.lang.Iterable<? extends T> elements)

      Get a stack which is the result of pushing all elements to the top of this stack. This will not change this stack but return a new stack with the given elements at the `top()`.

      This method reverses the order of pushing so if you pop the elements from the returned stack they will have the same order as they had in the iterable's sequence. If you prefer otherwise use `pushAll(Iterable)`.

      Parameters:
        `elements` - elements to push to this stack
      Returns:
        stack with the elements pushed to its top

    - #### pop

          @NotNull
          FStack<T> pop()

      Pop the stack. This will remove the top-most element from the stack and return a new stack without it.
      Returns:
        a new stack without the top element of this stack
      Throws:
        `java.util.EmptyStackException` - if this stack is `empty`

    - #### isEmpty

          boolean isEmpty()

      Is this stack empty? An empty stack does not have a top element, therefore `top()` and `pop()` are not allowed and will result in `EmptyStackException`s
      Returns:

    - #### size

          int size()

      Get the size of this stack. This is an expensive operation!
      Returns:
        number of elements in this stack

    - #### iterator

          @NotNull
          default java.util.Iterator<T> iterator()

      Specified by:
        `iterator` in interface `java.lang.Iterable<T>`

    - #### empty

          @NotNull
          static <E> FStack<E> empty()

      Get an empty stack. This stack will only behave well if elements are either immutable or if they are never changed. See
      Type Parameters:
        `E` - element type of the returned stack
      Returns:
        empty stack

    - #### empty

          @NotNull
          static <E> FStack<E> empty(@NotNull
                                              Copier<E> copier)

      Get an empty stack which uses a copier to allow using changeable elements securely in multi-threaded environments.

      The returned functional stack is itself immutable, and will copy elements when pushed and requested.

      Type Parameters:
        `E` - element type of returned stack
      Parameters:
        `copier` - copier applied on incoming and outgoing elements
      Returns:
        functional stack which decouples the elements by copying them when necessary
      See Also:
        `empty()`, `emptyCopyable()`

    - #### emptyCopyable

          @NotNull
          static <E extends Copyable<E>> FStack<E> emptyCopyable()

      Get an empty stack which can be used securely in multi-threaded environemnts because it copies it copyable elements.
      Type Parameters:
        `E` - copyable element type
      Returns:
        functional stack which decouples its elements by copying them when necessary
      See Also:
        `empty()`, `empty(Copier)`

    - #### from

          @NotNull
          static <E> FStack<E> from(@NotNull
                                             java.lang.Iterable<E> iterable)

      Create a stack from pushing all elements of an iterable to this stack. Because of the lifo characteristics of stacks iterating over the returned stack will be done in the reverse order of the given `iterable`. If you prefer this the other way round use `reverseFrom(Iterable)`.
      Type Parameters:
        `E` - element type of the iterable and the returned stack
      Parameters:
        `iterable` - iterable to push onto the stack
      Returns:
        stack initialized from the given iterable
      See Also:
        `from(Copier, Iterable)`, `fromCopyable(Iterable)`

    - #### from

          @NotNull
          static <E> FStack<E> from(@NotNull
                                             Copier<E> copier,
                                             @NotNull
                                             java.lang.Iterable<E> iterable)

      Create a stack from pushing copies of all elements of an iterable to this stack. Because of the lifo characteristics of stacks iterating over the returned stack will be done in the reverse order of the given `iterable`. If you prefer this the other way round use `reverseFrom(Copier, Iterable)`.
      Type Parameters:
        `E` - element type of the iterable and the returned stack
      Parameters:
        `copier` - copier applied to all incoming and outgoing elements
        `iterable` - iterable to push onto the stack
      Returns:
        stack initialized from the given iterable
      See Also:
        `from(Iterable)`, `from(Copier, Iterable)`

    - #### fromCopyable

          @NotNull
          static <E extends Copyable<E>> FStack<E> fromCopyable(@NotNull
                                                                         java.lang.Iterable<E> iterable)

      Create a stack from pushing copies of all elements of an iterable to this stack. Because of the lifo characteristics of stacks iterating over the returned stack will be done in the reverse order of the given `iterable`. If you prefer this the other way round use `reverseFromCopyable(Iterable)`.
      Type Parameters:
        `E` - copyable element type of the iterable and the returned stack
      Parameters:
        `iterable` - iterable to push onto the stack
      Returns:
        stack initialized from the given iterable
      See Also:
        `from(Iterable)`, `from(Copier, Iterable)`

    - #### reverseFrom

          @NotNull
          static <E> FStack<E> reverseFrom(@NotNull
                                                    java.lang.Iterable<E> iterable)

      Create a stack from pushing all elements of an iterable to this stack. This method basically pushes the elements in the reverse order, so that iterating over the stack will present the same sequence of elements the `iterable` presents. If you prefer this the other way round use `from(Iterable)`.
      Type Parameters:
        `E` - element type of the iterable and the returned stack
      Parameters:
        `iterable` - iterable to push onto the stack
      Returns:
        stack initialized from the given iterable
      See Also:
        `reverseFrom(Copier, Iterable)`, `reverseFromCopyable(Iterable)`

    - #### reverseFrom

          @NotNull
          static <E> FStack<E> reverseFrom(@NotNull
                                                    Copier<E> copier,
                                                    @NotNull
                                                    java.lang.Iterable<E> iterable)

      Create a stack from pushing copies of all elements of an iterable to this stack. This method basically pushes the elements in the reverse order, so that iterating over the stack will present the same sequence of elements the `iterable` presents. If you prefer this the other way round use `from(Copier, Iterable)`.
      Type Parameters:
        `E` - element type of the iterable and the returned stack
      Parameters:
        `copier` - copier applied to all incoming and outgoing stack elements
        `iterable` - iterable to push onto the stack
      Returns:
        stack initialized from the given iterable
      See Also:
        `reverseFrom(Iterable)`, `reverseFromCopyable(Iterable)`

    - #### reverseFromCopyable

          @NotNull
          static <E extends Copyable<E>> FStack<E> reverseFromCopyable(@NotNull
                                                                                java.lang.Iterable<E> iterable)

      Create a stack from pushing copies of all elements of an iterable to this stack. This method basically pushes the elements in the reverse order, so that iterating over the stack will present the same sequence of elements the `iterable` presents. If you prefer this the other way round use `fromCopyable(Iterable)`.
      Type Parameters:
        `E` - copyable element type of the iterable and the returned stack
      Parameters:
        `iterable` - iterable to push onto the stack
      Returns:
        stack initialized from the given iterable
      See Also:
        `reverseFrom(Iterable)`, `reverseFromCopyable(Iterable)`