Skip to content

Instantly share code, notes, and snippets.

@sebinsua
Last active August 15, 2022 20:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sebinsua/74af82c3489579e5a0d66322ae360236 to your computer and use it in GitHub Desktop.
Save sebinsua/74af82c3489579e5a0d66322ae360236 to your computer and use it in GitHub Desktop.
function createGenerator(maybeIterable) {
const isGenerator = (maybeGenerator) =>
"next" in maybeGenerator &&
typeof maybeGenerator["next"] === "function" &&
"throw" in maybeGenerator &&
typeof maybeGenerator["throw"] === "function" &&
"return" in maybeGenerator &&
typeof maybeGenerator["return"] === "function";
function* generatorFrom(maybeIterable) {
const iterable =
typeof maybeIterable === "function"
? maybeIterable()
: Array.isArray(maybeIterable)
? maybeIterable
: [maybeIterable];
yield* iterable;
}
return isGenerator(maybeIterable)
? maybeIterable
: generatorFrom(maybeIterable);
}
export function* iterate(op, start) {
let last = start;
while (true) {
yield last;
last = op(last);
}
}
export function* takeNth(n, iterable) {
let i = 0;
for (const value of iterable) {
if (i % n === 0) {
yield value;
}
i++;
}
}
export function* map(fn, ...iterables) {
const generators = iterables.map(createGenerator);
while (true) {
const args = [];
for (const generator of generators) {
const result = generator.next();
if (result.done) {
return;
}
args.push(result.value);
}
yield fn(...args);
}
}
export function apply(fn, ...iterables) {
const generators = iterables.map(createGenerator);
const args = generators.flatMap((generator) => Array.from(generator));
return fn(...args);
}
export const sum = (...args) =>
args.flatMap((v) => v).reduce((acc, v) => acc + v, 0);
export const multiply = (...args) =>
args.flatMap((v) => v).reduce((acc, v) => acc * v, 1);
export const negate = (v) => -1 * v;
export const comp = (...fns) => (data) =>
fns.reduceRight((acc, fn) => fn(acc), data);
export const rest = ([, ...tail]) => (tail.length > 0 ? tail : []);
export const juxt = (...fns) => (data) => [...fns.map((fn) => fn(data))];
import {
apply,
sum,
map,
multiply,
takeNth,
iterate,
negate,
juxt,
comp,
rest
} from "./clojure.core";
const component = (stepSizes = []) =>
apply(sum, map(multiply, takeNth(2, stepSizes), iterate(negate, 1)));
// Thanks to @jonasseglare for coming up with the original function.
// See: https://gist.github.com/ericnormand/d6fa214ed0733998a2e0a3f4d3fb62e5?permalink_comment_id=4252808#gistcomment-4252808
const move = juxt(comp(component, rest), component);
console.log(move([]));
console.log(move([10]));
console.log(move([10, 2]));
console.log(move([10, 2, 3]));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment