Skip to content

Instantly share code, notes, and snippets.

@yanatan16
Created September 23, 2014 05:14
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 yanatan16/23adb2a97a7b3ac3051a to your computer and use it in GitHub Desktop.
Save yanatan16/23adb2a97a7b3ac3051a to your computer and use it in GitHub Desktop.
TRANSducers!
// function reducing(acc, next) {
// return next_acc
// }
// function transducing(reducing) {
// return more_reducing
// }
// Example reducer (without transducers)
// function incrPrintConcat() {
// var i = 0
// return function (acc, val) {
// console.log(i, val, acc)
// return (acc||[]).concat(val+1)
// }
// }
//
// With transducers:
// tcomp(map(function (x) { return x+1 }),
// forEach(function (acc, val, i) { console.log(i, val, acc) }),
// concat)
// Perform transduction
Array.prototype.transduce = function (f, init) {
return this.reduce(f(), init)
}
Object.prototype.transduce = function (f, init) {
var obj = this
return Object.keys(obj).transduce(tcomp(map(function (key) { return [key, obj[key]] }), f), init)
}
// Compose transducers
function tcomp(f) {
var gs = Array.prototype.slice.call(arguments, 1)
while (gs.length)
f = (function (ff, g) {
return function (x) { return ff(g(x)) }
})(f, gs.shift())
return f
}
// Modifier transducers
function forEach(f) {
return function (next) {
return function (acc, val, i) {
f(acc, val, i)
return next(acc, val, i)
}
}
}
function map(f) {
return function (next) {
return function (acc, val, i) {
return next(acc, f(val, i), i)
}
}
}
function filter(f) {
return function (next) {
return function (acc, val, i) {
if (f(val, i))
return next(acc, val, i)
else
return acc
}
}
}
function take(n) {
return filter(function (val, i) {
return i < n
})
}
function takeWhile(f) {
var taking = true
return filter(function (val, i) {
return taking && (taking = f(val, i))
})
}
function drop(n) {
return filter(function (val, i) {
return i >= n
})
}
function dropWhile(f) {
var taking = false
return filter(function (val, i) {
return taking || (taking = f(val, i))
})
}
function takeNth(n) {
return filter(function (val, i) {
return i === n
})
}
function attrgetter(name) {
return map(function (obj) {
return obj[name]
})
}
function itemgetter(i) {
return map(function (arr) {
return arr[i]
})
}
// Accumulating transducers
function concat() {
return function () {
return function (acc, val) {
return (acc||[]).concat(val)
}
}
}
function objectify(keyf) {
return function () {
return function (acc, val, i) {
acc = acc || {}
acc[keyf(val, i)] = val
return acc
}
}
}
console.log([1,2,3].transduce(tcomp(map(function(x){return x+1}), concat()), []))
console.log({a:'b',c:'d',e:'f'}.transduce(
tcomp(itemgetter(1),
drop(1),
map(function (letter) { return letter.toUpperCase() }),
objectify(function(x) {return x.toLowerCase()}))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment