Last active
August 15, 2022 20:03
-
-
Save sebinsua/74af82c3489579e5a0d66322ae360236 to your computer and use it in GitHub Desktop.
This file contains 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
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))]; |
This file contains 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
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
See: https://codesandbox.io/s/condescending-roentgen-d72qnc?file=%2Fsrc%2Fclojure.js%3A0-1559