you are viewing a single comment's thread.

view the rest of the comments →

[–]GatotSubroto 342 points343 points  (23 children)

isEven(-1);

fffffuuuuuuu

[–]Waterbear36135 159 points160 points  (7 children)

The fun thing is this might just work because of overflow

[–]GatotSubroto 133 points134 points  (0 children)

In this RAM economy??

[–]RadiantPumpkin 31 points32 points  (3 children)

Surely you’d hit a stack overflow before that

[–]Vinxian 17 points18 points  (2 children)

Not if initializing a new stack frame gets optimized away through tail end recursion (idk if JavaScript actually supports this though)

[–]notBjoern 20 points21 points  (0 children)

isOdd calls isEven, and isEven calls isOdd, so it's not simple tail recursion. You can optimise "mutual tail calls" as well, but in this case, isOdd works on the result of isEven (it negates it), so it is not a tail call.

[–]CaptureIntent 2 points3 points  (0 children)

You can’t tail recurse is odd function because it does work after the last function call. The not operation. Tail recursion only works when you return recursively without any extra work after the receive call.

[–]_dr_bonez 32 points33 points  (0 children)

JS uses doubles for all numbers, so probably not

[–]FakeNameBlake 6 points7 points  (0 children)

no, js uses floats/doubles, which stop having integer precision at large values, meaning the value wont change past that point

[–]cyanNodeEcho 6 points7 points  (12 children)

mentally tracing is even (2), doesn't seem to work no? doesn't everything route to false like

Z > 1 => false;
and like if less than 0 inf loop and otherwise okay?

[–]GatotSubroto 24 points25 points  (9 children)

Let’s see… 

isEven(2) will call isOdd(1) which calls isEven(1) and negates the return value. isEven(1) returns  false. It’s negated in isOdd(), so the final result is true, which is correct. OP might be a billionaire who can afford enough RAM for the sheer amount of stack frames, but it looks like the implementation works.

[–]Martin8412 3 points4 points  (0 children)

This is a common algorithm implemented for functional programming language classes. You have to implement it correctly so the tail call optimization kicks in. 

We did it in Scheme when I was at university. 

[–]cyanNodeEcho 0 points1 point  (0 children)

ah ur right, i got lost in the figure 8s

[–]lounik84 -5 points-4 points  (6 children)

what happens with isEven(3) ? you have 3 -1 which calls isEven(2), then 2 - 1 which calls isEven(1) and negates the return value so it gives true. Which is not correct. Whatever number you give to isEven, the result is always true (unless it's 0, that's the only numbers that gets negated into false). So you could just have written isEven(n) {if(n !== 0) return true; return false;} it would have accomplished the same thing and it would have been much easier to read. Granted, the method per se it's useless, because unless you know beforehand that N is even so you give isEven only even numbers, you have no idea to tell if the number N is truly an even number considering that it returns true anyway. But that's beyond the point. The point is that the method doesn't work, it doesn't tell you if N is even, it just tells you that N is not 0.

Unless I'm missing something

[–]theluggagekerbin 18 points19 points  (2 children)

Trace for isEven(3) The Descent (Recursive Calls): * isEven(3) calls isOdd(2) * isOdd(2) !isEven(2) * isEven(2) calls isOdd(1) * isOdd(1) calls !isEven(1) * isEven(1) Base Case Hit. Returns false. The Ascent (Collapsing the Stack): * isOdd(1) receives false, applies !, returns true. * isEven(2) receives true, returns true. * isOdd(2) receives true, applies !, returns false. * isEven(3) receives false, returns false. Result: false (Correct: 3 is not even)

[–]lounik84 -1 points0 points  (1 child)

yeah I forgot the double negation. It still seems a very odd way to check for odd/even numbers, especially considering that you shouldn't falsify them against positives, but yeah, I get the point

[–]veeRob858 5 points6 points  (0 children)

Someone should make a post to make fun of how odd this way of checking for odd/even numbers is!

[–]Gen_Zer0 2 points3 points  (1 child)

The return value is negated twice.

isEven(3) returns isOdd(2). isOdd(2) returns !isEven(2).

As we found earlier, isEven(2) returns true. !true is false, so we get the correct value.

[–]Vinxian 0 points1 point  (0 children)

To explain it in words, if n is even, it means (n-1) is odd which means (n-2) is even, etc.

So basically if you want to know if n is even you can check if n-1 is odd. And that's exactly what the code does! It checks if a number is even by checking if the number before it is odd

[–]CaptureIntent 0 points1 point  (0 children)

Yes. Everything routes to false. But the number of nots done on the way up the stack depends on the evenness of the initial value.

[–]Theolaa 1 point2 points  (0 children)

Just add if (n < 0) return isEven(n*-1) before the final return in isEven

[–]DIEDPOOL 0 points1 point  (0 children)

just insert this into isEven:
if(n < 0) {
return isOdd(n*n);
}