Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Javascript macro: implementing F# style forward pipe operator

I want to implement a higher order function (hof) that essentially works like F# style forward-pipe operator (passes a value as the first argument to another function, myFunc). The only way I can think of is this:

function hof(val, myFunc, args_array) {...}

where args_array is the array of arguments for the call to myFunc (excluding the first argument, since that's going to be val)

But this doesn't look very elegant to me. Is there a better way to do this?

Edit: I found this on github https://gist.github.com/aaronpowell/d5ffaf78666f2b8fb033. But I don't really understand what the sweet.js code is doing. It'd be very helpful if you could annotate the code, specifically:

case infix { $val | _ $fn($args (,) ...) } => {
    return #{
        ($fn.length <= [$args (,) ...].length + 1 ? $fn($args (,) ..., $val) : $fn.bind(null, $args (,) ..., $val))
    }
}

case infix { $val | _ $fn } => {
    return #{
        ($fn.length <= 1 ? $fn($val) : $fn.bind(null, $val))
    }
}
like image 525
tldr Avatar asked Aug 02 '26 20:08

tldr


2 Answers

Isn't this called Currying?

Anyhow, here's a rubbish example, I'm sure there are better examples if you search:

function myCurry() {
    var args = [].slice.call(arguments);
    var fn = args.splice(0,1)[0];
    return function(arg) {
      var a = [].concat(arg, args);
      return fn.apply(this, a);
    };
}

// Just sums the supplied arguments, initial set are 1,2,3
var fn = myCurry(function(){
                   var sum = 0;
                   for (var i=0, iLen=arguments.length; i<iLen; i++) {

                     // Show args in sequence - 4, 1, 2, 3
                     console.log('arguments ' + i + ': ' + arguments[i]);
                     sum += arguments[i];
                   }
                   return sum;
                }, 1,2,3);

// Provide an extra argument 4
console.log(fn(4)); // 10
like image 106
RobG Avatar answered Aug 04 '26 11:08

RobG


If you want something like the F# pipeline operator, I think your best bet is either this approach that you had in your post:

hof(val, myFunc, [arg1, arg2, arg3]);

or this:

hof(val, myFunc, arg1, arg2, arg3);

The first one can be implemented like this:

function hof(val, func, args) {
    func.apply(this, [val].concat(args || []));
}

The second one can be implemented like this:

function hof(val, func) {
    func.apply(this, [val].concat(Array.prototype.slice(arguments, 2));
}

But that all leaves the question of why you wouldn't just call the function in a normal way:

myFunc(val, arg1, arg2, arg3);
like image 30
JLRishe Avatar answered Aug 04 '26 10:08

JLRishe