Yinan Wang Yinan Wang - 7 months ago 20
Javascript Question

Return functions recursively to form nested functions - Javascript

I'm trying to build a function in JS that has a return composed of different nested functions based on a parameter passed by the user.

function addA(otherFunction)
{
//gets the result from some base function and modifies it
//e.g. +1
}

function addB(otherFunction)
{
//does the same thing as addA, except different values. Consider it a variation of addA.
//eg. -1
}

function constr(input)
{
//based on the chars in input, we will recursively select a new function to be applied.
//the value of this function should be a function
if (...) return addA(constr(shorterInput))
if (*last char) return addA
if (*last char) return addB
if (...) return addB(constr(shorterInput))
}


So far, my script is recognizing addA and and addB as functions. But when it strings two functions together, for example

addB(addA)


The type becomes undefined. Can anybody let me know why it does not register as a function and/or the proper way to return nested functions. Thanks!

Edit: Here is the real code:



function cons(a,b)
{
return function (selector) {
return selector(a,b);
};
}

function a(list)
{
function aHelper(a,b)
{
return a
}
return list(aHelper);
}

function d(list)
{
function dHelper(a,b)
{
return b
}
return list(dHelper);
}

function abc(input)
{
if (input.length==0 || input==null) return null;
var x=input.charAt(input.length-1);
if (x==='a')
{
if (input.length>1)
{
var z=a(abc(input.substr(0,input.length-1)));
return z;
}
return a;
}
if (x==='d')
{
if (input.length>1)
{
var z=d(abc(input.substr(0,input.length-1)));
return z;
}
return d;
}
}
function show(list) {
var sval;
if (list == null) return '()';
else if (typeof list!='string')
{
sval = '(' + show(a(list)) + ' ' + show(d(list)) + ')';
}
else
{
sval=list;
}
return sval;
}

var func=abc('ad');
var func2=abc('a');
var list=cons('a',cons('b','c'));
console.log(typeof func);
console.log(typeof func2);
console.log(typeof list);
console.log(typeof func2(list));
console.log(typeof func(list));




Answer

Your function abc is supposed to return a function that can process lists, like a or d. However, you match that signature only in 2 out of 7 cases:

  • return a, return d are fine
  • return null - that's not a callable value
  • z = d(…); return z does return a list
  • z = a(…); return a does return an element of the list (of whatever type)
  • d(abc(…)) and a(abc(…)) use abc as if it would return a list

A correct implementation would look like this:

function abc(directions) {
    if (directions.length == 0) {
       return function id(list) { return list; }; // a function that does nothing
    }
    var f = directions[0] == 'a' ? car : cdr; // ignoring other values, you might also throw an error
    var processRest = abc(input.slice(1));

    return function(list) { // make a function to process a list
        var z = f(list); // do the current operation
        return processRest(z); // do the rest of operations
    };
}

Or even better/shorter with the help of higher-order function composition:

function id(x) { return x; }
function compose(f, g) {
    if (f == id) return g;
    if (g == id) return f;
    return function(x) { return f(g(x)); };
}
function abc(dirs) {
    return !dirs.length ? id : compose(abc(dirs.slice(1)), dirs[0]=='a'?car:cdr);
}