6

The general question I suppose is: when does || return the item on the left, and when does it return the item on the right?

The specific question, is why doesn't this work:

var fibonacci = (function () {

    var cache = [0, 1];

    function fibonacci(number) {
        return cache[number] = cache[number] || (fibnonacci(number - 1) + fibonacci(number - 2));
    }

    return fibonacci;
})();

var $div = $('div');

for (var index = 0; index < 10; index++) {
    $('<span />').text(fibonacci(index))
        .appendTo($div);
}
sircodesalot
  • 11,231
  • 8
  • 50
  • 83

3 Answers3

13

It returns the item on the left if and only if it is truthy.

The following are not truthy:

  • The primitive boolean value false
  • The primitive string value "" (the empty string)
  • the numbers +0, -0 and NaN
  • the primitive value null
  • the primitive value undefined

Everything else is truthy.

Here is the list on the language specification.

In your case cache[0] returns 0 which as we can see is falsy so it enters recursion. This is why we avoid || for short circuiting in these situations.

You should consider checking directly that the object has that property: number in cache is one such way and another is cache[number] !== undefined.

Benjamin Gruenbaum
  • 270,886
  • 87
  • 504
  • 504
  • Shouldn't cache[0] return a value then? For some reason it just gives me a StackOverflow (tm). – sircodesalot Aug 03 '13 at 18:56
  • 1
    @sircodesalot Because `cache[0]` is `0` which is falsy and so it goes into an infinite recursion (because `cache[x]` for negative `x` is `undefined`, i.e. falsy as well). – freakish Aug 03 '13 at 18:59
  • 1
    @sircodesalot no, fibonacci(0) is falsy which means it calls the recursion. This is _exactly_ why we avoid `||` (and more generally 'truthyness') in these situations. Just use `cache[number]===undefined` – Benjamin Gruenbaum Aug 03 '13 at 18:59
  • @BenjaminGruenbaum As I've mentioned the real problem is not that `cache[0]` is falsy but rather that `cache[x]` for negative `x` is falsy hence the infinite recursion. – freakish Aug 03 '13 at 19:03
  • @freakish Right, but we only check cache[x] for negative x _because_ cache[0] is falsy. If it wasn't falsy we wouldn't be in that position in the first place (like you mention in your comment) :) – Benjamin Gruenbaum Aug 03 '13 at 19:04
1

Your code doesn't work because you can't use the value in cache when it's 0 as 0 || func() asks for the function to be called.

So it always call the second term for 0 and thus makes a stack overflow as the recursion has no end.

A solution would be to change your internal function like this :

function fibnonacci(number) {
    if (number in cache) return cache[number];
    return cache[number] = fibnonacci(number - 1) + fibonacci(number - 2);
}

As an aside please note the spelling of Fibonacci.

Denys Séguret
  • 372,613
  • 87
  • 782
  • 758
0

It returns the first true from the left. If no true it returns false. If the expressions resolve to true, in case of a Boolean or a non-zero or non-null or non-undefined value.

Edit:

Yes, the value has to be truthy...not only true.

Vivek Jain
  • 3,811
  • 6
  • 30
  • 47