Factorialize a Number (good day, can someone please explain this functionception?)

Tell us what’s happening:
so the Hint code is this:

function factorialize(num) {
  if (num === 0) { return 1; }
  return num * factorialize(num-1);
}

factorialize(5);

my code uses a for loop, for the love of me I can’t grapple with the functionception concept, can you please break it down for me or please point me towards the right keywords to google because even though I haven’t tried it, I don’t think functionception will be helpful. I really don’t get this, it’s calling a function inside a function that is the same function O.O even if I think "okay, so it’s basically num * num -1 which makes sense, I just don’t get how you call a function inside a similar function O.O is this normal? Sorry, JS is my first language (I’m not sure if html/css) counts and this is really just blowing my mind.

Your code so far


function factorialize(num) {
  let total = 1;
  for (let i = 1; i <= num; i++) {
    //let num2 = i;
    total = total * i ;
    //console.log(num + " num");
    console.log(total + " total");
    //console.log(num2 + " num2" );
  }
  return total;
}

factorialize(5);

Your browser information:

User Agent is: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36.

Link to the challenge:
https://learn.freecodecamp.org/javascript-algorithms-and-data-structures/basic-algorithm-scripting/factorialize-a-number

Try googling ‘recursive functions in javascript’.

1 Like

Okay I will do just that :slight_smile: thanks!

So it looks like you have stumbled upon recursion! Most of the time I’m using recursion, it’s in prolog so I’ll try and keep my explanation relevant to JavaScript. Recursion is a technique where you can recursively define a function with itself. Now, this by itself will leave you with a few problems. The biggest is that if you define a function with itself, how are you supposed to know/determine when the function stops?
Here’s a simple example:

function foo(x){
    y = x + 1;
    console.log(y);
    foo(y);
}

This function takes some number, and adds 1 to it infinitely(or at least until you run out of stack space).
In order to determine a stopping point, you need to add a base case.

function foo(x){
   if(x > 5){
    return x
    }
    y = x + 1;
    console.log(y);
    foo(y);
}

This is now equivalent to:

function foo(x){
    while(y < 5){
        y = x + 1;
        console.log(y);
    }
}

I hope this explanation cleared up some of your confusion.

Almost everything that can be defined recursively can also be created with a loop.

2 Likes

JavaScript supports tail call recursion so you can’t run out of stack space in K-log’s first example function and it will just loop forever.

On a side note functionception is a hilarious name for recursion and it gave me me a chuckle. We should just start calling it that.

1 Like

Thanks for pointing that out! Also, I agree we should start a petition to change recursion to functionception.

2 Likes

Fairly major clarification: to all intents and purposes, outside of the webkit environment, JS does not support it. No other engine supports proper tail calls (the few that did implement it have subsequently had it removed) and even in WK stack traces don’t really work. It is in the spec, but that doesn’t mean it’s actually implemented.

2 Likes

Good to know thanks, why do so so many people talk about JS supporting tail recursion if it isn’t implemented in most places?

Thanks for taking the time to explain this! :slight_smile:

Interestingly Safari gives a “Maximum call stack size exceeded” warning but it keeps running forever.
So it at least works in Safari and is implemented in webkit like DanCouper said.

I haven’t tried it on Edge or Firefox though.

Note: Safari actually eventually crashed so I can’t even confirm it works there.

It is in the ECMAScript 2015 spec, just vendors didn’t implement it because of technical issues (and no real need from users meaning there isn’t really any impetus to overcome those issues). There always seems to be ongoing talk about adding a keyword for recursive functions but it always seems to break down. Stuff that does allow tail call recursion and compiles to JS (OCaml & Haskell for example) always just rewrites the compiled JS output to while loops afaik.

I’ve never really seen it claimed as being supported outside of specific environments much though — like one version of Node, and sorta kinda possibly WebKit (maybe there is some compelling technical need to have it on mobile Safari, possibly? I dunno)

This is basically the canonical reference anyway:

http://kangax.github.io/compat-table/es6/

1 Like

It’s been 18 days, I just looked at your example again and I actually understand it. hahaha. would you look at that.

1 Like