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
// Let's make it possible to create pure functions even when we're | |
// dealing with impure operations that would have side effects! | |
// First we'll need a "Type" that can contain a (sometimes impure) function | |
function IO(fn) { | |
if (!(this instanceof IO)) {//make it simpler for end users to create a type without "new" | |
return new IO(fn); | |
} | |
this.runIO = fn;//IO now provides an extra control layer that allows the composition of unexecuted effects |
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
// Finally wrapped your head around Promises? Time to toss out all that knowledge and learn the functional alternative! | |
// Here's a super simple implementation of a Task "type" | |
const __Task = fork => ({fork}) | |
// Absurdly simple! All we're doing is using a function that returns some unknown value, by name, in an object. | |
// At this point "fork" is just a cute name though: what matters is how we use it. | |
// What makes Task a "Task" is that is that the "fork" value here... will be a higher-order function. | |
// Here's a usage example, already fully functional, already nearly as powerful as Promise! |
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
/* | |
Enable the "Request Desktop Site" functions on mobile chrome (android and iOS) allow users to see desktop layouts on responsive sites. Note that this is distinct from "opt out of mobile!" buttons built into your site: this is meant to work with the browser's native opt-in/opt-out functionality. | |
Since these functions work, in part, by simply spoofing the user agent to pretend to be desktop browsers, all we have to do is just remember that the browser once claimed to be android earlier in the same session and then alter the viewport tag in response to its fib. | |
Here's an example viewport tag <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"> that we'd be setting to scaleable-yes,max scale=2. That's just an example of something that works on the site I was building: you should customize the "desktop" viewport content setting to whatever works for your site's needs. If you wanted, you could stick this code in the head just after the primary viewport tag so that the br |
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
// spreadBatchesAsyncGen :: Iterator[[...Promises]] -> AsyncGenerator[[...Promises]] | |
const spreadBatchesAsyncGen = async function* (iterableOfPromises) { | |
for (let array of iterableOfPromises) { | |
yield* await Promise.all(array) | |
} | |
} |
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
const outputs = await pipe( | |
postIds,// array of numbers, which is... already an iterable | |
mapGen(fetchById),// generator of an array of eventually all resolved promises (requested in chunks of 3) | |
chunkGen(5),// generator of arrays of 5 promises, our "batch" | |
spreadBatchesAsyncGen,// async generator of individual resolved promises | |
forEachAsyncGen(renderPost)// Promise of an array of numbers | |
) |
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
await pipe( | |
postIds[Symbol.iterator](),// creates a generator from a plain array of postIds | |
chunkGen(5),// generator that pulls in 5 numbers and yields them out in arrays of 5 | |
mapGen(map(fetchById)),// generator that takes in arrays of numbers & turns them into arrays of requests | |
spreadBatchesAsyncGen,// async generator that spreads arrays of resolved promises & emits one promise at a time | |
forEachAsyncGen(renderPost)// a function that consumes the generator & does something with each result | |
) |
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
export async function* batchTasks(tasks = [], limit = 5, taskCallback = r => r) { | |
for (let i = 0; i < tasks.length; i = i + limit) { | |
const batch = tasks.slice(i, i + limit) | |
yield* await Promise.all( | |
batch.map((task) => task().then(taskCallback)) | |
) | |
} | |
} |
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
/* | |
Native Arrays are not great structures for cellular automata. | |
Non-empty, circular, doubly-linked lists would be ideal... | |
but all we really need to do is write a comonadic-like interface | |
such that it _pretends_ that the array is circular, and can thus | |
pass the exfn below a sort of "local" slice of an Array as if it were circular. | |
So you can mostly ignore the implementation mess below | |
*/ | |
Array.prototype.extendNear = function(exfn){ | |
const len = this.length; |
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
/* | |
So, let's play with some Semigroups and (maybe?) Monoids for combining lists in interesting ways | |
*/ | |
//This one is pretty straightforward | |
//Union (keep all values from both lists, but no repeats) | |
const Union = function(xs){ | |
if (!(this instanceof Union)) { | |
return new Union(xs); | |
} |
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
var object = { | |
value:5, | |
increment(){ return ++this.value; } | |
}; | |
/* | |
But of course, even though that value is central to what the object is, | |
it's not really a _primitive_ value in the sense that we can directly coerce it into a number or string: | |
*/ |
NewerOlder