Last active
August 29, 2015 14:13
-
-
Save unscriptable/0c3c144a09e0091f37f6 to your computer and use it in GitHub Desktop.
Simple (and probably naive) JavaScript Lens implementation
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
module.exports = Group; | |
Group.compete = compete; | |
function Group (equals, compare) { | |
this.equals = equals; | |
this.compare = compare; | |
} | |
Group.prototype = { | |
compete: function () { | |
return compete(this.equals, this.compare); | |
} | |
}; | |
/** | |
* Filter function to determine which of all multiplexed streams | |
* is currently winning. | |
* TODO: change this so that multiple streams can be winners, but | |
* don't use an array of winners. Perhaps inject another function? | |
*/ | |
function compete (equals, compare) { | |
var winner; | |
return function (value) { | |
var id = identify(value); | |
if (equals(value, winner) || compare(value, winner) >= 0) { | |
winner = value; | |
} | |
return winner == value; | |
}; | |
} |
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
module.exports = Lens; | |
Lens.Object = ObjectLens; | |
Lens.Array = ArrayLens; | |
Lens.compose = compose; | |
Lens.copyObject = copy; | |
/** | |
* Lens: given a function that returns a function that maps `a` to | |
* a "transformed a", it will give us a function that maps `s` to a | |
* "transformed s". | |
*/ | |
function ObjectLens (propName) { | |
return new Lens(get, set); | |
function get (obj) { | |
return obj[propName]; | |
} | |
function set (obj, val) { | |
var c = copy(obj); | |
c[propName] = val; | |
return c; | |
} | |
} | |
function ArrayLens (index) { | |
return new Lens(get, set); | |
function get (arr) { | |
return arr[index]; | |
} | |
function set (arr, val) { | |
var c = arr.slice(0); | |
c[index] = val; | |
return c; | |
} | |
} | |
function Lens (get, set) { | |
this.get = get; | |
this.set = set; | |
} | |
Lens.prototype = { | |
over: function (map) { | |
var get, set; | |
get = this.get; | |
set = this.set; | |
return function (s) { | |
set(s, map(get(s))); | |
return s; | |
}; | |
}, | |
compose: function (lens) { | |
return compose(this, lens); | |
} | |
}; | |
function compose (lens1, lens2) { | |
return new Lens(get, set); | |
function get (a) { | |
return lens2.get(lens1.get(a)); | |
} | |
function set (s, a) { | |
return lens2.set(s, lens1.get(a)); | |
} | |
} | |
function copy (o) { | |
var c = Object.create(Object.getPrototypeOf(o)); | |
var keys = Object.keys(o); | |
for (var n = 0, len = keys.length; n < len; n++) { | |
c[n] = o[n]; | |
} | |
return c; | |
} |
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 most = require('most'); | |
var Lens = require('./Lens'); | |
var Group = require('./Group'); | |
var sampleEvent = { | |
pixelData: { r: 72, g: 27, b: 135 }, | |
coords: { x: 32, y: 7 } | |
}; | |
var streams = []; | |
var bundle = most.merge(streams); | |
var pixelLens = new Lens.Object('pixelData'); | |
var coordsLens = new Lens.Object('coords'); | |
var brightestPixel = Group.compete(sameSource, pixelCompare); | |
bundle.filter(brightestPixel) | |
.forEach(console.log.bind(console)); | |
function pixelCompare (s1, s2) { | |
// this doesn't seem like the intended use case for lenses :) | |
var p1 = pixelLens.get(s1); | |
var p2 = pixelLens.get(s2); | |
return intensity(p1.r, p1.g, p1.b) - intensity(p2.r, p2.g, p2.b); | |
} | |
function sameSource (s1, s2) { | |
var c1 = coordsLens.get(s1); | |
var c2 = coordsLens.get(s2); | |
return sameCoords(c1, c2); | |
} | |
function intensity (r, g, b) { | |
// fast, approximate light intensity formula for the human eye | |
return (r + r + g + g + g + b) / 6 / 256; | |
} | |
function sameCoords (c1, c2) { | |
return c1.x === c2.x && c1.y === c2.y; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment