Skip to content

Instantly share code, notes, and snippets.

@Raynos Raynos/continuable.js Secret
Last active Dec 16, 2015

Embed
What would you like to do?
// An alternative to promises from https://github.com/medikoo/deferred#promises-approach
var fs = require("fs")
var partial = require("ap").partial
// continuable module not written, but trivial to implement
// see https://github.com/Raynos/continuable
var map = require("continuable/map")
var list = require("continuable/list")
// Continuable<T>: (continuation:(err: Error, result: T) => void) => void
// partial (fn: Function, ...args: Value) => Function
// map (lambda:(A) => B) => (Continuable<A>) => Continuable<B>
// flatten (source:Continuable<Continuable<T>>) => Continuable<T>
// fileNames := Continuable<Array<String>>
var fileNames = partial(fs.readdir, __dirname)
// validFiles := Continuable<Array<String>>
var validFiles = map(function (fileNames) {
return fileNames.filter(function (fileName) {
return fileName.slice(-3) === ".js" && fileName !== "lib.js"
})
})(fileNames)
// files := Continuable<Array<File>>
var files = flatten(map(function (validFiles) {
return list(validFiles.map(function (fileName) {
return partial(fs.readFile, fileName)
}))
})(validFiles))
// writer := Continuable<FileWriteResult>
var writer = flatten(map(function (files) {
return partial(fs.writeFile, __dirname + "/lib.js", files.join("\n"))
})(files))
writer(function (err, result) {
// err is err either nothing or first error in chain
// of operations
// do stuff with write result
})
// type Algebra := Functor & Monad
// Continuable := (Continuable<T>) => Algebra
function ContinuableAlgebra(continuable) {
continuable.map = function (lambda) {
return ContinuableAlgebra(map(lambda)(continuable))
}
continuable.chain = function (lambda) {
return ContinuableAlgebra(flatten(map(lambda)(continuable)))
}
continuable.of = function (v) {
return function (cb) { cb(null, v) }
}
return continuable
}
// flatten (source:Continuable<Continuable<T>>) => Continuable<T>
function flatten(source) {
return function continuable(callback) {
source(function (err, next) {
if (err) {
return callback(err)
}
next(callback)
})
}
}
// list (Array<Continuable<T>>) => Continuable<Array<T>>
function list(continuables) {
return function continuable(cb) {
var result = [], finished, count = 0
continuables.forEach(function (source, index) {
source(function (err, value) {
if (err && !finished) {
finished = true
return cb(err)
} else if (!err) {
result[index] = value
if (++count === futures.length) {
cb(null, result)
}
}
})
})
}
}
// map (lambda:(A) => B) => (Continuable<A>) => Continuable<B>
function map(lambda) { return function duplex(source) {
return function continuable(callback) {
source(function (err, value) {
return err ? callback(err) : callback(null, lambda(value))
})
}
} }
var slice = Array.prototype.slice
// partial (fn: Function, ...args: Value) => Function
function partial(fn) {
var curried = slice.call(arguments, 1)
return function rest() {
var args = curried.concat(slice.call(arguments))
return fn.apply(null, args)
}
}
var fs = require("fs")
var partial = require("ap").partial
var Continuable = require("continuable")
var list = require("continuable/list")
Continuable(partial(fs.readdir, __dirname))
// Continuable<Array<String>>
.map(function (fileNames) {
return fileNames.filter(function (fileName) {
return fileName.slice(-3) === ".js" && fileName !== "lib.js"
})
})
// Continuable<Array<String>>
.map(function (validFiles) {
return validFiles.map(function (fileName) {
return partial(fs.readFile, fileName)
})
})
// Continuable<Array<Continuable<File>>>
.chain(function (files) {
return list(files)
})
// Continuable<Array<File>>
.chain(function (files) {
var content = files.join("\n")
return partial(fs.writeFile, __dirname + "/lib.js", content)
})
// Continuable<WriteResult>
(function (err, writeResult) {
/* handle err or writeResult */
})
var fs = require("fs")
var partial = require("ap").partial
// continuable module not written, but trivial to implement
// see https://github.com/Raynos/continuable
var map = require("continuable/map")
var list = require("continuable/list")
function Chain(continuable) {
if (!continuable) {
return
}
continuable.chain = function (duplex) {
return Chain(duplex(continuable))
}
return continuable
}
Chain(partial(fs.readdir, __dirname))
.chain(map(function (fileNames) {
return fileNames.filter(function (fileName) {
return fileName.slice(-3) === ".js" && fileName !== "lib.js"
})
}))
.chain(map(function (validFiles) {
return list(validFiles.map(function (fileName) {
return partial(fs.readFile, fileName)
}))
}))
.chain(flatten)
.chain(map(function (files) {
return partial(fs.writeFile, __dirname + "/lib.js", files.join("\n"))
}))
.chain(flatten)
(function (err, files) {
// err is err either nothing or first error in chain
// of operations
// do stuff with write result
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.