Last active
February 18, 2020 11:57
-
-
Save MKRhere/f8e1a96e2bc53c6ffbad8c23f44b88af to your computer and use it in GitHub Desktop.
Extend Array with Proxies for fancy features
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const betterArray = xs => new Proxy(xs, { | |
get (xs, key) { | |
if (xs[key] || !xs.length) return xs[key]; | |
const idx = Number(key); | |
if (!idx || idx > 0) return xs[key]; | |
return xs[xs.length + idx]; | |
}, | |
}); | |
const arr = betterArray([ 1, 2, 3, 4, 5 ]); | |
arr[-1]; // 5 | |
arr[-2]; // 4 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const isNumber = x => typeof x === "number"; | |
const isFunc = x => typeof x === "function"; | |
const makeArrayCallable = xs => (...args) => { | |
switch (args.length) { | |
case 0: return callableArray([...xs]); | |
case 1: { | |
const [arg] = args; | |
switch (typeof arg) { | |
case "number": { | |
if (arg >= 0) return xs[arg]; | |
else return xs[xs.length + arg]; | |
} | |
case "function": | |
return callableArray(xs.map(arg)); | |
default: | |
throw new TypeError("Invalid call signature: " + typeof arg); | |
} | |
} | |
case 2: { | |
if (args.every(isNumber)) return callableArray(xs.slice(...args)); | |
const [arg1, arg2] = args; | |
if (isFunc(arg1)) return callableArray(xs.reduce(arg1, arg2)); | |
else throw new TypeError(`Invalid call signature: ${typeof arg1} ${typeof arg2}`); | |
} | |
} | |
} | |
const callableArray = xs => new Proxy(makeArrayCallable(xs), { get (_, key) { return xs[key] } }); | |
const arr = callableArray([ 1, 2, 3, 4, 5 ]); | |
arr(3); // 4 | |
arr(1, 3); // Callable<[ 2, 3, 4 ]> | |
arr(x => x + 1); // Callable<[ 2, 3, 4, 5, 6 ]>; | |
arr((a, b) => a + b, 0); // 15 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment