import { isNullOrUndefined } from "../utility" ; /**
 * `List` is a sequence container that supports constant-time insertion and
 * removal from the front and back of the container. It does not support
 * random access, meaning there is no indexing operator. It is implemented as a
 * doubly-linked list.
 */ export class List < T > implements Iterable < T > { private head ? : Node < T > = undefined ; private tail ? : Node < T > = undefined ; private size : number = 0 ; returns public constructor ( ) { } returns public get length ( ) : number { return this . size ; } param init returns public static from < T > ( init ) { const list = new List < T > ( ) ; for ( const elem of init ) { list . push ( elem ) ; } return list ; } param elements returns see from public static of < T > ( ... elements ) { return List . from ( elements ) ; } param elements returns public push ( ... elements ) { for ( const element of elements ) { this . pushOne ( element ) ; } return this . size ; } returns public pop ( ) { if ( isNullOrUndefined ( this . tail ) ) { return undefined ; } -- this . size ; const popped = this . tail . element ; this . tail = this . tail . previous ; if ( ! isNullOrUndefined ( this . tail ) ) { this . tail . next = undefined ; } else { this . head = undefined ; } return popped ; } returns public shift ( ) { if ( isNullOrUndefined ( this . head ) ) { return undefined ; } -- this . size ; const shifted = this . head . element ; this . head = this . head . next ; if ( ! isNullOrUndefined ( this . head ) ) { this . head . previous = undefined ; } else { this . tail = undefined ; } return shifted ; } param elements returns public unshift ( ... elements ) { for ( let i = elements . length - 1 ; i >= 0 ; -- i ) { this . unshiftOne ( elements [ i ] ) ; } return this . size ; } returns public * [ Symbol . iterator ] ( ) { let current = this . head ; while ( ! isNullOrUndefined ( current ) ) { const toYield = current . element ; current = current . next ; yield toYield ; } return ; } param element returns private pushOne ( element ) { ++ this . size ; const toPush = { element , next : undefined , previous : this . tail , } ; if ( isNullOrUndefined ( this . tail ) ) { this . head = toPush ; this . tail = toPush ; } else { this . tail . next = toPush ; this . tail = toPush ; } return this . size ; } param element returns private unshiftOne ( element ) { ++ this . size ; const toUnshift = { element , next : this . head , previous : undefined , } ; if ( isNullOrUndefined ( this . head ) ) { this . head = toUnshift ; this . tail = toUnshift ; } else { this . head . previous = toUnshift ; this . head = toUnshift ; } return this . size ; } } /**
 * Doubly-linked list node.
 */ interface Node < T > { element : T ; next ? : Node < T > ; previous ? : Node < T > ; }