-1

Just a curious question. I want to create a function can handle infinite "layer"? make add(2)(3), add(1)(2)(3)...(10) all works.

Any ideas?

Weijing Lin
  • 575
  • 2
  • 5
  • 16
  • maybe `return this`? – smac89 Feb 02 '18 at 06:03
  • `f=_=>f` but you'll never get anything than this function as a return value... – Kaiido Feb 02 '18 at 06:04
  • 2
    [Related](https://stackoverflow.com/q/31306312/1541563) – Patrick Roberts Feb 02 '18 at 06:09
  • @AaditMShah, sure that's related, but that's not a duplicate. – Patrick Roberts Feb 02 '18 at 06:39
  • @PatrickRoberts I'm pretty sure that it's a duplicate. Both questions want a curried `add` function with a potentially infinite number of chained applications. True, one only takes a single argument at a time whereas the other one can take multiple arguments at a time. Nevertheless, the underlying idea is the same. That being said, good job on using `Symbol.isPrimitive` instead of `valueOf`. That's something I didn't know before. – Aadit M Shah Feb 02 '18 at 06:45
  • @AaditMShah The linked question doesn't request infinite currying, only a single curry. Your answer there just happened to go beyond the scope of the question and somewhat answered this one. Also, it's [`Symbol.toPrimitive`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/toPrimitive), not `Symbol.isPrimitive`. – Patrick Roberts Feb 02 '18 at 06:50
  • @PatrickRoberts Oh, right. My mistake. It's been a long time since I answered that question. From the title and my vague memory I thought that it was a duplicate. – Aadit M Shah Feb 02 '18 at 09:46
  • @PatrickRoberts, can you remove the duplicate mark? It confused others. – Weijing Lin Feb 14 '18 at 07:57

1 Answers1

6

You can, with a slight catch. The return value must be a function that you can coerce to a number. Here's how:

function add (addend) {
  'use strict'
  const sum = (this || 0) + addend
  const chain = add.bind(sum)

  for (const prop of Object.getOwnPropertyNames(Number.prototype)) {
    chain[prop] = Number.prototype[prop].bind(sum)
  }

  return chain
}

console.log(add(1))
console.log(add(1)(2))
console.log(add(1)(2)(3))
// convinced yet?
let four = add(4)
console.log(typeof four, four === 4)
// it's a function, not a number, so coerce to a primitive first
four = Number(four)
console.log(typeof four, four === 4)

add() is a function that contains its context (this) and all the Number.prototype properties, including its Symbol.toPrimitive property. In strict mode, the context behaves a lot more nicely, allowing you to define it as a primitive value like a number instead of defaulting to window and coercing bound primitives to Objects.

Patrick Roberts
  • 49,224
  • 10
  • 102
  • 153
  • 1
    There should probably be note about the fact that what is returned is indeed a function, which means `add(1)(2) !== 3`, and that Number methods will not be available (e.g `toFixed`, `toExponential` etc.) even though basic arithmetics which use `toPrimitive` will work. – Kaiido Feb 02 '18 at 06:35
  • @WeijingLin please stop attempting to edit my answer. If you have a concern with it, use comments to ask for clarification. – Patrick Roberts Feb 02 '18 at 08:06
  • @Kaiido I decided to fix that issue – Patrick Roberts Mar 28 '18 at 08:48