• Stars
    star
    359
  • Rank 117,797 (Top 3 %)
  • Language
    JavaScript
  • Created almost 9 years ago
  • Updated about 7 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

A proposal for adding partial application support to JavaScript.

ECMAScript Proposal: Function.prototype.papp

This proposal introduces papp and pappRight – concise ways of using partial application for functions that require no immediate this parameter. It is backwards-compatible, and is immediately useful with most any JavaScript function today.

Try it out!

npm install --save papp-polyfill

Then require it once (in your code, as early as possible):

require('papp-polyfill')

Introduction

Partial application is possible in JavaScript via Function.prototype.bind:

function add (x, y) { return x + y; }

var addTen = add.bind(null, 10);
addTen(20) //=> 30

However, bind is undesirable for three reasons:

  1. Sometimes you don't care about the value of this, yet you still must provide bind's first argument
  2. Sometimes you do care about the value of this, but don't want to commit to a specific value yet.
  3. Using bind is significantly slower than using a plain closure (!) (this has been fixed in V8, and wasn't an issue in other engines for quite a while)

Function.prototype.papp solves both these issues in a simple, elegant, and noise-free manner. Here is an illustrative example:

function add (x, y, z) { return x + y + z; }

var addTen = add.papp(3, 7);
addTen(5) //=> 15

// AS OPPOSED TO:
// var addTen = add.bind(null, 3, 7)
// OR:
// var addTen = (x) => add(3, 7, x)

var addThenIncrement = add.papp(1);
addThenIncrement(10, 6) //=> 17

// AS OPPOSED TO:
// var addThenIncrement = add.bind(null, 1)
// OR:
// var addThenIncrement = (a, b) => add(1, a, b)

Accepting papp into the ES standard will allow JS runtimes to implement a more performant version of bind that is dedicated to partial application.

Ignoring this

For functions that don't use the keyword this, papp helps with brevity:

function add (x, y) { return x + y; }

var addTen = add.papp(10);
addTen(20) //=> 30

Deferring Function Binding

If a function does use the keyword this, papp allows you to partially apply arguments without committing to a this value:

function greet (target) {
  return `${this.name} greets ${target}`;
}

var greetNewcomer = greet.papp('the newcomer');
greetNewcomer.call({ name: 'Alice' }) //=> 'Alice greets the newcomer'

Practical Examples

These examples are pulled from real-world use cases of partial application.

HTTP API Output Whitelisting

Player.whitelist = {
  basic: pluck.papp(['name', 'score']),
  admin: pluck.papp(['name', 'score', 'email']),
};

function pluck (attrs, obj) {
  var result = {};
  attrs.forEach( name => result[name] = obj[name] );
  return result;
}

// Example use (in practice, alice would come from a database):
var alice = { name: 'Alice', score: 100, email: '[email protected]', password_hash: '...' };

Player.whitelist.basic(alice) //=> { name: 'Alice', score: 100 }

Player.whitelist.admin(alice) //=> { name: 'Alice', score: 100, email: '[email protected]' }

Constructing User-friendly APIs

function createClient (host) {
  return {
    get:  makeRequest.papp(host, 'GET'),
    post: makeRequest.papp(host, 'POST'),
    put:  makeRequest.papp(host, 'PUT'),
    del:  makeRequest.papp(host, 'DELETE'),
  };
}

var client = createClient('https://api.example.com');
client.get('/users');
client.post('/comments', { content: "papp is great!" });

function makeRequest (host, method, url, data, options) {
  // ... Make request, return a promise ...
}

// AS OPPOSED TO:
// function createClient (host) {
//   return {
//     get:  (url, data, options) => makeRequest(host, 'GET', url, data, options),
//     post: (url, data, options) => makeRequest(host, 'POST', url, data, options),
//     put:  (url, data, options) => makeRequest(host, 'PUT', url, data, options),
//     del:  (url, data, options) => makeRequest(host, 'DELETE', url, data, options),
//   }
// }

Other Examples

These examples illustrate concepts you can use in your own applications.

Mapping with Arrays

var chapters = ["The Beginning", "Climax", "Resolution"];

var numberedChapters = chapters.map( toListItem.papp('My Book') )
//=> ["My Book / 1. The Beginning", "My Book / 2. Climax", "My Book / 3. Resolution"]

// AS OPPOSED TO:
// var numberedChapters = chapters.map( (chapter, i) => toListItem('My Book', chapter, i) )

function toListItem (prefix, item, i) {
  return `${prefix} / ${i + 1}. ${item}`
}

Polyfill

ES6:

Function.prototype.papp = function (...args) {
  var fn = this;
  return function (...moreArgs) {
    return fn.apply(this, [...args, ...moreArgs]);
  };
};

ES5:

Function.prototype.papp = function () {
  var slice = Array.prototype.slice;
  var fn = this;
  var args = slice.call(arguments);
  return function () {
    return fn.apply(this, args.concat(slice.call(arguments)));
  };
};

More Repositories

1

solid_use_case

A flexible use case pattern that works *with* your workflow, not against it.
Ruby
109
star
2

zaml

The Final Form of configuration files
TypeScript
46
star
3

jsdn

JavaScript Diagram Notation
JavaScript
29
star
4

es-explicit-this

Explicit this naming in ECMAScript functions
18
star
5

mithril-cc

An opinionated library for writing Mithril components
TypeScript
13
star
6

rollup-endpoint

The easiest way to serve a rollup bundle.
JavaScript
13
star
7

blog-post-examples

Examples (and more!) from my blog.
JavaScript
11
star
8

query-loader

Easy-to-use loading bar that loads static assets before displaying the page.
JavaScript
10
star
9

curated-js

A harshly curated list of minimal and pragmatic JavaScript libraries
7
star
10

proposal-temporary-bindings

6
star
11

staticmatic-js-app-starter

Quick starter for backbone.js, underscore.js, and jquery
JavaScript
6
star
12

shout

A nice-looking url shortener (with admin panel) that uses random dictionary words
HTML
4
star
13

lomic

Programming language for the game Nomic
Ruby
3
star
14

solarjs

A Radically Simple Node.js Server Framework
TypeScript
2
star
15

keydash

Improve your keyboard navigation skills. For free!
TypeScript
2
star
16

node-sass-endpoint

Easily server a SASS file from express.
JavaScript
2
star
17

powermotivate.me

A javascript implementation of the Seinfeld calendar
JavaScript
2
star
18

Fx.js

A lightweight, self-contained javascript animation library
JavaScript
2
star
19

Sublime-Text-2-Icon

2
star
20

staticmatic-basic

Default skeleton for StaticMatic
Ruby
2
star
21

pomic

A programming version of the game Nomic
Ruby
1
star
22

cheese_bot

A Planet Wars bot for Google's AI Contest http://ai-contest.com/
Java
1
star
23

repo-map

JavaScript
1
star
24

snake-mmo

Basically a test project to help develop SocketStream.
CoffeeScript
1
star
25

Modernize-Web-Solutions

The source code to our portfolio site!
JavaScript
1
star
26

fortune-lang-prototype

The fortune lab
OCaml
1
star
27

lomicbox

Manage multiple instances of lomic with ease
1
star
28

solbrain

Prolog
1
star
29

js-zero

Backup of an old type checker
JavaScript
1
star
30

staticmatic-iphone

A basic skeleton with some useful iPhone boilerplate
Ruby
1
star
31

soupmobile-webpop

The source to soupmobile.com's new design
CSS
1
star
32

temp52

Shell
1
star
33

test17

Shell
1
star
34

temp53

Shell
1
star
35

totg

flash game
ActionScript
1
star