'Possible to do a chained factorial method without a helper method

I'm seeing if it's possible to write a factorial method as follows:

class InlineMath {
    constructor(x) {
        this.x = x
    }
    minus(y) {
        this.x -= y;
        return this;
    }
    times(y) {
        this.x *= y;
        return this;
    }
    factorial(n) {
        if (n == 1) {
            return this;
        } else {
            this.x = this.times(this.factorial(this.minus(1)));
        }
    }
}
x = new InlineMath(2);
x.factorial().factorial();
console.log(x);

I know this is a totally non-standard way to do it but was just seeing if this way was possible (i.e., only through side-effects).

But so far the only way I can figure out how to do it is offload it like so:

class InlineMath {
    constructor(x) {
        this.x = x
    }
    minus(y) {
        this.x -= y;
        return this;
    }
    times(y) {
        this.x *= y;
        return this;
    }
    factorial() {
        this.x = _factorial(this.x);
        return this;
    }
}
function _factorial(n) {
    if (n==1) {
        return n;
    } else {
        return n * _factorial(n-1);
    }  
}
x = new InlineMath(2);
x.factorial().factorial();
console.log(x);


Solution 1:[1]

Multiple mistakes here.

  • Don't reassign this.x, keep your instances immutable.
  • the factorial method should not take a parameter, it should use the value stored in the instance
  • consequently, the recursive call of factorial needs to be made on a different instance, and not be given an argument
  • the factorial method must always return a new instance, not nothing like your current else branch.

With some renaming:

class InlineNumber {
    constructor(n) {
        this.n = n
    }
    factorial() {
        if (this.n == 1) {
            // return 1
            return this;
        } else {
            // return n * (n-1)!
            return this.times(this.minus(new InlineNumber(1)).factorial());
        }
    }
    minus(subtrahend) {
        return new InlineNumber(this.n - subtrahend.n);
    }
    times(multiplicand) {
        return new InlineNumber(this.n * multiplicand.n);
    }
    valueOf() {
        return this.n;
    }
}
const x = new InlineNumber(3);
console.log(x.factorial().factorial());

Solution 2:[2]

In the factorial formula n * (n-1)!, you need the value n twice. With a mutable math object, you'll need to clone it for the recursive call:

class InlineMath {
    constructor(x) {
        this.x = x
    }
    clone() {
        return new InlineMath(this.x);
    }
    minus(y) {
        this.x -= y;
        return this;
    }
    times(y) {
        this.x *= y;
        return this;
    }
    factorial() {
        if (this.x > 1)
            this.times(this.clone().minus(1).factorial().x);
        return this;
    }
}
x = new InlineMath(3);
x.factorial().factorial();
console.log(x);

Notice that writing the formula as (n-1)! * n is not easily possible:

this.minus(1).factorial().times(this.clone().x)

won't work as the cloning happens too late. I recommend my other answer which avoids this can of worms…

Solution 3:[3]

I'm hoping this is only a proof-of-concept, and that you never plan on using code like this. But a simple change to your code will achieve this "through side-effects":

class InlineMath {
    constructor(x) {
        this.x = x
    }
    minus(y) {
        this.x -= y;
        return this;
    }
    times(y) {
        this.x *= y;
        return this;
    }
    factorial() {
        if (this.x <= 1) {
          this.x = 1;
        } else {
          this.x *= this.minus(1).factorial().x
        }
        return this;
    }
}
const x = new InlineMath(3);
x.factorial().factorial();
console.log(x);

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2
Solution 3 Mulan