scontainers
Version:
A container/collection/iterator library for JavaScript, comfortable to use, performant and versatile.
142 lines (107 loc) • 2.77 kB
JavaScript
;
function _implSymbol(target, sym, value) {
Object.defineProperty(target, sym, {
value,
configurable: true
});
return target[sym];
}
function _getSymbol(targetSymName, ...traitSets) {
let symbol;
traitSets.forEach(traitSet => {
const sym = traitSet[targetSymName];
if (typeof sym === 'symbol') {
if (!!symbol && symbol !== sym) {
throw new Error(`Symbol ${targetSymName} offered by multiple trait sets.`);
}
symbol = sym;
}
});
if (!symbol) {
throw new Error(`No trait set is providing symbol ${targetSymName}.`);
}
return symbol;
}
function _testTraitSet(traitSet) {
if (!traitSet || typeof traitSet === 'boolean' || typeof traitSet === 'number' || typeof traitSet === 'string') {
throw new Error(`${traitSet} cannot be used as a trait set.`);
}
}
const {
traits,
id
} = require('../utils.js');
_testTraitSet(traits.utils);
_testTraitSet(traits.scontainers);
_testTraitSet(traits.semantics);
const _describeScontainer = _getSymbol("describeScontainer", traits.utils, traits.scontainers, traits.semantics);
const _implCoreGenerators = _getSymbol("implCoreGenerators", traits.utils, traits.scontainers, traits.semantics);
const _plus = _getSymbol("plus", traits.utils, traits.scontainers, traits.semantics);
const _minus = _getSymbol("minus", traits.utils, traits.scontainers, traits.semantics);
const _implCoreTraits = _getSymbol("implCoreTraits", traits.utils, traits.scontainers, traits.semantics);
class Range {
constructor(begin, end) {
if (end !== undefined) {
if (begin !== undefined) {
this.begin = begin;
}
this.end = end;
} else if (begin !== undefined) {
this.end = begin;
this.begin = 0;
} else {
this.end = Infinity;
this.begin = 0;
}
}
len() {
return this.end - this.begin;
}
toString() {
return `${this.begin}…${this.end}`;
}
}
Range[_describeScontainer]({
argKeys: [id`begin`, id`end`]
});
Range[_implCoreGenerators]({
nToKey(n) {
return n[_plus](this.args.begin);
},
keyToN(key) {
return key[_minus](this.args.begin);
},
nthUnchecked(n) {
return n[_plus](this.args.begin);
},
// add: nope
len() {
const {
begin,
end
} = this.args;
return end[_minus](begin);
}
});
Range[_implCoreTraits]({
nthUnchecked(n) {
return this.begin + n;
},
keyToN(key) {
return key - this.begin;
},
nToKey(n) {
return n + this.begin;
},
len() {
return this.len();
},
// optimizations
sum() {
return (this.begin + this.end - 1) * this.len() / 2;
},
slice(begin, end) {
return new Range(this.begin + begin, this.begin + end);
}
});
module.exports = Range;