Iterable+ext
extends iterables with custom methods.
Last updated
Was this helpful?
extends iterables with custom methods.
Last updated
Was this helpful?
JSโฉ iteration โฉ iterable โฉ extension
extends iterables with methods such as filter
, map
, take
, ... etc.
// โญ๏ธ check if iterable
array.isIterable, // true
object.isIterable, // false
(3).isIterable, // false
// โญ๏ธ extended methods
'xyz'.forEach(x => log(x)); // x, y, z
'abc'.map(x=>x+2).array, // [ 'a2', 'b2', 'c2' ]
'abcdefg'.take(4).array, // [ 'a', 'b', 'c', 'd' ]
'abcd'.some(x => x > 'm'), // false
// โญ๏ธ (closed) range
range(0, 3).map(x => x * 2).array, // [0, 2, 4, 6]
range(0, 10).every(x => x < 10), // false
replit โฉ Iterable.js
// 2023.01.21 - 18:42 (?) first recorded, rename Iterable+ext.js
// ----------------------------------------
//
// โญ Iterable + ext
// ----------------------------------------
// - range()
// ----------------------------------------
// ๐ธ .isIterable -> boolean
// ๐ธ .array -> array
// ----------------------------------------
// ๐น .filter() -> it
// ๐น .map() -> it
// ๐น .take() -> it
// ๐น .reduce() -> any
// ----------------------------------------
// ๐น .every() -> boolean
// ๐น .some() -> boolean
// ๐น .forEach() -> void
// ๐น .toArray() -> array
//
Object.defineProperties(Object.prototype, {
// ๐ธ obj.isIterable
isIterable: {
get() {
return typeof this[Symbol.iterator] === 'function';
}
},
// ๐ธ it.array
array: {
get: function() {
this._checkIterable();
return [...this];
}
},
// obj._iterableValues
_checkIterable: {
value: function() {
// throw error if not iterable
if (!this.isIterable) {
throw new TypeError(`object is not iterable!`);
}
}
},
// ๐น it.map(f)
map: {
value: function(f) {
this._checkIterable();
const values = this;
// return a mapped iterable
return {
// make iterabor (by using generator function)
*[Symbol.iterator]() {
for (const val of values) yield f(val);
}
}
}
},
// ๐น it.filter(f)
filter: {
value: function(condition) {
this._checkIterable();
const values = this;
// return a filtered iterable
return {
// make iterabor (by using generator function)
*[Symbol.iterator]() {
for (const val of values) if (condition(val)) yield val;
}
}
}
},
// ๐น it.take(n)
take: {
value: function(n) {
this._checkIterable();
const values = this;
// return a partial iterable
return {
// make iterabor (by using generator function)
*[Symbol.iterator]() {
for (const val of values) {
if (n > 0) {
n -= 1;
yield val;
} else { return }
}
}
}
}
},
// ๐น it.forEach(f)
forEach: {
value: function(f) {
this._checkIterable();
for (const val of this) f(val);
}
},
// ๐น it.reduce()
reduce: {
value: function(...args) {
this._checkIterable();
return [...this].reduce(...args);
}
},
// ๐น it.toArray()
toArray: {
value: function() {
this._checkIterable();
return [...this];
}
},
// ๐น it.every(condition)
every: {
value: function(condition) {
this._checkIterable();
for (const val of this) if (!condition(val)) return false;
return true;
}
},
// ๐น it.some(condition)
some: {
value: function(condition) {
this._checkIterable();
for (const val of this) if (condition(val)) return true;
return false;
}
},
});
// โญ๏ธ closed range: [start, end]
function range(start, end, step = start < end ? 1 : -1) {
function isInRange(i) {
return (step > 0) ? (start <= i && i <= end) : (end <= i && i <= start);
}
// return an iterable
return {
*[Symbol.iterator]() {
for (let i = start; isInRange(i) ; i += step) {
yield i;
}
}
}
}
// export
// module.exports = { range };
export { range };
replit โฉ index.js
'use strict'; // โญ toggle sloppy/strict mode
const { log } = console;
// โญ import
const { logError } = require('./helpers/debug.js'); // functions for debugging
const { isObject } = require('./ext/Object_ext.js'); // extend Object.prototype
const { range } = require('./ext/Iterable.js'); // iterable methods
// ---------------------------------------------------------------------------
const array = [1, 2, 3];
const string = "Hello, world!";
const map = new Map();
const set = new Set();
const object = {};
'xyz'.forEach(x => log(x)); // x, y, z
// โ
log expressions that never throw
// ---------------------------------------------------------------------------
;[
array.isIterable, // โ
string.isIterable, // โ
map.isIterable, // โ
set.isIterable, // โ
object.isIterable, // โจ
(3).isIterable, // โจ
range(0, 10).every(x => x < 10), // โจ
'abcd'.some(x => x > 'm'), // โจ
].forEach(x => log(x));
// โ
list iterables -> array
[
range(1, 3), // [ 1, 2, 3 ]
range(3, -2), // [ 3, 2, 1, 0, -1, -2 ]
range(1, 3, 0.5), // [ 1, 1.5, 2, 2.5, 3 ]
range(0, 10).take(4), // [0, 1, 2, 3]
range(0, 3).map(x => x * 2), // [0, 2, 4, 6]
'abcd', // [ 'a', 'b', 'c', 'd' ]
'abc'.map(x => x + 1), // [ 'a1', 'b1', 'c1' ]
'abcdefg'.filter(x => x < 'd'), // [ 'a', 'b', 'c' ]
'abcdefg'.take(4), // [ 'a', 'b', 'c', 'd' ]
].forEach(x => log(x.array));
// โ log expressios that may throw
// ---------------------------------------------------------------------------
[
`object.map(x => x)`, // โ TypeError: 'object' not iterable!
].forEach(exprStr => {
try { log(eval(exprStr)) } catch (e) { logError(e) }
});
range() - half-open range of numbers. (iterable)
obj.isIterable - check if an object is iterable.
Iterator extension (deprecated)
Canvas+ext - use range
.
0: (?)
// โญ extending iterables (`it` for short)
// ----------------------------------------
// ๐ธ .isIterable -> boolean
// ๐ธ .array -> array
// ๐น .filter() -> it
// ๐น .map() -> it
// ๐น .take() -> it
// ๐น .reduce() -> any
//
// ๐น .every() -> boolean
// ๐น .some() -> boolean
// ๐น .forEach() -> void
// ๐น .toArray() -> array
// โญ helper functions
// ----------------------------------------
// โข ๐น range(start, end, step): iterable
// Iterable (protocol)
Object.defineProperties(Object.prototype, {
// ๐ธ obj.isIterable
isIterable: {
get() {
return typeof this[Symbol.iterator] === 'function';
}
},
// ๐ธ it.array
array: {
get: function() {
this._checkIterable();
return [...this];
}
},
// obj._iterableValues
_checkIterable: {
value: function() {
// throw error if not iterable
if (!this.isIterable) {
throw new TypeError(`object is not iterable!`);
}
}
},
// ๐น it.map(f)
map: {
value: function(f) {
this._checkIterable();
const values = this;
// return a mapped iterable
return {
// make iterabor (by using generator function)
*[Symbol.iterator]() {
for (const val of values) yield f(val);
}
}
}
},
// ๐น it.filter(f)
filter: {
value: function(condition) {
this._checkIterable();
const values = this;
// return a filtered iterable
return {
// make iterabor (by using generator function)
*[Symbol.iterator]() {
for (const val of values) if (condition(val)) yield val;
}
}
}
},
// ๐น it.take(n)
take: {
value: function(n) {
this._checkIterable();
const values = this;
// return a partial iterable
return {
// make iterabor (by using generator function)
*[Symbol.iterator]() {
for (const val of values) {
if (n > 0) {
n -= 1;
yield val;
} else { return }
}
}
}
}
},
// ๐น it.forEach(f)
forEach: {
value: function(f) {
this._checkIterable();
for (const val of this) f(val);
}
},
// ๐น it.reduce()
reduce: {
value: function(...args) {
this._checkIterable();
return [...this].reduce(...args);
}
},
// ๐น it.toArray()
toArray: {
value: function() {
this._checkIterable();
return [...this];
}
},
// ๐น it.every(condition)
every: {
value: function(condition) {
this._checkIterable();
for (const val of this) if (!condition(val)) return false;
return true;
}
},
// ๐น it.some(condition)
some: {
value: function(condition) {
this._checkIterable();
for (const val of this) if (condition(val)) return true;
return false;
}
},
});
// โญ๏ธ closed range: [start, end]
function range(start, end, step = start < end ? 1 : -1) {
function isInRange(i) {
return (step > 0) ? (start <= i && i <= end) : (end <= i && i <= start);
}
// return an iterable
return {
*[Symbol.iterator]() {
for (let i = start; isInRange(i) ; i += step) {
yield i;
}
}
}
}
// export
module.exports = { range };