{"id":16374488,"url":"https://github.com/azz/es-function-partial-curry","last_synced_at":"2025-10-26T08:30:37.493Z","repository":{"id":66081949,"uuid":"49139365","full_name":"azz/es-function-partial-curry","owner":"azz","description":":rocket: Partial application and function currying for EcmaScript.","archived":false,"fork":false,"pushed_at":"2016-01-08T03:17:50.000Z","size":3,"stargazers_count":6,"open_issues_count":2,"forks_count":2,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-01-31T17:12:44.190Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/azz.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-01-06T14:16:55.000Z","updated_at":"2017-09-21T21:23:31.000Z","dependencies_parsed_at":"2023-03-17T09:15:35.945Z","dependency_job_id":null,"html_url":"https://github.com/azz/es-function-partial-curry","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/azz%2Fes-function-partial-curry","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/azz%2Fes-function-partial-curry/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/azz%2Fes-function-partial-curry/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/azz%2Fes-function-partial-curry/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/azz","download_url":"https://codeload.github.com/azz/es-function-partial-curry/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":238293237,"owners_count":19448148,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-11T03:17:24.006Z","updated_at":"2025-10-26T08:30:37.167Z","avatar_url":"https://github.com/azz.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# EcmaScript `partial` and `curry`\n\nThis proposal offers two popular functional programming features for EcmaScript,\npartial application and currying.\n\n## Provisions\n\nTwo functions are added to the standard API from `Function.prototype`:\n\n  - `Function.prototype.partial` - Which returns another function with arguments pre-bound.\n  - `Function.prototype.curry` - Which, like `partial` returns another function, but invoking the returned function will bind further arguments to the function. Invoking a curried function with no arguments causes the underlying function to be called.\n\n## API\n\n`Function.prototype.partial(...args)` - Yields a regular function with arguments bound.\n\n`Function.prototype.curry(...args)` - Yields a \"curried\" function, which will continue to accept argument bindings with subsequent calls. To invoke a curried function, call it with no arguments.\n\n## Examples\n\nBasic partial application:\n\n```js\nfunction clamp(lower, upper, value) {\n  if (value \u003e upper) return upper;\n  if (value \u003c lower) return lower;\n  return value;\n}\n\nconst zeroToOne = clamp.partial(0.0, 1.0);\nzeroToOne(1.5); //=\u003e 1.0\n```\n\nRepeated currying with `reduce`:\n\n```js\nfunction sum(a, b) { return a + b; }\n\nfunction immutableSetPropertyToSum(key, ...vals) {\n  return {\n    ...this,\n    [key]: vals.reduce(sum, 0)\n  };\n}\n\nconst setFoo = immutableSetPropertyToSum.curry(\"foo\");\nconst call = (fn, arg) =\u003e fn(arg);\nconst setFooToVal = [1, 2, 3].reduce(call, setFoo);\n// Same as `() =\u003e immutableSetPropertyToSum(\"foo\", 1, 2, 3)`\n\nconst obj = { foo: 0, bar: 1 };\n\nobj::setFooToVal(); //=\u003e { foo: 6, bar: 1 }\n// Equivalent to `setFooToVal.call(obj)`\n\nobj; //=\u003e { foo: 0, bar: 1 }\n```\n\nThe above demonstrates that `this` can be bound _after_ a partial or curried function is created.\n\nUsage with immutable `class`es and lazy execution: ([Try in Babel REPL](https://babeljs.io/repl/#?experimental=true\u0026evaluate=true\u0026loose=false\u0026spec=false\u0026code=%22use%20strict%22%3B%0A%0AFunction.prototype.partial%20%3D%20function%20%28...bindArgs%29%20%7B%0A%20%20const%20fn%20%3D%20this%3B%0A%20%20return%20function%20%28...args%29%20%7B%0A%20%20%20%20return%20fn.call%28this%2C%20...bindArgs%2C%20...args%29%0A%20%20%7D%0A%7D%0A%0AFunction.prototype.curry%20%3D%20function%20%28...bindArgs%29%20%7B%0A%20%20const%20fn%20%3D%20this%3B%0A%20%20return%20function%20%28...args%29%20%7B%0A%20%20%20%20return%20args.length%20%3D%3D%3D%200%0A%20%20%20%20%20%20%3F%20fn.call%28this%2C%20...bindArgs%29%0A%20%20%20%20%20%20%3A%20fn.curry.call%28fn%2C%20...bindArgs%2C%20...args%29%3B%0A%20%20%7D%0A%7D%0A%0Aclass%20Stack%20%7B%0A%20%20constructor%28...vals%29%20%7B%0A%20%20%20%20this._list%20%3D%20%5B...vals%5D%3B%0A%20%20%7D%0A%20%20push%28...vals%29%20%7B%0A%20%20%20%20return%20new%20Stack%28...this._list%2C%20...vals%29%3B%0A%20%20%7D%0A%20%20%0A%20%20pop%28%29%20%7B%20return%20new%20Stack%28...this._list.slice%280%2C%20-1%29%29%3B%20%7D%0A%20%20top%28%29%20%7B%20return%20this._list.slice%28-1%29%3B%20%7D%0A%20%20%0A%20%20toString%28%29%20%7B%20return%20this._list.toString%28%29%3B%20%7D%0A%7D%0A%0Aconst%20stack%20%3D%20new%20Stack%281%2C%202%2C%203%29%3B%0A%0Afunction%20lazilyAddItems%28items%29%20%7B%0A%20%20if%20%28!items.length%29%20return%20this%3B%0A%20%20return%20this%28...items%29%3B%0A%7D%0A%0Aconst%20curriedPush%20%3D%20Stack.prototype.push.curry%28%29%0A%20%20%3A%3AlazilyAddItems%28%5B4%2C%205%2C%206%5D%29%0A%20%20%3A%3AlazilyAddItems%28%5B7%2C%208%2C%209%5D%29%3B%0A%0Aconst%20stack2%20%3D%20stack%3A%3AcurriedPush%28%29%3B%20%2F%2F%20late%20binding%20%28curried.call%28stack%29%29%0Aconsole.log%28stack2.toString%28%29%29%20%2F%2F%3D%3E%201%2C2%2C3%2C4%2C5%2C6%2C7%2C8%2C9%0A%0Aconst%20stack3%20%3D%20%28new%20Stack%29%3A%3AcurriedPush%28%29%3B%0Aconsole.log%28stack3.toString%28%29%29%20%2F%2F%3D%3E%204%2C5%2C6%2C7%2C8%2C9%0A%0Aconsole.log%28stack.toString%28%29%29%20%2F%2F%3D%3E%201%2C2%2C3%20%28immutable%29))\n\n```js\nclass Stack {\n  constructor(...vals) {\n    this._list = [...vals];\n  }\n  push(...vals) {\n    return new Stack(...this._list, ...vals);\n  }\n\n  pop() { return new Stack(...this._list.slice(0, -1)); }\n  top() { return this._list.slice(-1); }\n\n  toString() { return this._list.toString(); }\n}\n\nconst stack = new Stack(1, 2, 3);\n\nfunction lazilyAddItems(items) {\n  if (!items.length) return this;\n  return this(...items);\n}\n\nconst curriedPush = Stack.prototype.push.curry()\n  ::lazilyAddItems([4, 5, 6])\n  ::lazilyAddItems([7, 8, 9]);\n\nconst stack2 = stack::curriedPush(); // late binding (curried.call(stack))\nconsole.log(stack2.toString()) //=\u003e 1,2,3,4,5,6,7,8,9\n\nconst stack3 = (new Stack)::curriedPush();\nconsole.log(stack3.toString()) //=\u003e 4,5,6,7,8,9\n\nconsole.log(stack.toString()) //=\u003e 1,2,3 (immutable)\n```\n\n## Notes\n\nNote that a curried function will not invoke the underlying function until it is called with zero arguments. However a partial function will be invoked unless `partial` is called again.\n\nThus, all of the following are semantically **equivalent**:\n\n- `fn.curry()(1, 2, 3)()`\n- `fn.curry(1, 2, 3)()`\n- `fn.curry(1)(2)(3)()`\n- `fn.curry(1, 2)(3)()`\n- `fn.partial(1, 2, 3)()`\n- `fn.partial(1).partial(2).partial(3)()`\n- `fn.partial(1).partial(2)(3)`\n- `fn.partial(1, 2).partial(3)()`\n- `fn.partial(1, 2, 3)()`\n- `fn.partial(1)(2, 3)`\n\n`fn.partial()` (with no arguments) is essentially a no-op (but still produces a new closure).\n\n## Binding `this`  \n\nThe recommended method of performing `this` binding with these functions is using the `::` operator.\n\n`::fn.partial(1)(2)` is semantically the same as `fn.call(this, 1, 2)`.\n\nOne thing to note when using classes is that when calling a method, you will likely want to bind the function to the instance. This can be done, as shown above with `::instance.method`.\n\nFor example, a partial function could be `(::instance.method).partial(arg)`, this is **not** the same as `::instance.method.partial(arg)`.\n\nThe former yields `instance.method.bind(instance).partial(arg)`.\n\nThe latter yields\n`instance.method.partial.call(instance.method, arg)`. Here, `this` becomes the method, not the instance.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fazz%2Fes-function-partial-curry","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fazz%2Fes-function-partial-curry","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fazz%2Fes-function-partial-curry/lists"}