{
:empty
:new
:is_empty
:push
:pop
:pop_all
:append
:concat
}

Where

Define (concat queues)
    (LIST.reduce queues empty append)

Where

Define (pop_all queue)
    Unfold queue
        Match (pop queue) {
        | 'nothing 'nil
        | 'just.{item queue} [item & (Fold queue)]
        }

Define (push_all queue items)
    (LIST.reduce items queue push)

Define (append a b)
    Iterate {a b} From {a b}
        Match (pop b) {
        | 'nothing a
        | 'just.{item b} (Continue (push a item) b)
        }

Where

Define (push queue item)
    {
    :incoming [item & queue.incoming]
    :outgoing queue.outgoing
    }

Define (pop queue)
    Unfold queue
        Match queue.outgoing {
        | 'cons.{item outgoing}
            Let queue
                {
                :incoming queue.incoming
                :outgoing
                }
            In
            'just.{item queue}
        | 'nil
            If Pattern 'nil Matches queue.incoming
                'nothing
                (Fold (new (LIST.reverse queue.incoming)))
        }

Where

Define (new init)
    {
    :incoming 'nil
    :outgoing init
    }

Let empty
    {
    :incoming 'nil
    :outgoing 'nil
    }

Define (is_empty queue)
    (And [Pattern 'nil Matches queue.incoming] [Pattern 'nil Matches queue.outgoing])

Where

Open LIST {:Infix &}

Where

Let LIST Package "list"