Skip to content

Instantly share code, notes, and snippets.

@tincho
Last active June 11, 2018 16:17
Show Gist options
  • Save tincho/4bf3eae5ec237e925b26c04cef9077f1 to your computer and use it in GitHub Desktop.
Save tincho/4bf3eae5ec237e925b26c04cef9077f1 to your computer and use it in GitHub Desktop.
all functional-programming js tools i've written
// var logHello = _partial(console.log, "hello ");
// logHello("world");
// accepts _partial (fn reference) as placeholder just like underscore accepts _
// var partialApplied = _partial(originalFn, _partial, "second", _partial, "fifth");
// partialApplied("first", "third") will call originalFn("first", "second", "third", "fifth")
function _partial() {
var args = Array.prototype.slice.call(arguments);
var method = args.shift();
var self = this;
var placeHolderPos = [];
args.forEach(function(arg, i) {
arg === self && placeHolderPos.push(i);
});
// remove placeholders!
args = args.filter(_notEqual.bind(undefined, self));
return function() {
var thisArguments = Array.prototype.slice.call(arguments);
placeHolderPos.forEach(function(pos) {
var arg = thisArguments.shift();
args.splice(pos, 0, arg);
});
var applyArguments = args.concat(thisArguments);
return method.apply(undefined, applyArguments);
}
}
};
// n-ary a function to accept only N (arity) of the arguments passed
// suppouse:
// getManyThings.then(function(a, b, c) { // i Just want to do console.log(a) });
// if I do: getManyThings.then(console.log);, console.log will receive a, b and C.
// how do I prevent it?
// With arity: (https://en.wikipedia.org/wiki/Arity)
// getManyThings.then(_ary(console.log));
function _ary(fn, arity) {
// default arity is 1
arity = arity || 1;
return function() {
var args = Array.prototype.slice.call(arguments, 0, arity);
return fn.apply(null, args);
};
}
// _compose(sum1, divide2, multiply5)(5) === 15
function _compose() {
var fs = Array.prototype.slice.call(arguments);
return function(x) {
return fs.reduce(function(p, f) { return f(p); }, x);
}
}
function _noop() {}
function _constant(v) { return function() { return v; }; }
function _notEqual(a, b) { return a !== b; }
// returns true if *any* of the arguments evaluates true
function _or() {
var args = Array.prototype.slice.call(arguments);
args = Array.prototype.concat.apply([], args);
var token = 0;
for (var i = 0; i < args.length; i++) {
token += +!!args[i];
}
return !!token;
}
// this should be a little more performant than doing something like:
// [some(), other(), another()].some(v => !!v);
// returns true if *all* of the arguments evaluates true
function _and() {
var token = 1;
var args = Array.prototype.slice.call(arguments);
args = Array.prototype.concat.apply([], args);
for (var i = 0; i < args.length; i++) {
token *= +!!args[i];
}
return !!token;
}
// _if(condition, thenFunction[, elseFunction]);
function _if() {
// ES6:
// var args = ...arguments;
var args = Array.prototype.slice.call(arguments);
var cond = args.shift();
if (typeof cond === "function") { cond = cond(); }
var noop = function(){};
return (args[+!cond] || noop).apply(this);
}
// "functional _if = _fif"
function _fif() {
// ES6:
// return _if.bind(this, ...arguments);
var args = Array.prototype.slice.call(arguments);
return function() { return _if.apply(this, args); }
}
// domElementsArray.forEach( _method("addEventListener", "click", clickHandler) );
function _method(method) {
var callArgs = [].slice.call(arguments, 1);
return function(obj) {
return obj[method].apply(obj, callArgs);
}
}
@tincho
Copy link
Author

tincho commented Jun 5, 2018

_if use cases:

  • in a compose pipeline for example
function getFromServer(string: url) { ... return object: response; }
function getProperty() { /* se getProperty or _property above */ }
function valueForViewA() { return "A" }
function valueForViewB() { return "B" }
function updateView(v) { .... }

updateView(compose(
    getFromServer(url),
    _fif( getProperty("Enabled"), valueForViewA, valueForViewB) 
));

@tincho
Copy link
Author

tincho commented Jun 5, 2018

test code (try it on http://tddbin.com)

function compose() {
    var fs = Array.prototype.slice.call(arguments);
    return function(x) {
        return fs.reduce(function(p, f) {
             return f(p);
        }, x);
    }
}

function getProperty(prop) {
  return function(obj) {
    return obj[prop];
  }
}


function _if() {
    // ES6:
    // var args = ...arguments;
    var args = Array.prototype.slice.call(arguments);
    var cond = args.shift();
    if (typeof cond === "function") { cond = cond(); }
    var noop = function(){};
    return (args[+!cond] || noop).apply(this);
}

function _fif() {
    // ES6:
    // return _if.bind(this, ...arguments);
    var args = Array.prototype.slice.call(arguments);
    return function(cond) {
        // ES6:
        // args = [cond, ...args];
        args.splice(0,0, cond);
        return _if.apply(this, args);
    }
}

function valueForViewA() { return "A" }
function valueForViewB() { return "B" }


describe("if", () => {


it("test 1", () => {
 
  const getFromServer = () => ({Enabled: true});
  const value = compose(
    getFromServer,
    getProperty("Enabled"),
    _fif(valueForViewA, valueForViewB) 
  )();
  console.log(value);
  assert( value === "A" );
});

it("test 2", () => {
 
  const getFromServer = () => ({Enabled: false});
  const value = compose(
    getFromServer,
    getProperty("Enabled"),
    _fif( valueForViewA, valueForViewB) 
  )();
  console.log(value);
  assert( value === "B" );
});
})

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment