Function.prototype.partial

# Tim Ruffles (9 years ago)

It'd be nice to add Function.prototype.partial, which is exactly like .bind without the this-setting first argument.

Adding it would have benefits:

  • .bind(null, ... is newbie confusing and ugly in functional code[1]
  • .bind(null, ... is a very common idiom[2]
  • .partial is intention revealing: it's clear you're writing functional code that doesn't care about this

Adding it seems low cost, and is backwards compatible:

  • implementors could literally make it a proxy to .bind if they want to get it done fast
  • shimmable
  • not new functionality, just a subset of existing functionality

Cheers,

Tim

@timruffles

# Jordan Harband (9 years ago)

(note, it couldn't be a direct proxy to bind because bind(null) permanently sets the "this" value (ie, (function () { return this }).bind(null).call([]) will return null or the global object, not the empty array. the polyfill would be a bit trickier, and couldn't use "bind" under the hood without changes to bind itself)

# Andrea Giammarchi (9 years ago)

I think his point was that in the functional programming way he is thinking about, you don't care about this at all so you can shim partial like:

Object.defineProperty(
  Function.prototype,
  'partial',
  {
    writable: true,
    configurable: true,
    value: function partial() {
      for (var a = [null], i = 0; i < arguments.length; a[++i] =
arguments[i - 1]);
      return this.bind.apply(this, a);
    }
  }
);

The dynamic this alternative seems quite straight forward anyway

Object.defineProperty(
  Function.prototype,
  'partial',
  {
    writable: true,
    configurable: true,
    value: function partial() {
      for (var f = this, a = [], i = 0; i < arguments.length; a[i] =
arguments[i++]);
      return function () { a.push.apply(a, arguments); return f.apply(this,
a); };
    }
  }
);
# Andrea Giammarchi (9 years ago)

for code sake, the dynamic should copy and push, not just push

Object.defineProperty(
  Function.prototype,
  'partial',
  {
    writable: true,
    configurable: true,
    value: function partial() {
      for (var f = this, a = [], i = 0; i < arguments.length; a[i] =
arguments[i++]);
      return function () {
        var args = a.slice(0);
        args.push.apply(a, arguments);
        return f.apply(this, a);
      };
    }
  }
);
# Isiah Meadows (9 years ago)

I agree that it would be nice. I frequently come up with a helper function for that, although my lazy fingers don't feel like typing 7 letters each time to create a partially applied function...

// Maybe Function.prototype.part?
list.map(create.part('type'))