3

Here is the problem. I have to implement make function:

var sum = function (a, b) { return a + b; }
var mult = function (a, b) { return a * b; }

//'make' function goes here

var res = make(1)(2)(3)(4);

console.log(res(sum));    //OUTPUT: 10
console.log(res(mult));   //OUTPUT: 24

I have implemented it, but I feel like a little better way still exists. :)

So, here is my solution:

function make(a, arr) {
    if (a instanceof Function) { return arr.reduce(a); }

    arr = arr || [];
    arr.push(a);

    return function (b) { return make(b, arr); };
}
4
  • 1
    The task is pertty bad. It forces you to inspect the argument and check whether it's a function or not. That's pretty un-functional in my opinion Commented Mar 12, 2014 at 19:37
  • @NiklasB. yes, at least once. At the end of recursion. But the task is the task) Commented Mar 12, 2014 at 19:38
  • I think the last edit you made is probably the best way to do it. Commented Mar 12, 2014 at 19:57
  • What is the output of make(1)(sum)? Consider var comp = (f,g) => x => f(g(x)); and var res = make(x => x *2)(x => x + 1) then res(comp)(3). The expected output is 8 but it is impossible with your sugary, sweet function. Attempting to implement this is a fool's errand. Commented Mar 13, 2016 at 16:53

3 Answers 3

3

You want functions? You can have functions!

function sum(a, b) { return a + b; }
function mult(a, b) { return a * b; }
function diff(a, b) { return a - b; }

function make(x, f) {
    if (typeof x === 'function') return f(x);
    return function(y) { 
        return make(y, function(a) { 
            return f ? a(f(a), x) : x; 
        });
    };
}

console.log(make(1)(2)(3)(4)(sum));   // -> 10
console.log(make(1)(2)(3)(4)(mult));  // -> 24
console.log(make(4)(3)(2)(1)(diff));  // -> -2

Instead of building up an array, this builds up a function that, when given a function, reduces all the elements using that function, from left to right :)

I'm pretty sure this wouldn't qualify as code that anyone would ever want to see in their codebase.

Sign up to request clarification or add additional context in comments.

6 Comments

I wonder if testing typeof x is better than testing for a call property. No strong opinion, just a thought.
@kojiro: I don't know Javascript, I just copied OP's check. Feel free to edit
@NiklasB. I think, "arrays" solution is a little easier to understand. But I like your code. It is just great. Have you enjoyed the question? :)
I usually program in Haskell, so it was not too much of a challenge. In fact it reminded me of how horrible the Javascript syntax makes this kind of stuff look. JS has some nice functional features but just cruel syntax to express them.
IMO, single letter naming convention makes the code less readable.
|
0
function make(inp, arr) {
  if (typeof inp == 'function') {
    while(arr.length > 1)
      arr.push(inp(arr.pop(), arr.pop()));
    return arr[0];
  }

  if (!arr) arr = [];
  arr.push(inp);
  return function (inp1) {
    return make(inp1, arr);
  };
}

1 Comment

@NiklasB. I was in the process of making it smaller - when I noticed an update to the page. I just changed the part where the "inp" method was being evaluated. I posted the update to actually see the change and saw what he did and then posted a comment on his update.
0

Here's a better JavaScript specific solution:

var test = make(1)(2)(3)(4);

alert(test(add)); // ((1 + 2) + 3) + 4 = 10
alert(test(mul)); // ((1 * 2) * 3) * 4 = 24
alert(test(sub)); // ((1 - 2) - 3) - 4 = -8

function make(x) {
    if (typeof x !== "function") return foldl([x]);
    throw new TypeError("Initial value can't be a function");
}

function foldl(array) {
    return function (fx) {
        return typeof fx !== "function" ?
            foldl(array.concat(fx)) :
            array.reduce(fx);
    };
}

function add(a, b) { return a + b; }
function mul(a, b) { return a * b; }
function sub(a, b) { return a - b; }

There are several advantages to this method:

  1. Better error reporting when you write incorrect code like make(add).
  2. Simple functional definition which is easy to read and understand.
  3. If you want foldr then just rename reduce to reduceRight.
  4. Using concat instead of push to preserve original array.

I can't think of a better functional implementation for make.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.