import * as assert from "@esfx/internal-assert" ; import { Equaler } from "@esfx/equatable" ; import { HashSet } from "@esfx/collections-hashset" ; import { HashMap } from "@esfx/collections-hashmap" ; import { HierarchyIterable } from '@esfx/iter-hierarchy' ; import { identity , isDefined } from '@esfx/fn' ; import { toHashSet , toArray } from './scalars' ; import { flowHierarchy } from './internal/utils' ; class AppendIterable < T > implements Iterable < T > { private _source : Iterable < T > ; private _value : T ; constructor ( source , value ) { this . _source = source ; this . _value = value ; } * [ Symbol . iterator ] ( ) { yield * this . _source ; yield this . _value ; } } param source param value category export function append < TNode , T extends TNode > ( source , value ) ; param source param value category export function append < T > ( source , value ) ; export function append < T > ( source , value ) { assert . mustBeIterableObject ( source , "source" ) ; return flowHierarchy ( new AppendIterable ( source , value ) , source ) ; } class PrependIterable < T > implements Iterable < T > { private _source : Iterable < T > ; private _value : T ; constructor ( value , source ) { this . _value = value ; this . _source = source ; } * [ Symbol . iterator ] ( ) { yield this . _value ; yield * this . _source ; } } param value category export function prepend < TNode , T extends TNode > ( source , value ) ; param value category export function prepend < T > ( source , value ) ; export function prepend < T > ( source , value ) { assert . mustBeIterableObject ( source , "source" ) ; return flowHierarchy ( new PrependIterable ( value , source ) , source ) ; } class ConcatIterable < T > implements Iterable < T > { private _left : Iterable < T > ; private _right : Iterable < T > ; constructor ( left , right ) { this . _left = left ; this . _right = right ; } * [ Symbol . iterator ] ( ) { yield * this . _left ; yield * this . _right ; } } param left param right category export function concat < TNode , T extends TNode > ( left , right ) ; param left param right category export function concat < TNode , T extends TNode > ( left , right ) ; param left param right category export function concat < T > ( left , right ) ; export function concat < T > ( left , right ) { assert . mustBeIterableObject ( left , "left" ) ; assert . mustBeIterableObject ( right , "right" ) ; return flowHierarchy ( new ConcatIterable ( left , right ) , left , right ) ; } class FilterByIterable < T , K > implements Iterable < T > { private _source : Iterable < T > ; private _keySelector : ( element : T ) => K ; private _predicate : ( key : K , offset : number ) => boolean ; private _invert : boolean ; constructor ( source , keySelector , predicate , invert ) { this . _source = source ; this . _keySelector = keySelector ; this . _predicate = predicate ; this . _invert = invert ; } * [ Symbol . iterator ] ( ) { const keySelector = this . _keySelector ; const predicate = this . _predicate ; const inverted = this . _invert ; let offset = 0 ; for ( const element of this . _source ) { let result = predicate ( keySelector ( element ) , offset ++ ) ; if ( inverted ) result = ! result ; if ( result ) { yield element ; } } } } param source param keySelector param predicate category export function filterBy < TNode , T extends TNode , K > ( source , keySelector , predicate ) ; param source param keySelector param predicate category export function filterBy < T , K > ( source , keySelector , predicate ) ; export function filterBy < T , K > ( source , keySelector , predicate ) { assert . mustBeIterableObject ( source , "source" ) ; assert . mustBeFunction ( keySelector , "keySelector" ) ; assert . mustBeFunction ( predicate , "predicate" ) ; return flowHierarchy ( new FilterByIterable ( source , keySelector , predicate , false ) , source ) ; } export { filterBy as whereBy } ; param source param predicate category export function filter < TNode , T extends TNode , U extends T > ( source , predicate ) ; param source param predicate category export function filter < T , U extends T > ( source , predicate ) ; param source param predicate category export function filter < TNode , T extends TNode > ( source , predicate ) ; param source param predicate category export function filter < T > ( source , predicate ) ; export function filter < T > ( source , predicate ) { assert . mustBeIterableObject ( source , "source" ) ; assert . mustBeFunction ( predicate , "predicate" ) ; return filterBy ( source , identity , predicate ) ; } export { filter as where } ; param source category export function filterDefined < TNode , T extends TNode > ( source ) ; param source category export function filterDefined < T > ( source ) ; export function filterDefined < T > ( source ) { return filterBy ( source , identity , isDefined ) as Iterable < NonNullable < T > > ; } export { filterDefined as whereDefined } ; param source param keySelector category export function filterDefinedBy < TNode , T extends TNode , K > ( source , keySelector ) ; param source param keySelector category export function filterDefinedBy < T , K > ( source , keySelector ) ; export function filterDefinedBy < T , K > ( source , keySelector ) { return filterBy ( source , keySelector , isDefined ) ; } export { filterDefinedBy as whereDefinedBy } ; param source param keySelector param predicate category export function filterNotBy < TNode , T extends TNode , K > ( source , keySelector , predicate ) ; param source param keySelector param predicate category export function filterNotBy < T , K > ( source , keySelector , predicate ) ; export function filterNotBy < T , K > ( source , keySelector , predicate ) { assert . mustBeIterableObject ( source , "source" ) ; assert . mustBeFunction ( keySelector , "keySelector" ) ; assert . mustBeFunction ( predicate , "predicate" ) ; return flowHierarchy ( new FilterByIterable ( source , keySelector , predicate , true ) , source ) ; } export { filterNotBy as whereNotBy } ; param source param predicate category export function filterNot < TNode , T extends TNode , U extends T > ( source , predicate ) ; param source param predicate category export function filterNot < T , U extends T > ( source , predicate ) ; param source param predicate category export function filterNot < TNode , T extends TNode > ( source , predicate ) ; param source param predicate category export function filterNot < T > ( source , predicate ) ; export function filterNot < T > ( source , predicate ) { assert . mustBeIterableObject ( source , "source" ) ; assert . mustBeFunction ( predicate , "predicate" ) ; return filterNotBy ( source , identity , predicate ) ; } export { filterNot as whereNot } ; param source param keySelector category export function filterNotDefinedBy < TNode , T extends TNode , K > ( source , keySelector ) ; param source param keySelector category export function filterNotDefinedBy < T , K > ( source , keySelector ) ; export function filterNotDefinedBy < T , K > ( source , keySelector ) { return filterNotBy ( source , keySelector , isDefined ) ; } export { filterNotDefinedBy as whereNotDefinedBy } ; class MapIterable < T , U > implements Iterable < U > { private _source : Iterable < T > ; private _selector : ( element : T , offset : number ) => U ; constructor ( source , selector ) { this . _source = source ; this . _selector = selector ; } * [ Symbol . iterator ] ( ) { const selector = this . _selector ; let offset = 0 ; for ( const element of this . _source ) { yield selector ( element , offset ++ ) ; } } } param source param selector category export function map < T , U > ( source , selector ) { assert . mustBeIterableObject ( source , "source" ) ; assert . mustBeFunction ( selector , "selector" ) ; return new MapIterable ( source , selector ) ; } export { map as select } ; class FlatMapIterable < T , U , R > implements Iterable < U | R > { private _source : Iterable < T > ; private _projection : ( element : T ) => Iterable < U > ; private _resultSelector ? : ( element : T , innerElement : U ) => R ; constructor ( source , projection , resultSelector ? ) { this . _source = source ; this . _projection = projection ; this . _resultSelector = resultSelector ; } * [ Symbol . iterator ] ( ) { const projection = this . _projection ; const resultSelector = this . _resultSelector ; for ( const element of this . _source ) { const inner = projection ( element ) ; if ( resultSelector ) { for ( const innerElement of inner ) { yield resultSelector ( element , innerElement ) ; } } else { yield * inner ; } } } } param source param projection category export function flatMap < T , U > ( source , projection ) ; param source param projection param resultSelector category export function flatMap < T , U , R > ( source , projection , resultSelector ) ; export function flatMap < T , U , R > ( source , projection , resultSelector ? ) { assert . mustBeIterableObject ( source , "source" ) ; assert . mustBeFunction ( projection , "projection" ) ; assert . mustBeFunctionOrUndefined ( resultSelector , "resultSelector" ) ; return new FlatMapIterable ( source , projection , resultSelector ) ; } export { flatMap as selectMany } ; class DropIterable < T > implements Iterable < T > { private _source : Iterable < T > ; private _count : number ; constructor ( source , count ) { this . _source = source ; this . _count = count ; } * [ Symbol . iterator ] ( ) { let remaining = this . _count ; if ( remaining <= 0 ) { yield * this . _source ; } else { for ( const element of this . _source ) { if ( remaining > 0 ) { remaining -- ; } else { yield element ; } } } } } param source param count category export function drop < TNode , T extends TNode > ( source , count ) ; param source param count category export function drop < T > ( source , count ) ; export function drop < T > ( source , count ) { assert . mustBeIterableObject ( source , "source" ) ; assert . mustBePositiveFiniteNumber ( count , "count" ) ; return flowHierarchy ( new DropIterable ( source , count ) , source ) ; } export { drop as skip } ; class DropRightIterable < T > implements Iterable < T > { private _source : Iterable < T > ; private _count : number ; constructor ( source , count ) { this . _source = source ; this . _count = count ; } * [ Symbol . iterator ] ( ) { const pending = [ ] ; const count = this . _count ; if ( count <= 0 ) { yield * this . _source ; } else { for ( const element of this . _source ) { pending . push ( element ) ; if ( pending . length > count ) { yield pending . shift ( ) ! ; } } } } } param source param count category export function dropRight < TNode , T extends TNode > ( source , count ) ; param source param count category export function dropRight < T > ( source , count ) ; export function dropRight < T > ( source , count ) { assert . mustBeIterableObject ( source , "source" ) ; assert . mustBePositiveFiniteNumber ( count , "count" ) ; return flowHierarchy ( new DropRightIterable ( source , count ) , source ) ; } export { dropRight as skipRight } ; class DropWhileIterable < T > implements Iterable < T > { private _source : Iterable < T > ; private _predicate : ( element : T ) => boolean ; private _invert : boolean ; constructor ( source , predicate , invert ) { this . _source = source ; this . _predicate = predicate ; this . _invert = invert ; } * [ Symbol . iterator ] ( ) { const predicate = this . _predicate ; const inverted = this . _invert ; let skipping = true ; for ( const element of this . _source ) { if ( skipping ) { let result = predicate ( element ) ; if ( inverted ) result = ! result ; skipping = ! ! result ; } if ( ! skipping ) { yield element ; } } } } param source param predicate category export function dropWhile < TNode , T extends TNode > ( source , predicate ) ; param source param predicate category export function dropWhile < T > ( source , predicate ) ; export function dropWhile < T > ( source , predicate ) { assert . mustBeIterableObject ( source , "source" ) ; assert . mustBeFunction ( predicate , "predicate" ) ; return flowHierarchy ( new DropWhileIterable ( source , predicate , false ) , source ) ; } export { dropWhile as skipWhile } ; param source param predicate category export function dropUntil < TNode , T extends TNode > ( source , predicate ) ; param source param predicate category export function dropUntil < T > ( source , predicate ) ; export function dropUntil < T > ( source , predicate ) { assert . mustBeIterableObject ( source , "source" ) ; assert . mustBeFunction ( predicate , "predicate" ) ; return flowHierarchy ( new DropWhileIterable ( source , predicate , true ) , source ) ; } export { dropUntil as skipUntil } ; class TakeIterable < T > implements Iterable < T > { private _source : Iterable < T > ; private _count : number ; constructor ( source , count ) { this . _source = source ; this . _count = count ; } * [ Symbol . iterator ] ( ) { let remaining = this . _count ; if ( remaining > 0 ) { for ( const element of this . _source ) { yield element ; if ( -- remaining <= 0 ) { break ; } } } } } param source param count category export function take < TNode , T extends TNode > ( source , count ) ; param source param count category export function take < T > ( source , count ) ; export function take < T > ( source , count ) { assert . mustBeIterableObject ( source , "source" ) ; assert . mustBePositiveFiniteNumber ( count , "count" ) ; return flowHierarchy ( new TakeIterable ( source , count ) , source ) ; } class TakeRightIterable < T > implements Iterable < T > { private _source : Iterable < T > ; private _count : number ; constructor ( source , count ) { this . _source = source ; this . _count = count ; } * [ Symbol . iterator ] ( ) { const count = this . _count ; if ( count <= 0 ) { return ; } else { const pending = [ ] ; for ( const element of this . _source ) { pending . push ( element ) ; if ( pending . length > count ) { pending . shift ( ) ; } } yield * pending ; } } } param source param count category export function takeRight < TNode , T extends TNode > ( source , count ) ; param source param count category export function takeRight < T > ( source , count ) ; export function takeRight < T > ( source , count ) { assert . mustBeIterableObject ( source , "source" ) ; assert . mustBePositiveFiniteNumber ( count , "count" ) ; return flowHierarchy ( new TakeRightIterable ( source , count ) , source ) ; } class TakeWhileIterable < T > implements Iterable < T > { private _source : Iterable < T > ; private _predicate : ( element : T ) => boolean ; private _invert : boolean ; constructor ( source , predicate , invert ) { this . _source = source ; this . _predicate = predicate ; this . _invert = invert ; } * [ Symbol . iterator ] ( ) { const predicate = this . _predicate ; const inverted = this . _invert ; for ( const element of this . _source ) { let result = predicate ( element ) ; if ( inverted ) result = ! result ; if ( ! result ) { break ; } yield element ; } } } param source param predicate category export function takeWhile < TNode , T extends TNode , U extends T > ( source , predicate ) ; param source param predicate category export function takeWhile < T , U extends T > ( source , predicate ) ; param source param predicate category export function takeWhile < TNode , T extends TNode > ( source , predicate ) ; param source param predicate category export function takeWhile < T > ( source , predicate ) ; export function takeWhile < T > ( source , predicate ) { assert . mustBeIterableObject ( source , "source" ) ; assert . mustBeFunction ( predicate , "predicate" ) ; return flowHierarchy ( new TakeWhileIterable ( source , predicate , false ) , source ) ; } param source param predicate category export function takeUntil < TNode , T extends TNode , U extends T > ( source , predicate ) ; param source param predicate category export function takeUntil < T , U extends T > ( source , predicate ) ; param source param predicate category export function takeUntil < TNode , T extends TNode > ( source , predicate ) ; param source param predicate category export function takeUntil < T > ( source , predicate ) ; export function takeUntil < T > ( source , predicate ) { assert . mustBeIterableObject ( source , "source" ) ; assert . mustBeFunction ( predicate , "predicate" ) ; return flowHierarchy ( new TakeWhileIterable ( source , predicate , true ) , source ) ; } class IntersectByIterable < T , K > implements Iterable < T > { private _left : Iterable < T > ; private _right : Iterable < T > ; private _keySelector : ( element : T ) => K ; private _keyEqualer ? : Equaler < K > ; constructor ( left , right , keySelector , keyEqualer ? ) { this . _left = left ; this . _right = right ; this . _keySelector = keySelector ; this . _keyEqualer = keyEqualer ; } * [ Symbol . iterator ] ( ) { const keySelector = this . _keySelector ; const set = toHashSet ( this . _right , keySelector , this . _keyEqualer ) ; if ( set . size <= 0 ) { return ; } for ( const element of this . _left ) { if ( set . delete ( keySelector ( element ) ) ) { yield element ; } } } } param left param right param keySelector param keyEqualer category export function intersectBy < TNode , T extends TNode , K > ( left , right , keySelector , keyEqualer ? ) ; param left param right param keySelector param keyEqualer category export function intersectBy < TNode , T extends TNode , K > ( left , right , keySelector , keyEqualer ? ) ; param left param right param keySelector param keyEqualer category export function intersectBy < T , K > ( left , right , keySelector , keyEqualer ? ) ; export function intersectBy < T , K > ( left , right , keySelector , keyEqualer ? ) { assert . mustBeIterableObject ( left , "left" ) ; assert . mustBeIterableObject ( right , "right" ) ; assert . mustBeFunction ( keySelector , "keySelector" ) ; assert . mustBeTypeOrUndefined ( Equaler . hasInstance , keyEqualer , "keyEqualer" ) ; return flowHierarchy ( new IntersectByIterable ( left , right , keySelector ) , left , right ) ; } param left param right param equaler category export function intersect < TNode , T extends TNode > ( left , right , equaler ? ) ; param left param right param equaler category export function intersect < TNode , T extends TNode > ( left , right , equaler ? ) ; param left param right param equaler category export function intersect < T > ( left , right , equaler ? ) ; export function intersect < T > ( left , right , equaler ? ) { assert . mustBeIterableObject ( left , "left" ) ; assert . mustBeIterableObject ( right , "right" ) ; assert . mustBeTypeOrUndefined ( Equaler . hasInstance , equaler , "equaler" ) ; return intersectBy ( left , right , identity , equaler ) ; } class UnionByIterable < T , K > implements Iterable < T > { private _left : Iterable < T > ; private _right : Iterable < T > ; private _keySelector : ( element : T ) => K ; private _keyEqualer ? : Equaler < K > ; constructor ( left , right , keySelector , keyEqualer ? ) { this . _left = left ; this . _right = right ; this . _keySelector = keySelector ; this . _keyEqualer = keyEqualer ; } * [ Symbol . iterator ] ( ) { const keySelector = this . _keySelector ; const set = new HashSet < K > ( this . _keyEqualer ) ; for ( const element of this . _left ) { if ( set . tryAdd ( keySelector ( element ) ) ) { yield element ; } } for ( const element of this . _right ) { if ( set . tryAdd ( keySelector ( element ) ) ) { yield element ; } } } } param left param right param keySelector param keyEqualer category export function unionBy < TNode , T extends TNode , K > ( left , right , keySelector , keyEqualer ? ) ; param left param right param keySelector param keyEqualer category export function unionBy < TNode , T extends TNode , K > ( left , right , keySelector , keyEqualer ? ) ; param left param right param keySelector param keyEqualer category export function unionBy < T , K > ( left , right , keySelector , keyEqualer ? ) ; export function unionBy < T , K > ( left , right , keySelector , keyEqualer ? ) { assert . mustBeIterableObject ( left , "left" ) ; assert . mustBeIterableObject ( right , "right" ) ; assert . mustBeFunction ( keySelector , "keySelector" ) ; assert . mustBeTypeOrUndefined ( Equaler . hasInstance , keyEqualer , "keyEqualer" ) ; return flowHierarchy ( new UnionByIterable ( left , right , keySelector , keyEqualer ) , left , right ) ; } param left param right param equaler category export function union < TNode , T extends TNode > ( left , right , equaler ? ) ; param left param right param equaler category export function union < TNode , T extends TNode > ( left , right , equaler ? ) ; param left param right param equaler category export function union < T > ( left , right , equaler ? ) ; export function union < T > ( left , right , equaler ? ) { assert . mustBeIterableObject ( left , "left" ) ; assert . mustBeIterableObject ( right , "right" ) ; assert . mustBeTypeOrUndefined ( Equaler . hasInstance , equaler , "equaler" ) ; return unionBy ( left , right , identity , equaler ) ; } class ExceptByIterable < T , K > implements Iterable < T > { private _left : Iterable < T > ; private _right : Iterable < T > ; private _keySelector : ( element : T ) => K ; private _keyEqualer ? : Equaler < K > ; constructor ( left , right , keySelector , keyEqualer ? ) { this . _left = left ; this . _right = right ; this . _keySelector = keySelector ; this . _keyEqualer = keyEqualer ; } * [ Symbol . iterator ] ( ) { const keySelector = this . _keySelector ; const set = toHashSet ( this . _right , keySelector , this . _keyEqualer ! ) ; for ( const element of this . _left ) { if ( set . tryAdd ( keySelector ( element ) ) ) { yield element ; } } } } param left param right param keySelector param keyEqualer category export function exceptBy < TNode , T extends TNode , K > ( left , right , keySelector , keyEqualer ? ) ; param left param right param keySelector param keyEqualer category export function exceptBy < T , K > ( left , right , keySelector , keyEqualer ? ) ; export function exceptBy < T , K > ( left , right , keySelector , keyEqualer ? ) { assert . mustBeIterableObject ( left , "left" ) ; assert . mustBeIterableObject ( right , "right" ) ; assert . mustBeFunction ( keySelector , "keySelector" ) ; assert . mustBeTypeOrUndefined ( Equaler . hasInstance , keyEqualer , "keyEqualer" ) ; return flowHierarchy ( new ExceptByIterable ( left , right , keySelector , keyEqualer ) , left ) ; } export { exceptBy as relativeComplementBy } ; param left param right param equaler category export function except < TNode , T extends TNode > ( left , right , equaler ? ) ; param left param right param equaler category export function except < T > ( left , right , equaler ? ) ; export function except < T > ( left , right , equaler ? ) { assert . mustBeIterableObject ( left , "left" ) ; assert . mustBeIterableObject ( right , "right" ) ; assert . mustBeTypeOrUndefined ( Equaler . hasInstance , equaler , "equaler" ) ; return exceptBy ( left , right , identity , equaler ) ; } export { except as relativeComplement } ; class DistinctByIterable < T , K > implements Iterable < T > { private _source : Iterable < T > ; private _keySelector : ( value : T ) => K ; private _keyEqualer ? : Equaler < K > ; constructor ( source , keySelector , keyEqualer ? ) { this . _source = source ; this . _keySelector = keySelector ; this . _keyEqualer = keyEqualer ; } * [ Symbol . iterator ] ( ) { const set = this . _keyEqualer ? new HashSet < K > ( this . _keyEqualer ) : new Set < K > ( ) ; const keySelector = this . _keySelector ; for ( const element of this . _source ) { const key = keySelector ( element ) ; if ( ! set . has ( key ) ) { set . add ( key ) ; yield element ; } } } } param source param values category export function exclude < TNode , T extends TNode > ( source , ... values ) ; param source param values category export function exclude < T > ( source , ... values ) ; export function exclude < T > ( source , ... values ) { assert . mustBeIterableObject ( source , "left" ) ; return exceptBy ( source , values , identity ) ; } category param source param keySelector param keyEqualer export function distinctBy < TNode , T extends TNode , K > ( source , keySelector , keyEqualer ? ) ; category param source param keySelector param keyEqualer export function distinctBy < T , K > ( source , keySelector , keyEqualer ? ) ; export function distinctBy < T , K > ( source , keySelector , keyEqualer ? ) { assert . mustBeIterableObject ( source , "source" ) ; assert . mustBeFunction ( keySelector , "keySelector" ) ; assert . mustBeTypeOrUndefined ( Equaler . hasInstance , keyEqualer , "keyEqualer" ) ; return flowHierarchy ( new DistinctByIterable ( source , keySelector , keyEqualer ) , source ) ; } category param source param equaler export function distinct < TNode , T extends TNode , K > ( source , keyEqualer ? ) ; category param source param equaler export function distinct < T > ( source , equaler ? ) ; export function distinct < T > ( source , equaler ? ) { assert . mustBeIterableObject ( source , "source" ) ; assert . mustBeTypeOrUndefined ( Equaler . hasInstance , equaler , "equaler" ) ; return distinctBy ( source , identity , equaler ) ; } class DefaultIfEmptyIterable < T > implements Iterable < T > { private _source : Iterable < T > ; private _defaultValue : T ; constructor ( source , defaultValue ) { this . _source = source ; this . _defaultValue = defaultValue ; } * [ Symbol . iterator ] ( ) { const source = this . _source ; const defaultValue = this . _defaultValue ; let hasElements = false ; for ( const value of source ) { hasElements = true ; yield value ; } if ( ! hasElements ) { yield defaultValue ; } } } param source param defaultValue category export function defaultIfEmpty < TNode , T extends TNode > ( source , defaultValue ) ; param source param defaultValue category export function defaultIfEmpty < T > ( source , defaultValue ) ; export function defaultIfEmpty < T > ( source , defaultValue ) { assert . mustBeIterableObject ( source , "source" ) ; return flowHierarchy ( new DefaultIfEmptyIterable ( source , defaultValue ) , source ) ; } class PatchIterable < T > implements Iterable < T > { private _source : Iterable < T > ; private _start : number ; private _skipCount : number ; private _range : Iterable < T > | undefined ; constructor ( source , start , skipCount , range ) { this . _source = source ; this . _start = start ; this . _skipCount = skipCount ; this . _range = range ; } * [ Symbol . iterator ] ( ) { const start = this . _start ; const skipCount = this . _skipCount ; let offset = 0 ; let hasYieldedRange = false ; for ( const value of this . _source ) { if ( offset < start ) { yield value ; offset ++ ; } else if ( offset < start + skipCount ) { offset ++ ; } else { if ( ! hasYieldedRange && this . _range ) { yield * this . _range ; hasYieldedRange = true ; } yield value ; } } if ( ! hasYieldedRange && this . _range ) { yield * this . _range ; } } } param source param start param skipCount param range category export function patch < TNode , T extends TNode > ( source , start , skipCount ? , range ? ) ; param source param start param skipCount param range category export function patch < T > ( source , start , skipCount ? , range ? ) ; export function patch < T > ( source , start , skipCount ? , range ? ) { assert . mustBeIterableObject ( source , "source" ) ; assert . mustBePositiveFiniteNumber ( start , "start" ) ; assert . mustBePositiveFiniteNumber ( skipCount , "skipCount" ) ; assert . mustBeIterableObjectOrUndefined ( range , "range" ) ; return flowHierarchy ( new PatchIterable ( source , start , skipCount , range ) , source ) ; } class ScanIterable < T , U > implements Iterable < T | U > { private _source : Iterable < T > ; private _accumulator : ( current : T | U , element : T , offset : number ) => T | U ; private _isSeeded : boolean ; private _seed : T | U | undefined ; constructor ( source , accumulator , isSeeded , seed ) { this . _source = source ; this . _accumulator = accumulator ; this . _isSeeded = isSeeded ; this . _seed = seed ; } * [ Symbol . iterator ] ( ) { const accumulator = this . _accumulator ; let hasCurrent = this . _isSeeded ; let current = this . _seed ; let offset = 0 ; for ( const value of this . _source ) { if ( ! hasCurrent ) { current = value ; hasCurrent = true ; } else { current = accumulator ( current ! , value , offset ) ; yield current ; } offset ++ ; } } } param source param accumulator category export function scan < T > ( source , accumulator ) ; param source param accumulator param seed category export function scan < T , U > ( source , accumulator , seed ) ; export function scan < T , U > ( source , accumulator , seed ? ) { assert . mustBeIterableObject ( source , "source" ) ; assert . mustBeFunction ( accumulator , "accumulator" ) ; return new ScanIterable < T , U > ( source , accumulator , arguments . length > 2 , seed ! ) ; } class ScanRightIterable < T , U > implements Iterable < T | U > { private _source : Iterable < T > ; private _accumulator : ( current : T | U , element : T , offset : number ) => T | U ; private _isSeeded : boolean ; private _seed : T | U | undefined ; constructor ( source , accumulator , isSeeded , seed ) { this . _source = source ; this . _accumulator = accumulator ; this . _isSeeded = isSeeded ; this . _seed = seed ; } * [ Symbol . iterator ] ( ) { const source = toArray ( this . _source ) ; const accumulator = this . _accumulator ; let hasCurrent = this . _isSeeded ; let current = this . _seed ; for ( let offset = source . length - 1 ; offset >= 0 ; offset -- ) { const value = source [ offset ] ; if ( ! hasCurrent ) { current = value ; hasCurrent = true ; continue ; } current = accumulator ( current ! , value , offset ) ; yield current ; } } } param source param accumulator category export function scanRight < T > ( source , accumulator ) ; param source param accumulator param seed category export function scanRight < T , U > ( source , accumulator , seed ) ; export function scanRight < T , U > ( source , accumulator , seed ? ) { assert . mustBeIterableObject ( source , "source" ) ; assert . mustBeFunction ( accumulator , "accumulator" ) ; return new ScanRightIterable < T , U > ( source , accumulator , arguments . length > 2 , seed ) ; } class SymmetricDifferenceByIterable < T , K > implements Iterable < T > { private _left : Iterable < T > ; private _right : Iterable < T > ; private _keySelector : ( element : T ) => K ; private _keyEqualer ? : Equaler < K > ; constructor ( left , right , keySelector , keyEqualer ? ) { this . _left = left ; this . _right = right ; this . _keySelector = keySelector ; this . _keyEqualer = keyEqualer ; } * [ Symbol . iterator ] ( ) { const keySelector = this . _keySelector ; const rightKeys = new HashSet < K > ( this . _keyEqualer ) ; const right = new HashMap < K , T > ( this . _keyEqualer ) ; for ( const element of this . _right ) { const key = keySelector ( element ) ; if ( rightKeys . tryAdd ( key ) ) { right . set ( key , element ) ; } } const set = new HashSet < K > ( this . _keyEqualer ) ; for ( const element of this . _left ) { const key = keySelector ( element ) ; if ( set . tryAdd ( key ) && ! right . has ( key ) ) { yield element ; } } for ( const [ key , element ] of right ) { if ( set . tryAdd ( key ) ) { yield element ; } } } } param left param right param keySelector param keyEqualer category export function symmetricDifferenceBy < TNode , T extends TNode , K > ( left , right , keySelector , keyEqualer ? ) ; param left param right param keySelector param keyEqualer category export function symmetricDifferenceBy < TNode , T extends TNode , K > ( left , right , keySelector , keyEqualer ? ) ; param left param right param keySelector param keyEqualer category export function symmetricDifferenceBy < T , K > ( left , right , keySelector , keyEqualer ? ) ; export function symmetricDifferenceBy < T , K > ( left , right , keySelector , keyEqualer ? ) { assert . mustBeIterableObject ( left , "left" ) ; assert . mustBeIterableObject ( right , "right" ) ; assert . mustBeFunction ( keySelector , "keySelector" ) ; assert . mustBeTypeOrUndefined ( Equaler . hasInstance , keyEqualer , "keyEqualer" ) ; return flowHierarchy ( new SymmetricDifferenceByIterable ( left , right , keySelector , keyEqualer ) , left , right ) ; } param left param right param equaler category export function symmetricDifference < TNode , T extends TNode > ( left , right , equaler ? ) ; param left param right param equaler category export function symmetricDifference < TNode , T extends TNode > ( left , right , equaler ? ) ; param left param right param equaler category export function symmetricDifference < T > ( left , right , equaler ? ) ; export function symmetricDifference < T > ( left , right , equaler ? ) { assert . mustBeIterableObject ( left , "left" ) ; assert . mustBeIterableObject ( right , "right" ) ; assert . mustBeTypeOrUndefined ( Equaler . hasInstance , equaler , "equaler" ) ; return symmetricDifferenceBy ( left , right , identity , equaler ) ; } class TapIterable < T > implements Iterable < T > { private _source : Iterable < T > ; private _callback : ( element : T , offset : number ) => void ; constructor ( source , callback ) { this . _source = source ; this . _callback = callback ; } * [ Symbol . iterator ] ( ) { const source = this . _source ; const callback = this . _callback ; let offset = 0 ; for ( const element of source ) { callback ( element , offset ++ ) ; yield element ; } } } param source param callback category export function tap < TNode , T extends TNode > ( source , callback ) ; param source param callback category export function tap < T > ( source , callback ) ; export function tap < T > ( source , callback ) { assert . mustBeIterableObject ( source , "source" ) ; assert . mustBeFunction ( callback , "callback" ) ; return flowHierarchy ( new TapIterable ( source , callback ) , source ) ; } class MaterializeIterable < T > implements Iterable < T > { private _source : readonly T [ ] ; constructor ( source ) { this . _source = [ ... source ] ; } [ Symbol . iterator ] ( ) { return this . _source [ Symbol . iterator ] ( ) ; } } category export function materialize < TNode , T extends TNode > ( source ) ; export function materialize < T > ( source ) ; export function materialize < T > ( source ) { assert . mustBeIterableObject ( source , "source" ) ; return flowHierarchy ( new MaterializeIterable ( source ) , source ) ; }