0

I saw last days this question about Javascript, that a function should return back some values based on the number of parentheses calls in the function.

console.log(f() == 1); //->true
console.log(f()() == 3); //->true
console.log(f()()() == 6); //->true
... //and so on 10,15,21...

I came up with the following code:

function f() {
    f.count++;
    return f;
};

f.count=0;
f.toString = function(){
 console.log(f.count);
 return f.count;
};

console.log(f() == 1); // true
console.log(f()() == 3); //3
console.log(f()()() == 6); //6

But this will break if, for instance, I call:

f();
console.log(f() == 1); // true
console.log(f()() == 3); //3
console.log(f()()() == 6); //6

Which I understand why. However, my question is: how can I make this recursive in the way that the function can tell how many parentheses were used and to be independent of the other calls?

So for instance, when I'm saying f() to get 1 and if I say f(); f(); to get 1 and 1. Not 1 and 2.

I know that maybe it has to do with the scope of the variable (I was trying to follow this: What is the scope of variables in JavaScript?), but for my example, my tries were without success.

Edwin
  • 2,146
  • 20
  • 26
  • Return a new function instead of the same one. – Ry- Jan 28 '18 at 21:13
  • but then will not be recursive, or what you have in mind? – Edwin Jan 28 '18 at 21:17
  • this function is not properly recursive. It returns itself and you call it again, but it is not defined in terms of itself. Moreover, this works by side-effect: it modifies the field count, which is not a good programming practice. – Roberto Trani Jan 28 '18 at 21:19
  • If you need a function that calls itself `n` times, it's more natural to use a parameter `n` instead of calling it with n `()`, no? – Roberto Trani Jan 28 '18 at 21:21
  • As said above, this isn't recursivity but some kind of weird currying. You should tell us exactly what you seek : solving a specific problem or fit this syntax ? – topheman Jan 28 '18 at 21:27
  • @RobertoTrani I know, but these were the requirements, so I have to work with what I have. And as a side note, these whole question/requirements were not mine, but I just found the question challenging and fun to find an answer to it. – Edwin Jan 28 '18 at 21:28
  • @topheman a better solution than mine in the direction of recursive call or something like that – Edwin Jan 28 '18 at 21:29
  • @Edwin: Your original function wasn’t recursive either, but I’m pretty sure that isn’t an actual requirement. – Ry- Jan 28 '18 at 21:32
  • @Ryan I was just interested if maybe can be done in a recursive way, let's say you add an `n` argument to `f` and check if is undefined or not and go on from there. – Edwin Jan 28 '18 at 21:35

1 Answers1

3

You need to use a new counter every time f is called and then return a different function, so that that one does not reset the counter.

Also, in ES6 you can use this to keep track of the count as a primitive number:

function f() {
    const g = f.bind((+this || 0)+1);
    g.toString = () => (+this+1) * (+this+2)/2 || 1;
    return g;
}

console.log('' + f()); // 1
console.log('' + f()()); // 3
console.log('' + f()()()); // 6
console.log('' + f()()); // 3
trincot
  • 317,000
  • 35
  • 244
  • 286
  • great snippet. There is no need to coerce `this` though (`+this`). – topheman Jan 28 '18 at 21:45
  • 1
    Thanks. The coercion is still necessary in sloppy mode, where `this` is the `window` object and gets coerced to string with the next `+ 1` acting as concatenation. – trincot Jan 28 '18 at 21:49
  • 1
    clarification/confirmation please: if `this` is the `window` object then `+this` becomes `NaN`, not a string nor the string `"NaN"`. Thus, the first call resolves to: `const g = f.bind(1)`. Wait! `bind` returns a function so the primitive `1` is cast (wrapped) to `Number`. Thus `Number` - not a numeric literal and not a number-as-string - is the `this` of all subsequent calls. – radarbob Jan 28 '18 at 23:27
  • In ES6 `this` remains a primitive; it is no longer cast to an object as in ES5. – trincot Jan 29 '18 at 05:39
  • nice snippet, let me check if I got some stuff right from it. When you did `+this || 0` you did that just to assure that `this` is gonna be `0` or the `this` value until that point parsed (in this case) to int? then the `toString` is just the logic to get different values for the number of parentheses – Edwin Jan 29 '18 at 09:29
  • 1
    When `f` is called (the initial call), `this` will be the `window` object (sloppy mode) or `undefined` (strict mode). In both cases, `+this` will be `NaN` which is falsy, so then the `|| 0` kicks in. The same with the `toString` function where the expression will be `NaN` again and `|| 1` kicks in. Once `this` is numerical, then `+this` is a no-op. – trincot Jan 29 '18 at 09:40