-
-
Save scott-christopher/a80af9be36f47901fb50 to your computer and use it in GitHub Desktop.
Dynamic dispatch objects for Ramda
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 _isTransformer = require('./src/internal/_isTransformer'); | |
var _xmap = require('./src/internal/_xmap'); | |
var R = require('./dist/ramda'); | |
/** | |
* This is an example of separating Ramda's current dynamic dispatching | |
* into external objects that can be applied explicitly. | |
* | |
* n.b. `relationsWith` and `mergeWith` are only included to support | |
* `dispatchOver` and are likely to be far from optimal. | |
*/ | |
/** | |
* Given two lists, will produce a 3-element array containing the difference, | |
* intersection and complement of the two lists, respectively. The provided | |
* function is used to compare values of each set for equality. | |
* | |
* relationsWith :: ((a, a) -> Boolean) -> [a] -> [a] -> [[a],[a],[a]] | |
*/ | |
var relationsWith = R.curryN(3, function relationsWith(fn, list1, list2) { | |
function _relationsWith(xs, l, i, r) { | |
var idx, x; | |
if (xs.length === 0) { | |
return [l, i, r]; | |
} else if (r.length === 0) { | |
return [R.concat(xs, l), i, r]; | |
} else { | |
x = xs[0]; | |
idx = R.findIndex(R.partial(fn, x), r); | |
if (idx >= 0) { | |
return _relationsWith( | |
R.tail(xs), | |
l, | |
R.append(x, i), | |
r.slice(0, idx).concat(r.slice(idx + 1)) | |
); | |
} else { | |
return _relationsWith(R.tail(xs), R.append(x, l), i, r); | |
} | |
} | |
} | |
return _relationsWith(list1, [], [], list2); | |
}); | |
/** | |
* Merges two objects. When a key exists in both objects, their values | |
* will be passed to the given function to determine the merged value. | |
* | |
* mergeWith :: ((a,a) -> a) -> {a} -> {a} -> {a} | |
*/ | |
var mergeWith = R.curryN(3, function mergeWith(fn, obj1, obj2) { | |
var k1 = R.toPairs(obj1), | |
k2 = R.toPairs(obj2), | |
lir = relationsWith(R.useWith(R.equals, R.head, R.head), k1, k2), | |
lr = R.concat(lir[0], lir[2]), | |
i = R.map(function (pair) { | |
var k = pair[0], | |
propK = R.prop(k), | |
trans = R.useWith(fn, propK, propK); | |
return [k, trans(obj1, obj2)]; | |
}, lir[1]); | |
return R.fromPairs(R.concat(lr, i)); | |
}); | |
/** | |
* When given an object of conditional dispatch pairs and an object | |
* containing methods, this function will produce a new object | |
* containing all methods of the original, however replacing those | |
* whose keys exist in the dispatch object with a function that | |
* will call the dispatch function, if the dispatch condition is | |
* satisfied. | |
* | |
* @see R.cond | |
* @see R.ifElse | |
* | |
* Conditional :: [(*... -> Boolean), (*... -> *)] | |
* dispatchOver :: {Conditional} -> {*... -> *} -> {*... -> *} | |
*/ | |
var dispatchOver = R.curryN(2, function dispatchOver(dispatches, obj) { | |
return mergeWith(function (ramdaFn, dispatchPair) { | |
return R.ifElse(dispatchPair[0], dispatchPair[1], ramdaFn); | |
}, obj, dispatches); | |
}); | |
/////// DISPATCH OBJECTS | |
var transducerDispatches = { | |
map: [ | |
R.pipe(R.nthArg(1), _isTransformer), | |
// just `_xmap` with logging for demonstration | |
function(fn, x) { | |
console.log('-> xmap') | |
return _xmap(fn, x); | |
} | |
] | |
}; | |
var fantasyDispatches = { | |
map: [ | |
R.pipe(R.nthArg(1), R.has('map')), | |
// just `invoker(1, 'map')` with logging for demonstration | |
function(fn, obj) { | |
console.log('-> fmap'); | |
return obj.map(fn); | |
} | |
] | |
}; | |
/////// EXAMPLE | |
var _R = R.pipe( | |
dispatchOver(transducerDispatches), | |
dispatchOver(fantasyDispatches) | |
)(R); | |
console.log(_R.into([], _R.map(_R.multiply(2)), [1, 2, 3, 4, 5])); | |
// -> xmap | |
// [ 2, 4, 6, 8, 10 ] | |
console.log(_R.map(_R.multiply(2), { map: function(fn) { return fn(21); }})); | |
// -> fmap | |
// 42 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment