This question is about an exercise in the book Eloquent JavaScript

Tags: , , ,



The last part to this exercise is to write a recursive function that takes two parameters, a joined list and an index respectively. The function will find the value in the object within the list at it’s respective index. The code i have written works the way i want (i can see it working when i console.log for every occasion the function is called. But on the last occasion it refers undefined as my value. I cannot understand why. Oh and it works for index of 0. code as followed.

and first, list looks like this:

list = {
    value: 1,
    rest: {
        value: 2,
        rest: {
            value: 3,
            rest: null
            }
        }
    };



   const nth = (list, targetNum) => {
   let value = Object.values(list)[0];
   if (targetNum == 0) {
       return value;
   } else {
       targetNum = targetNum -1;
       list = Object.values(list)[1];
    //    console.log(value);
    //    console.log(targetNum);
    //    console.log(list);
       nth(list, targetNum);
   }
};
console.log(nth(arrayToList([1,2,3]),2)); 

below is the code for arrayToList it was the first part of the exercise and if you have any comments that’s cool, cause the hints ended up suggesting to build the list from the end.

const arrayToList = (arr) => { 
    let list = {
        value: arr[0],
        rest: nestObject()
    };
    function nestObject() {
        let rest = {};
        arr.shift();
        const length = arr.length;
        if (length == 1) {
            rest.value = arr[0];
            rest.rest = null;
        } else {
            rest.value = arr[0];
            rest.rest = nestObject();
        }
        return rest;   
    }
    return list;
};

Answer

You simply need to add a return when recursively calling nth. Otherwise the logic is carried out but no value is returned (unless targetNum is 0)

const nth = (list, targetNum) => {
   let value = Object.values(list)[0];
   if (targetNum == 0) {
       return value;
   } else {
       targetNum = targetNum -1;
       list = Object.values(list)[1];
       return nth(list, targetNum); // return needed here too
   }
};

Or more succinctly:

const nth = (list, n) => n === 0 ? list.value : nth(list.rest, n - 1)

Here’s another non-recursive arrayToList that builds the list from the end:

const arrayToList = arr => arr.slice().reverse().reduce((rest, value) => ({value, rest}), null);

(The slice here is just to make a copy of the array so that the original is not reversed in place.)



Source: stackoverflow