Skip to content

Instantly share code, notes, and snippets.

@pravic
Created April 29, 2020 15:48
Show Gist options
  • Save pravic/047b74611f2be23ba0704f1c912b2278 to your computer and use it in GitHub Desktop.
Save pravic/047b74611f2be23ba0704f1c912b2278 to your computer and use it in GitHub Desktop.
Extending TIScript collections
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Iterator
// https://fitzgen.github.io/wu.js/
class Iterator
{
this var m = [];
function this(iterable) {
for(var k in iterable) {
this.m.push(k);
}
}
/// Converts an iterable to an Array.
function toArray() {
return this.m;
}
/// Applies the given function to each item in the iterable and yields the result.
function map(fn, thisArg=undefined) {
return this.m.map(fn, thisArg);
}
/// Yield only the items from the iterable for which `fn(item)` is truthy.
function filter(fn, thisArg=undefined) {
return this.m.filter(fn, thisArg);
}
/// Yield the first `n` items from the iterable.
function take(n) {
return new Iterator(this.m.slice(0, n));
}
/// Drop the first `n` items from the iterable.
function drop(n) {
return new Iterator(this.m.slice(n));
}
/// Reduce the iterable from left to right with the binary function `fn`.
/// If `initial` is supplied, start with that value,
/// otherwise use the first value in the iterable.
function reduce(fn, initial=undefined) {
return initial ? this.m.reduce(fn, initial) : this.m.reduce(fn);
}
/// Return `true` if `fn(item)` is truthy for any of the items in the iterable,
/// otherwise return `false`.
function some(fn, thisArg=undefined) {
return this.m.some(fn, thisArg);
}
/// Return `true` if `fn(item)` is truthy for every item in the iterable,
/// otherwise return `false`.
function every(fn, thisArg=undefined) {
return this.m.every(fn, thisArg);
}
/// Return the first item from the iterable for which `fn(item)` is truthy.
/// If no item is found, `undefined` is returned.
function find(fn, thisArg=undefined) {
return this.m.find(fn, thisArg);
}
/// Call `fn(item)` for each item in the iterable.
function forEach(fn) {
for (var v in this.m) {
fn(v);
}
}
//
// wu.js methods:
//
/// For each item in the iterable, yield a pair `[item, index]`.
function enumerate() {
var a = new Array(this.m.length);
for(var i = 0; i < this.m.length; i++) {
a[i] = [i, this.m[i]];
}
return new Iterator(a);
}
/// Return the nth item from the iterable.
/// If `n` is out of bounds, `undefined` is returned.
function nth(n) {
return (n >= 0 && n < this.m.length) ? this.m[n] : undefined;
}
/// Accumulate items from the iterable into arrays of size `n` and yield each array.
function chunk(n) {
var a = new Array(this.m.length);
for(var i = 0; i < this.m.length; i += n) {
a[i] = this.m.slice(i, i + n);
}
return new Iterator(a);
}
}
/** The Map object holds key-value pairs
and remembers the original insertion order of the keys.
Any value (both objects and primitive values) may be used as either a key or a value.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map
*/
class Map
{
this var m = {};
/// Returns the number of key/value pairs in the `Map` object.
get size() { return this.m.length; }
/// The `Map()` constructor creates `Map` objects.
///
/// `args`: An `Array` or other iterable object whose elements are key-value pairs.
/// Each key-value pair is added to the new `Map`.
function this(args=undefined) {
// args: [[key,value]]
if(args) {
// avoid partial construction on exceptions
var m = {};
for(var pair in args) {
m[pair[0]] = pair[1];
}
this.m = m;
}
}
/// Removes all key-value pairs from the Map object.
function clear() {
this.m = {};
}
/// Returns true if an element in the Map object existed and has been removed,
/// or false if the element does not exist.
function delete(key) {
if(!this.has(key)) {
return false;
} else {
delete m[key];
return true;
}
}
/// Returns a new Iterator object that contains an array of `[key, value]`
/// for each element in the Map object in insertion order.
function entries() {
var i = 0;
var a = new Array(this.m.length);
for(var(k,v) in this.m) {
a[i++] = [k,v];
}
return a;
}
/// Returns a new Iterator object that contains the keys
/// for each element in the Map object in insertion order.
function keys() {
return Object.keys(this.m);
}
/// Returns a new Iterator object that contains the **values** for each element
/// in the `Map` object in insertion order.
function values() {
// return this.entries().map(:a: a[1]);
var i = 0;
var a = new Array(this.m.length);
for(var(k,v) in this.m) {
a[i++] = v;
}
return a;
}
/// Returns the value associated to the `key`, or `undefined` if there is none.
function get(key) {
return this.m[key];
}
/// Returns a boolean asserting whether a value has been associated to the `key` in the `Map` object or not.
function has(key) {
return this.m[key] !== undefined;
}
/// Sets the `value` for the `key` in the `Map` object.
/// Returns the `Map` object.
function set(key, value) {
this.m[key] = value;
return this;
}
/// Calls `callbackFn` once for each key-value pair present in the `Map` object,
/// in insertion order.
/// If a `thisArg` parameter is provided to `forEach`,
/// it will be used as the `this` value for each callback.
function forEach(callbackFn, thisArg=undefined) {
for(var(k,v) in this.m) {
callbackFn.apply(thisArg, [k,v, this]);
}
}
}
/** The `Set` object lets you store unique values of any type,
whether primitive values or object references.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set
*/
class Set: Map
{
/// The `Set()` constructor creates `Set` objects.
///
/// `args`: An `Array` or other iterable object whose elements are key-value pairs.
/// Each key-value pair is added to the new `Map`.
function this(args=undefined) {
// args: [key]
if(args) {
// avoid partial construction on exceptions
var m = {};
for(var key in args) {
m[key] = key;
}
this.m = m;
}
}
/// Appends value to the `Set` object. Returns the `Set` object.
function add(value) {
this.m[value] = value;
return this;
}
// override
function set(value) {
throw "Use `Set.add(value)` instead.";
this.m[value] = value;
return this;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment